--- /dev/null
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("1.1.2")]
+[assembly: AssemblyTitle ("Mono C# Compiler")]
+[assembly: AssemblyDescription ("Mono C# Compiler with Generics")]
+[assembly: AssemblyCopyright ("2001, 2002, 2003 Ximian, Inc.")]
+[assembly: AssemblyCompany ("Ximian, Inc.")]
--- /dev/null
+2004-12-12 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Unary.TryReduceNegative): Added support for
+ SByteConstant and ByteConstant.
+ (Unary.Reduce): Check error values from TryReduceNegative().
+
+2004-12-11 Martin Baulig <martin@ximian.com>
+
+ * support.cs (ReflectionParameters.ParameterName): If we have a
+ `gpd', call `ParameterName' on it.
+
+ * parameter.cs (Parameter.GetParameterAttributes): New static method.
+
+ * pending.cs (PendingImplementation.DefineProxy): Call
+ DefineParameter() for all of the MethodBuilder's arguments.
+
+2004-12-09 Martin Baulig <martin@ximian.com>
+
+ * doc.cs (DocUtil): Make this a static class.
+
+2004-12-09 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): Moved the type inference
+ implementation into TypeManager.
+
+ * generics.cs (TypeManager): Moved the type inference
+ implementation here.
+
+2004-12-09 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager): Make this a partial class.
+
+ * generics.cs
+ (TypeManager): Move the generics part of `TypeManager' here.
+
+2004-12-08 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.VerifyClsCompliance): Report a CS3003
+ instead of a CS3002 for properties and indexer. Added CS3024
+ check for generic interfaces.
+
+ * attributes.cs (AttributeTester.AnalyzeTypeCompliance): Generic
+ instances are not CLS-compliant.
+
+2004-12-08 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay
+ (void_pointer_expression): New rule for `void*', `void**' etc.
+ (typeof_expression): Add `void_pointer_expression'; fixes #66846.
+
+2004-12-08 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): Removed the hack for
+ MethodCore.MayUnify().
+
+ * typemanager.cs (TypeManager.MayBecomeEqualGenericTypes): Make
+ this actually work.
+
+ * class.cs (MethodCore.MayUnify): Use
+ TypeManager.MayBecomeEqualGenericTypes().
+
+2004-12-08 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Is.DoResolve, As.DoResolve): If we're a type
+ parameter, box it. Fixes #69233.
+
+2004-12-08 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Valuetypes always
+ have the ctor constraint. Fixes #68326.
+
+2004-12-07 Atsushi Enomoto <atsushi@ximian.com>
+
+ * cs-parser.jay : interface comment was not consumed because of
+ extra opt_semicolon before doc handling.
+
+2004-12-03 Raja R Harinath <rharinath@novell.com>
+
+ Fix test-327.cs, test-328.cs, and put in early infrastructure
+ for eventually fixing #52697.
+ * namespace.cs (NamespaceEntry.LookupForUsing): New method.
+ (NamespaceEntry.LookupNamespaceOrType): New method, refactored
+ from other methods.
+ (NamespaceEntry.Lookup): Remove 'ignore_using' flag.
+ (AliasEntry.Resolve, UsingEntry.Resolve): Use 'LookupForUsing'.
+ (VerifyUsing, error246): Update.
+ * rootcontext.cs (RootContext.NamespaceLookup): Just use
+ 'NamespaceEntry.LookupNamespaceOrType'.
+
+2004-12-07 Martin Baulig <martin@ximian.com>
+
+ * driver.cs: Call it "BETA SOFTWARE" :-)
+
+2004-12-06 Raja R Harinath <rharinath@novell.com>
+
+ Fix crash on cs0657-17.cs.
+ * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute):
+ Use RootContext.Tree.Types, not 'new RootTypes ()'.
+ * attribute.cs (GlobalAttribute.CheckAttributeType): Narrow down
+ the case where the NamespaceEntry gets overwritten.
+
+2004-12-06 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed #69195, #56821
+ * ecore.cs (ResolveBoolean): Tiny refactoring.
+
+ * expression.cs (Binary.DoResolve): Add warning 429 and skipping
+ of right expression resolving when left is false constant and
+ operator is LogicalAnd OR true constant and operator is LogicalOr.
+
+ * statement.cs (ResolveUnreachable): Always reports warning.
+
+2004-12-05 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs: Distinguish between 1721 and 1722 (just a little help
+ for the programmer).
+
+2004-12-03 Miguel de Icaza <miguel@ximian.com>
+
+ * delegate.cs: Only allow this on new versions of the language.
+
+2004-12-02 Duncan Mak <duncan@ximian.com>
+
+ * ecore.cs (PropertyExpr.IsAccessorAccessible): Moved to
+ Expression class.
+ (Expression.IsAccessorAccessible): Moved from the PropertyExpr to
+ here as a static method. Take an additional bool out parameter
+ `must_do_cs1540_check' for signaling to InstanceResolve.
+ (PropertyExpr.InstanceResolve): Removed the `must_do_cs1540_check'
+ member field from PropertyExpr class and made it an argument of
+ the method instead.
+ (EventExpr.InstanceResolve): Copied from PropertyExpr, removed the
+ check for MarshalByRefObject, and report CS0122 instead of CS1540.
+ (EventExpr.DoResolve): Call IsAccessorAccessible on `add_accessor'
+ and `remove_accessor' as well as InstanceResolve: report CS0122
+ where applicable.
+
+ Fixes #70129.
+
+2004-12-07 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.AddToContainer): Report correct errors CS0694
+ and CS0692 where appropriate.
+
+2004-12-06 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodCore.MayUnify): Moved the CS0408 check here from
+ IsDuplicateImplementation() and improved it.
+
+ * expression.cs (Invocation.InferTypeArguments): Added
+ `Type[] inferred_class_types' argument (for MethodCore.MayUnify)
+ and removed the "ref" modifier from `infered_types'.
+
+ * decl.cs (MemberName.ToString): Removed the exception.
+
+2004-12-03 Atsushi Enomoto <atsushi@ximian.com>
+
+ * cs-tokenizer.cs : Only '////' is rejected. Other non-whitespace
+ comments are allowed.
+
+2004-12-03 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * delegate.cs: Add checks for subtypes in paramaters and return values
+ in VerifyMethod () to add support for Covariance/Contravariance
+ in delegates.
+
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * report.cs: Remove extra closing parenthesis.
+
+ * convert.cs (Error_CannotImplicitConversion): If the name of the
+ types are the same, provide some extra information.
+
+2004-12-02 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #70102
+ * attribute.cs (Resolve): Improved implementation of params
+ attribute arguments.
+
+ * support.cs (ParameterData): Add HasParams to be faster.
+
+2004-12-02 Atsushi Enomoto <atsushi@ximian.com>
+
+ all things are for /doc support:
+
+ * doc.cs: new file that supports XML documentation generation.
+ * mcs.exe.sources: added doc.cs.
+ * driver.cs:
+ Handle /doc command line option.
+ Report error 2006 instead of 5 for missing file name for /doc.
+ Generate XML documentation when required, after type resolution.
+ * cs-tokenizer.cs:
+ Added support for picking up documentation (/// and /** ... */),
+ including a new XmlCommentState enumeration.
+ * cs-parser.jay:
+ Added lines to fill Documentation element for field, constant,
+ property, indexer, method, constructor, destructor, operator, event
+ and class, struct, interface, delegate, enum.
+ Added lines to warn incorrect comment.
+ * rootcontext.cs :
+ Added Documentation field (passed only when /doc was specified).
+ * decl.cs:
+ Added DocComment, DocCommentHeader, GenerateDocComment() and
+ OnGenerateDocComment() and some supporting private members for
+ /doc feature to MemberCore.
+ * class.cs:
+ Added GenerateDocComment() on TypeContainer, MethodCore and Operator.
+ * delegate.cs:
+ Added overriden DocCommentHeader.
+ * enum.cs:
+ Added overriden DocCommentHeader and GenerateDocComment().
+
+2004-12-01 Miguel de Icaza <miguel@ximian.com>
+
+ * cfold.cs (ConstantFold.DoConstantNumericPromotions): After
+ unwrapping the enumeration values, chain to
+ DoConstantNumericPromotions again, so we can promote things to the
+ fundamental types (takes care of enums that are bytes, sbytes).
+
+ Fixes bug #62054.
+
+2004-12-01 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType): Remove complain flag.
+ Fix long-standing bug in type-lookup. Use FindType instead of
+ LookupType when ec.ResolvingTypeTree.
+ (Attribute.ResolveType, Attribute.Resolve)
+ (Attribute.DefinePInvokeMethod,GlobalAttribute.CheckAttributeType):
+ Update to changes.
+ (Attributes.Search): Remove internal version. Update.
+ (Attributes.SearchMulti): Update.
+ (Attributes.GetClsCompliantAttribute): Remove.
+ (Attributes.GetIndexerNameAttribute): Remove.
+ * decl.cs (MemberCore.GetClsCompliantAttributeValue): Update to changes.
+ (DeclSpace.GetClsCompliantAttributeValue): Likewise.
+ * class.cs (Indexer.Define): Likewise.
+
+2004-12-01 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #68790
+ * ecore.cs: CheckMarshallByRefAccess new virtual method for testing
+ MarshallByReference members access.
+
+ * expression.cs: Use CheckMarshallByRefAccess;
+ Better error CS0197 message.
+
+ * report.cs: Print whole related error message.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ * class (GetClassBases): Better error 60 report.
+ (EventProperty): Disabled warning 67 detection.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #60324
+ * cfold.cs (Assign.DoResolve): Add subtraction for DecimalConstant.
+
+ * constant.cs (DecimalConstant.Emit): Don't use int ctor for
+ precise values.
+
+2004-11-29 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #49488
+ * assign.cs (Assign.DoResolve): Add error 1648, 1650 report.
+
+ * decl.cs (MemberCore.MemberName): Error 1648 in compiler.
+
+2004-11-26 Miguel de Icaza <miguel@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): Refine error reporting and
+ report a cs0117 if the identifier does not exist, to distinguish
+ from 0617 which is a miss-use of the actual identifier.
+
+ * ecore.cs (EventExpr.Emit): Refine error report and distinguish
+ between cs0070 and cs0079.
+
+ * class.cs (MemberBase.DoDefine): When reporting a wrong
+ accessibility level, we use MethodCore to compare instead of
+ Method (this was a regression in some refactoring effort).
+
+ So now we correctly report cs0056 again.
+
+ * convert.cs (ImplicitReferenceConversion): Corrected typo, I was
+ testing the target_type (which was known to be object_type) and
+ not the source type (which is anonymous_method).
+
+ Fixed reporting of error cs1660.
+
+ * expression.cs (UserCast.Source): Expose the underlying cast.
+
+ * statement.cs (Switch.SwitchGoverningType): Sort the list of
+ allowed types to find a match to int32 first (most common).
+
+ In addition, it ignores any ImplicitUserConversions that did an
+ internal implicit conversion (as the switch statement allows only
+ one integral conversion to exist).
+
+ * class.cs (PartialContainer.Create): rename `name' to
+ `member_name' for clarity. Then replace the string calls with a
+ call to MemberName.GetPartialName, as now using
+ MemberName.ToString is an error (this is due to the side effects
+ it had, that were fixed in the past).
+
+ This will restore the error reporting on a number of partial class
+ errors that were missusing this (and getting an exception as a
+ results, which is now just a plain textual warning, because
+ yyparse debug output would crash otherwise).
+
+2004-11-26 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (PROGRAM_INSTALL_DIR): Remove.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * rootcontext.cs (LookupType): Make sure to cache lookups that
+ don't give us a negative result. This saves about 5% of corlib
+ compilation time.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * report.cs (AbstractMessage.Print): messages are sent to stderr
+
+ * class.cs (TypeContainer.GetClassBases): It is an error to have a
+ non-interface in the list of interfaces (at this point, either
+ parent was properly set, or a base class is being listed in the
+ interfaces section).
+
+ This flags error 1722, and resolves the crash from bug 69259.
+
+2004-11-25 Ben Maurer <bmaurer@ximian.com>
+
+ * statement.cs (Using.EmitExpressionFinally): make this work right
+ for valuetypes. Fixes 69926.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * const.cs (Const.ChangeType): Cope with the "0 literal can be
+ converted to an enum" here, before we try to change the underlying
+ type. This code exists, but it is a different code path than the
+ one used while encoding constants.
+
+ (ImplicitReferenceConversionExists): In addition, resynchronized
+ the code here, so it matches the same code in
+ ImplicitReferenceConversionExists for the `from any class-type S
+ to any interface-type T'.
+
+2004-11-25 Marek Safar <marek.safar@seznam.cz>
+
+ * cfold.cs (BinaryFold): Add addition for DecimalConstant.
+
+2004-11-24 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Use verbosity accordingly.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Unary.ResolveOperator): Do not report warning;
+ AddressOf reads from variable.
+
+ (LocalVariableReferences.DoResolveBase): Improved my previous fix.
+
+2004-11-24 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69462
+
+ * attribute.cs (Attributable): Removed CheckTargets.
+ (Attributes.Emit): Explicit attribute targets are tested here.
+
+ * class.cs (EventField.ValidAttributeTargets): Explicit target "field" is
+ not enabled for interfaces.
+
+ * codegen.cs (CommonAssemblyModulClass.AddAttributes): Removed CheckTargets.
+ (GetAssemblyName): Ouch next bug there.
+
+2004-11-23 Carlos Alberto Cortez <calberto.cortez@gmail.com>
+
+ * expression.cs: Error 275 added.
+
+2004-11-23 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #69177 (Implemented decimal constant support)
+
+ * cfold.cs (DoConstantNumericPromotions: Add DecimalConstant.
+ (BinaryFold): Add DecimalConstant.
+
+ * const.cs (Define): Decimal constant
+ (is not constant.
+ (ChangeType): Add decimal type handling.
+ (LookupConstantValue): Don't set value for decimal type but
+ emit DecimalConstantAttribute. Needed for constant optimization.
+
+ * constant.cs (ToDecimal): New method.
+ (ConvertToDecimal): New method.
+ (IntConstant): Implemented ConvertToDecimal.
+ (DecimalConstant.Emit): Emit optimized version for decimals in
+ int range.
+
+ * expression.cs (ResolveOperator): Changed order of constant
+ reduction to work correctly with native types which have
+ overloaded operators.
+ (ResolveMemberAccess): Extract constant value from attribute
+ for decimal type.
+
+ * rootcontext.cs (ResolveCore): Add DecimalConstantAttribute.
+
+ * typemanager.cs (TypeManager): Add decimal_constant_attribute_type,
+ void_decimal_ctor_int_arg, decimal_constant_attribute_ctor.
+ (ChangeType): Decimal is special.
+ (TypeToCoreType): Add decimal type.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * convert.cs (ImplicitConversionRequired): Add error cs0642 for
+ decimal types.
+
+2004-11-22 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (EventField.ApplyAttributeBuilder): Fix error
+ test cs1667-5.cs.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MemberBase.DoDefine): Fix error cs0508 report.
+
+ * pending.cs (PendingImplementation): Grab only interfaces.
+
+2004-11-19 Marek Safar <marek.safar@seznam.cz>
+
+ * statement.cs (ForeachHelperMethods): Add location member and
+ error 202 detection.
+
+2004-11-18 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (DoResolveBase): Fixed wrong warning for out
+ variables.
+
+2004-12-04 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.TypeParameter_to_Null): Use the constraints
+ to check whether the conversion is ok.
+
+ * typemanager.cs (TypeManager.GetTypeArguments): Just return
+ `Type.EmptyTypes' if we're not a generic TypeContainer.
+
+2004-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ImplicitReferenceConversionExists): A surprisingly
+ old bug: when converting from the null literal to a pointer,
+ return an EmptyCast, not the NullLiteral.
+
+ This fixes #69921, the recent null_type changes probably made this
+ bug more prominent.
+
+2004-12-03 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, call AnonymousMethod.Compatible() on it.
+
+2004-12-02 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (FieldBase): Use an unused bit field from the field to
+ encode the `has_offset' property from the FieldMember. This saves
+ a couple of Ks on bootstrap compilation.
+
+ * delegate.cs (NewDelegate.DoResolve): If we have an anonymous
+ method as our child, return the AnonymousMethod resolved
+ expression.
+
+ * expression.cs (New.DoResolve): Allow return values from
+ NewDelegate to also include AnonymousMethods.
+
+ Fixes #70150.
+
+2004-11-29 Raja R Harinath <rharinath@novell.com>
+
+ * decl.cs (MemberCore.MemberName): Remove readonly to fix an error
+ cs1648 report.
+ * rootcontext.cs (ResolveCore::interfaces_first_stage): Add
+ System.Runtime.InteropServices._Exception, since it's a base
+ interface of the core type System.Exception in the net_2_0 profile.
+
+2004-11-27 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (Expression.StoreFromPtr): Use `stobj' for generic parameters.
+
+2004-11-26 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile: Convert to use executable.make.
+ * gmcs.exe.sources: New.
+
+2004-11-25 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): Added support for byref types.
+
+2004-11-25 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Foreach.FetchMethodMoveNext): Wrap `mi.ReturnType'
+ in TypeManager.TypeToCoreType().
+
+2004-11-25 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs (Iterator.DoDefineMembers): Override and lookup the
+ "Dispose" method from the `current_type'.
+ (Iterator.EmitMoveNext): Use the `dispose_method' we looked up in
+ DoDefineMembers() instead of using the MethodBuilder; this is
+ required for generic iterators.
+
+ * class.cs (TypeContainer.DoDefineMembers): Make this virtual.
+
+2004-11-24 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (Expression.LoadFromPtr): Use `ldobj' for generic parameters.
+
+2004-11-20 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): Correctly infer generic
+ instances; see gen-103.cs.
+ (Invocation.InferTypeArguments): If a generic method doesn't have
+ any unbound type parameters, we don't need to infer anything.
+
+2004-11-19 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (gmcs.exe): Update to new location of bootstrap mcs.exe.
+
+2004-11-17 Raja R Harinath <rharinath@novell.com>
+
+ * typemanager.cs (TypeHandle.GetTypeHandle): Make private.
+ (TypeHandle.GetMemberCache): New.
+ (TypeHandle.TypeHandle): Update.
+ (TypeManager.LookupMemberCache): Rewritten from LookupMemberContainer.
+ (TypeManager.LookupParentInterfacesCache):
+ Rename from LookupInterfaceCache. Optimize slightly.
+ (TypeManager.MemberLookup_FindMembers): Update.
+ * decl.cs (MemberCache.MemberCache): Set Container to null in the
+ multi-type variant.
+ (AddCacheContents): Rename from AddHashtable.
+ * class.cs (TypeContainer.parent_container): Remove.
+ (TypeContainer.VerifyClsCompliance): Don't use parent_container.
+ (TypeContainer.DoDefineMembers): Don't initialize it.
+ Update to name changes.
+
+2004-11-17 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (MethodCore.CheckAccessModifiers): New helper routine
+ that factors the code to check access modifiers on override.
+
+ (PropertyBase): Use the code here.
+
+ Patch from Lluis S'anchez, fixes bug #69361.
+
+2004-11-15 Miguel de Icaza <miguel@ximian.com>
+
+ * anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New
+ routine that is used to report the use of a captured variable
+ whose address has been taken.
+
+ There are two checks: one when variables are being captured and
+ the other check is when the address of a variable is taken.
+
+ (because an anonymous methods might be resolved before *or* after
+ the address has been taken) and
+
+ * expression.cs (Conditional.DoResolve): Remove the special
+ casing that Martin added to trueExpr and falseExpr being both
+ NullLiteral. We get the right behavior now just by introducing
+ the null_type into the compiler.
+
+ * convert.cs (ExplicitConversion): Change the code to use
+ null_type instead of testing `expr is NullLiteral'.
+ (ImplicitConversionStandard): use null_type too.
+ (ImplicitReferenceConversionExists): use null_type too.
+ (ImplicitReferenceConversion): use null_type too.
+
+ * literal.cs: The type of `NullLiteral' is now null_type instead
+ of object_type.
+ (Resolve): Set the type here.
+
+ * typemanager.cs: Introduce null_type.
+
+2004-11-18 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs
+ (RootContext.LookupType): Return a `Type', not a `TypeExpr'.
+
+2004-11-18 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (TypeExpr.DoResolveAsTypeStep): Make this protected.
+
+2004-11-18 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (Constraints.Resolve): Take an `EmitContext' instead
+ of a `DeclSpace'. If one of our constraints is a `ConstructedType',
+ call ResolveConstructedType() on it to resolve it without checking
+ constraints.
+ (Constraints.ResolveTypes): Check them here.
+ (ConstructedType.DoResolveAsTypeStep): Fully resolve ourselves,
+ but don't check constraints.
+ (ConstructedType.ResolveAsTypeTerminal): Override this and also
+ check constraints here.
+ (ConstructedType.ResolveConstructedType): New public method. This
+ is called from DoResolveAsTypeStep() and Constraints.Resolve() to
+ resolve ourselves without checking constraints.
+
+ * ecore.cs (Expression.ResolveAsTypeTerminal): Make this virtual.
+
+2004-11-18 Martin Baulig <martin@ximian.com>
+
+ * decl.cs
+ (DeclSpace.CurrentType): Changed type from `TypeExpr' to `Type'.
+
+ * delegate.cs (Delegate.DefineType): Always create the EmitContext.
+
+2004-11-18 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (TypeExpr.ResolveType): Removed.
+ (Expression.ResolveAsTypeTerminal): We always return a fully
+ resolved `TypeExpr', so we can just access its `Type'.
+
+ * class.cs (TypeContainer.DefineType): Resolve `CurrentType' here.
+
+2004-11-17 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (IAlias.Type): Replaced with ResolveAsType() to make
+ sure we don't return any unresolved TypeExpr's.
+ (TypeAliasExpression): The .ctor now takes an `IAlias' instead of
+ a `TypeExpr'.
+ (Expression.ResolveAsTypeTerminal): Make sure `te.Type != null'.
+
+ * expression.cs (MemberAccess.ResolveAsTypeStep): Don't return any
+ unresolved `ConstructedType's.
+
+2004-11-17 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (TypeExpr.ResolveType): Don't make this virtual.
+
+2004-11-17 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs
+ (Expression.ResolveAsTypeTerminal): Removed the `bool silent' argument.
+
+ * decl.cs (DeclSpace.ResolveType): Removed.
+ (DeclSpace.ResolveTypeExpr): Removed the `bool silent' argument.
+
+2004-11-17 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCache.AddHashtable): Add entries in the opposite
+ direction, like FindMembers() does. Fixes #69546, testcase is in
+ test-315.cs.
+
+2004-11-16 Martin Baulig <martin@ximian.com>
+
+ This is based on a patch from Marek Safar, see bug #69082.
+ Fixes bugs #63705 and #67130.
+
+ * typemanager.cs (TypeManager.LookupInterfaceCache): New public
+ method; create a MemberCache for an interface type and cache the
+ result.
+
+ * decl.cs (IMemberContainer.ParentContainer): Removed.
+ (IMemberContainer.ParentCache): New property.
+ (MemberCache.SetupCacheForInterface): Removed.
+ (MemberCache..ctor): Added .ctor which takes a `Type[]'; use this
+ to create a cache for an interface's "parent".
+
+ * class.cs (TypeContainer.DoDefineMembers): Setup cache for
+ interfaces too.
+
+2004-11-14 Ben Maurer <bmaurer@ximian.com>
+
+ * statement.cs: Avoid adding bools to a hashtable.
+
+2004-11-15 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberName.GetPartialName): Removed, use GetTypeName() instead.
+
+2004-11-11 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.GetMethodName): New method.
+
+ * class.cs (MethodData.Define): Include the generic arity in the
+ name of an explicit interface; also add it to the method name.
+
+ * pending.cs (PendingImplementation.InterfaceMethod): The method
+ name now includes the generic arity.
+
+2004-11-07 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Invocation.OverloadResolve): Flag error if we are
+ calling an unsafe method from a safe location.
+
+2004-11-06 Marek Safar <marek.safar@seznam.cz>
+
+ Fix #69167
+ * codegen.cs (ApplyAttributeBuilder): Do not return; it is only warning.
+
+2004-11-06 Miguel de Icaza <miguel@ximian.com>
+
+ * namespace.cs (VerifyUsing): use GetPartialName instead of
+ ToString.
+
+2004-11-05 Miguel de Icaza <miguel@ximian.com>
+
+ * statement.cs (Return.Resolve): Fix regression in typo: if
+ `in_exc', we have to request a NeedReturnLabel, this was a typo
+ introduced in the anonymous method check-in. Fixes #69131.
+
+ * Indexers were using the ShortName when defining themselves,
+ causing a regression in the compiler bootstrap when applying the
+ patch from 2004-11-02 (first part), now they use their full name
+ and the bug is gone.
+
+2004-11-04 Zoltan Varga <vargaz@freemail.hu>
+
+ * driver.cs: Strip the path from the names of embedded resources. Fixes
+ #68519.
+
+2004-11-04 Raja R Harinath <rharinath@novell.com>
+
+ Fix error message regression: cs0104-2.cs.
+ * namespace.cs (NamespaceEntry.Lookup): Remove 'silent' flag.
+ (AliasEntry.Resolve): Update.
+ * rootcontext.cs (RootContext.NamespaceLookup): Update. Remove
+ 'silent' flag.
+ (RootContext.LookupType): Update.
+
+2004-11-03 Carlos Alberto Cortez <carlos@unixmexico.org>
+
+ * cs-parser.jay: Add support for handling accessor modifiers
+ * class: Add support port accessor modifiers and error checking,
+ define PropertyMethod.Define as virtual (not abstract anymore)
+ * ecore.cs: Add checking for proeprties access with access modifiers
+ * iterators.cs: Modify Accessor constructor call based in the modified
+ constructor
+2004-11-02 Ben Maurer <bmaurer@ximian.com>
+
+ * expression.cs (StringConcat): Handle being called twice,
+ as when we have a concat in a field init with more than two
+ ctors in the class
+
+2004-11-02 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (Event.Define, Indexer.Define, Property.Define): Do not
+ special case explicit implementations, we should always produce
+ the .property or .event declaration.
+
+ * decl.cs (MemberName): Renamed GetFullName to GetPartialName
+ since it will not return correct data if people use this
+ unresolved in the presence of using statements (see test-313).
+
+ * class.cs (MethodData.Define): If we are an explicit interface
+ implementation, set the method name to the full name of the
+ interface plus the name of the method.
+
+ Notice that using the method.MethodName.GetFullName() does not
+ work, as it will only contain the name as declared on the source
+ file (it can be a shorthand in the presence of using statements)
+ and not the fully qualifed type name, for example:
+
+ using System;
+
+ class D : ICloneable {
+ object ICloneable.Clone () {
+ }
+ }
+
+ Would produce a method called `ICloneable.Clone' instead of
+ `System.ICloneable.Clone'.
+
+ * namespace.cs (Alias.Resolve): Use GetPartialName.
+
+2004-11-01 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Add error 1055 report.
+
+2004-11-01 Miguel de Icaza <miguel@ximian.com>
+
+ * assign.cs (Assign.DoResolve): Only do the transform of
+ assignment into a New if the types are compatible, if not, fall
+ through and let the implicit code deal with the errors and with
+ the necessary conversions.
+
+2004-11-01 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Add error 1031 report.
+
+ * cs-tokenizer.cs: Add location for error 1038.
+
+2004-10-31 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Add error 1016 report.
+
+2004-10-31 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Add errors 1575,1611 report.
+
+2004-10-31 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Add error 1001 report.
+
+2004-10-31 Marek Safar <marek.safar@seznam.cz>
+
+ Fix #68850
+ * attribute.cs (GetMarshal): Add method argument for
+ caller identification.
+
+ * class.cs, codegen.cs, enum.cs, parameter.cs: Added
+ agument for GetMarshal and RuntimeMissingSupport.
+
+2004-10-31 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (ExtractSecurityPermissionSet): Removed
+ TypeManager.code_access_permission_type.
+
+ * typemanager.cs: Removed TypeManager.code_access_permission_type.
+
+2004-10-27 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (LocalVariableReference.DoResolveLValue): Check
+ for obsolete use of a variable here. Fixes regression on errors
+ cs0619-25 and cs0619-26.
+
+2004-10-27 Marek Safar <marek.safar@seznam.cz>
+
+ Fix #62358, implemented security attribute encoding.
+
+ * attribute.cs (Attribute.CheckSecurityActionValididy): New method.
+ Tests permitted SecurityAction for assembly or other types.
+ (Assembly.ExtractSecurityPermissionSet): New method. Transforms
+ data from SecurityPermissionAttribute to PermisionSet class.
+
+ * class.cs (ApplyAttributeBuilder): Added special handling
+ for System.Security.Permissions.SecurityAttribute based types.
+
+ * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Added
+ special handling for System.Security.Permissions.SecurityAttribute
+ based types.
+
+ * enum.cs (ApplyAttributeBuilder): Added special handling
+ for System.Security.Permissions.SecurityAttribute based types.
+
+ * parameter.cs (ApplyAttributeBuilder): Added special handling
+ for System.Security.Permissions.SecurityAttribute based types.
+
+ * rootcontext.cs: Next 2 core types.
+
+ * typemanager.cs (TypeManager.security_permission_attr_type):
+ Built in type for the SecurityPermission Attribute.
+ (code_access_permission_type): Build in type.
+
+2004-10-17 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (LocalVariableReference.DoResolveBase, Emit):
+ Remove the tests for `ec.RemapToProxy' from here, and encapsulate
+ all of this information into
+ EmitContext.EmitCapturedVariableInstance.
+
+ * codegen.cs (EmitCapturedVariableInstance): move here the
+ funcionality of emitting an ldarg.0 in the presence of a
+ remapping. This centralizes the instance emit code.
+
+ (EmitContext.EmitThis): If the ScopeInfo contains a THIS field,
+ then emit a load of this: it means that we have reached the
+ topmost ScopeInfo: the one that contains the pointer to the
+ instance of the class hosting the anonymous method.
+
+ * anonymous.cs (AddField, HaveCapturedFields): Propagate field
+ captures to the topmost CaptureContext.
+
+2004-10-12 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (LocalVariableReference): Move the knowledge about
+ the iterators into codegen's EmitCapturedVariableInstance.
+
+2004-10-11 Miguel de Icaza <miguel@ximian.com>
+
+ * codegen.cs (EmitContext.ResolveTopBlock): Emit a 1643 when not
+ all code paths return a value from an anonymous method (it is the
+ same as the 161 error, but for anonymous methods).
+
+2004-10-08 Miguel de Icaza <miguel@ximian.com>
+
+ The introduction of anonymous methods in the compiler changed
+ various ways of doing things in the compiler. The most
+ significant one is the hard split between the resolution phase
+ and the emission phases of the compiler.
+
+ For instance, routines that referenced local variables no
+ longer can safely create temporary variables during the
+ resolution phase: they must do so from the emission phase,
+ since the variable might have been "captured", hence access to
+ it can not be done with the local-variable operations from the runtime.
+
+ * statement.cs
+
+ (Block.Flags): New flag `IsTopLevel' to indicate that this block
+ is a toplevel block.
+
+ (ToplevelBlock): A new kind of Block, these are the blocks that
+ are created by the parser for all toplevel method bodies. These
+ include methods, accessors and anonymous methods.
+
+ These contain some extra information not found in regular blocks:
+ A pointer to an optional CaptureContext (for tracking captured
+ local variables and parameters). A pointer to the parent
+ ToplevelBlock.
+
+ (Return.Resolve): Catch missmatches when returning a value from an
+ anonymous method (error 1662).
+ Invoke NeedReturnLabel from the Resolve phase instead of the emit
+ phase.
+
+ (Break.Resolve): ditto.
+
+ (SwitchLabel): instead of defining the labels during the
+ resolution phase, we now turned the public ILLabel and ILLabelCode
+ labels into methods called GetILLabelCode() and GetILLabel() that
+ only define the label during the Emit phase.
+
+ (GotoCase): Track the SwitchLabel instead of the computed label
+ (its contained therein). Emit the code by using
+ SwitchLabel.GetILLabelCode ().
+
+ (LocalInfo.Flags.Captured): A new flag has been introduce to track
+ whether the Local has been captured or not.
+
+ (LocalInfo.IsCaptured): New property, used to tell whether the
+ local has been captured.
+
+ * anonymous.cs: Vastly updated to contain the anonymous method
+ support.
+
+ The main classes here are: CaptureContext which tracks any
+ captured information for a toplevel block and ScopeInfo used to
+ track the activation frames for various local variables.
+
+ Each toplevel block has an optional capture context associated
+ with it. When a method contains an anonymous method both the
+ toplevel method and the anonymous method will create a capture
+ context. When variables or parameters are captured, they are
+ recorded on the CaptureContext that owns them, for example:
+
+ void Demo () {
+ int a;
+ MyDelegate d = delegate {
+ a = 1;
+ }
+ }
+
+ Here `a' will be recorded as captured on the toplevel
+ CapturedContext, the inner captured context will not have anything
+ (it will only have data if local variables or parameters from it
+ are captured in a nested anonymous method.
+
+ The ScopeInfo is used to track the activation frames for local
+ variables, for example:
+
+ for (int i = 0; i < 10; i++)
+ for (int j = 0; j < 10; j++){
+ MyDelegate d = delegate {
+ call (i, j);
+ }
+ }
+
+ At runtime this captures a single captured variable `i', but it
+ captures 10 different versions of the variable `j'. The variable
+ `i' will be recorded on the toplevel ScopeInfo, while `j' will be
+ recorded on a child.
+
+ The toplevel ScopeInfo will also track information like the `this'
+ pointer if instance variables were referenced (this is necessary
+ as the anonymous method lives inside a nested class in the host
+ type of the method).
+
+ (AnonymousMethod): Expanded to track the Toplevel, implement
+ `AnonymousMethod.Compatible' to tell whether an anonymous method
+ can be converted to a target delegate type.
+
+ The routine now also produces the anonymous method content
+
+ (AnonymousDelegate): A helper class that derives from
+ DelegateCreation, this is used to generate the code necessary to
+ produce the delegate for the anonymous method that was created.
+
+ * assign.cs: API adjustments for new changes in
+ Convert.ImplicitStandardConversionExists.
+
+ * class.cs: Adjustments to cope with the fact that now toplevel
+ blocks are of type `ToplevelBlock'.
+
+ * cs-parser.jay: Now we produce ToplevelBlocks for toplevel blocks
+ insteda of standard blocks.
+
+ Flag errors if params arguments are passed to anonymous methods.
+
+ * codegen.cs (EmitContext): Replace `InAnonymousMethod' with
+ `CurrentAnonymousMethod' which points to the current Anonymous
+ Method. The variable points to the AnonymousMethod class that
+ holds the code being compiled. It is set in the new EmitContext
+ created for the anonymous method.
+
+ (EmitContext.Phase): Introduce a variable and an enumeration to
+ assist in enforcing some rules about when and where we are allowed
+ to invoke certain methods (EmitContext.NeedsReturnLabel is the
+ only one that enfonces this right now).
+
+ (EmitContext.HaveCaptureInfo): new helper method that returns
+ whether we have a CapturedContext initialized.
+
+ (EmitContext.CaptureVariable): New method used to register that a
+ LocalInfo must be flagged for capturing.
+
+ (EmitContext.CapturedParameter): New method used to register that a
+ parameters must be flagged for capturing.
+
+ (EmitContext.CapturedField): New method used to register that a
+ field must be flagged for capturing.
+
+ (EmitContext.HaveCapturedVariables,
+ EmitContext.HaveCapturedFields): Return whether there are captured
+ variables or fields.
+
+ (EmitContext.EmitMethodHostInstance): This is used to emit the
+ instance for the anonymous method. The instance might be null
+ (static methods), this (for anonymous methods that capture nothing
+ and happen to live side-by-side with the current method body) or a
+ more complicated expression if the method has a CaptureContext.
+
+ (EmitContext.EmitTopBlock): Routine that drives the emission of
+ code: it will first resolve the top block, then emit any metadata
+ and then emit the code. The split is done so that we can extract
+ any anonymous methods and flag any captured variables/parameters.
+
+ (EmitContext.ResolveTopBlock): Triggers the resolution phase,
+ during this phase, the ILGenerator should not be used as labels
+ and local variables declared here might not be accessible to any
+ code that is part of an anonymous method.
+
+ Exceptions to this include the temporary variables that are
+ created by some statements internally for holding temporary
+ variables.
+
+ (EmitContext.EmitMeta): New routine, in charge of emitting all the
+ metadata for a cb
+
+ (EmitContext.TemporaryReturn): This method is typically called
+ from the Emit phase, and its the only place where we allow the
+ ReturnLabel to be defined other than the EmitMeta. The reason is
+ that otherwise we would have to duplicate a lot of logic in the
+ Resolve phases of various methods that today is on the Emit
+ phase.
+
+ (EmitContext.NeedReturnLabel): This no longer creates the label,
+ as the ILGenerator is not valid during the resolve phase.
+
+ (EmitContext.EmitThis): Extended the knowledge in this class to
+ work in anonymous methods in addition to iterators.
+
+ (EmitContext.EmitCapturedVariableInstance): This emits whatever
+ code is necessary on the stack to access the instance to a local
+ variable (the variable will be accessed as a field).
+
+ (EmitContext.EmitParameter, EmitContext.EmitAssignParameter,
+ EmitContext.EmitAddressOfParameter): Routines to support
+ parameters (not completed at this point).
+
+ Removals: Removed RemapLocal and RemapLocalLValue. We probably
+ will also remove the parameters.
+
+ * convert.cs (Convert): Define a `ConstantEC' which points to a
+ null. This is just to prefity some code that uses
+ ImplicitStandardConversion code and do not have an EmitContext
+ handy.
+
+ The idea is to flag explicitly that at that point in time, it is
+ known that the conversion will not trigger the delegate checking
+ code in implicit conversions (which requires a valid
+ EmitContext).
+
+ Everywhere: pass new EmitContext parameter since
+ ImplicitStandardConversionExists now requires it to check for
+ anonymous method conversions.
+
+ (Convert.ImplicitStandardConversionExists): If the type of an
+ expression is the anonymous_method_type, and the type is a
+ delegate, we invoke the AnonymousMethod.Compatible method to check
+ whether an implicit conversion is possible.
+
+ (Convert.ImplicitConversionStandard): Only do implicit method
+ group conversions if the language level is not ISO_1.
+
+ * delegate.cs (Delegate.GetInvokeMethod): Common method to get the
+ MethodInfo for the Invoke method. used by Delegate and
+ AnonymousDelegate.
+
+ * expression.cs (Binary.DoNumericPromotions): only allow anonymous
+ method conversions if the target type is a delegate.
+
+ Removed extra debugging nops.
+
+ (LocalVariableReference): Turn the `local_info' into a public
+ field.
+
+ Add `prepared' field, the same hack used for FieldExprs to cope
+ with composed assignments, as Local variables do not necessarily
+ operate purely on the stack as they used to: they can be captured
+ fields.
+
+ Add `temp' for a temporary result, like fields.
+
+ Refactor DoResolve and DoResolveLValue into DoResolveBase.
+
+ It now copes with Local variables that are captured and emits the
+ proper instance variable to load it from a field in the captured
+ case.
+
+ (ParameterReference.DoResolveBase): During the resolve phase,
+ capture parameters if we are in an anonymous method.
+
+ (ParameterReference.Emit, ParameterReference.AddressOf): If in an
+ anonymous method, use the EmitContext helper routines to emit the
+ parameter reference.
+
+ * iterators.cs: Set RemapToProxy to true/false during the
+ EmitDispose class.
+
+ * parameters.cs (GetParameterByName): New helper method.
+
+ * typemanager.cs (anonymous_method_type) a new type that
+ represents an anonyous method. This is always an internal type,
+ used as a fencepost to test against the anonymous-methodness of an
+ expression.
+
+2004-10-20 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MethodCore.CheckBase): Add errors 505, 533, 544,
+ 561 report.
+ (PropertyBase.FindOutParentMethod): Add errors 545, 546 report.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.BetterFunction): If two methods have
+ equal parameter types, but only one of them is generic, the
+ non-generic one wins.
+ (New.DoResolve): Don't set `is_struct' to false if we're a generic
+ instance; just use `Type.IsValueType' to determine whether
+ something is a struct or not.
+ (MemberAccess.DoResolveAsTypeStep): Don't modify the `args' field,
+ so we can be called multiple times.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeParameter.DefineConstraints): New public method.
+ (TypeParameter.CheckAccessLevel): Override this and return true.
+ (ConstructedType.ResolveType): Renamed to DoResolveType(), don't
+ override ResolveType() anymore.
+ (ConstructedType.DoResolveAsTypeStep): Call DoResolveType() here.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs (RootContext.LookupType): If we're a nested type,
+ call DeclSpace.ResolveNestedType() on it.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * support.cs (ReflectionParameters.ParameterModifier): If `gpd' is
+ non-null, call ParameterModifier() on it.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs
+ (Iterators): Added `current_type' and `this_type' fields.
+ (Iterators.DefineIterator): Create a new EmitContext and store it
+ in `ec'; compute `this_type'.
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.IsPrivateAccessible): New public method.
+ (Closure.Filter): Use IsPrivateAccessible() instead of IsEqual().
+
+2004-11-10 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineType): Call
+ TypeBuilder.DefineGenericParameters() before resolving the type
+ parameters.
+ (MethodData.parent_method): New protected field.
+ (MethodData..ctor): Added `MethodInfo parent_method' argument.
+ (MethodData.Define): Compute `parent_method'.
+
+ * decl.cs
+ (MemberCore.GetObsoleteAttribute): Don't create a new EmitContext.
+ (MemberCore.GetClsCompliantAttributeValue): Likewise.
+ (DeclSpace.ec): New protected field; store the EmitContext here.
+ (DeclSpace.EmitContext): New public property.
+ (DeclSpace.ResolveType): Un-comment from the [Obsolte] attribute.
+ (DeclSpace.ResolveNestedType): New public method.
+ (DeclSpace.ResolveTypeExpr): Just call ResolveAsTypeTerminal() here.
+ (DeclSpace.NestedAccessible): Added `Type tb' argument.
+ (DeclSpace.FamilyAccessible): Likewise.
+ (DeclSpace.FindType): Call ResolveNestedType() for nested types.
+ (DeclSpace.GetClsCompliantAttributeValue): Don't create a new
+ EmitContext.
+
+ * delegate.cs (Delegate.Define): Store the EmitContext in the `ec'
+ field.
+
+ * enum.cs (Enum.Define): Store the EmitContext in the `ec' field.
+ (Enum.Emit): Don't create a new EmitContext.
+
+2004-10-18 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Fixed.Resolve): Don't access the TypeExpr's
+ `Type' directly, but call ResolveType() on it.
+ (Catch.Resolve): Likewise.
+ (Foreach.Resolve): Likewise.
+
+2004-10-18 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Cast.DoResolve): Don't access the TypeExpr's
+ `Type' directly, but call ResolveType() on it.
+ (Probe.DoResolve): Likewise.
+ (ArrayCreation.LookupType): Likewise.
+ (TypeOf.DoResolve): Likewise.
+ (SizeOf.DoResolve): Likewise.
+
+2004-10-18 Raja R Harinath <rharinath@novell.com>
+
+ * class.cs (FieldMember.DoDefine): Reset ec.InUnsafe after doing
+ the ResolveType.
+
+2004-10-17 John Luke <john.luke@gmail.com>
+
+ * class.cs (Operator.GetSignatureForError): use CSharpName
+
+ * parameter.cs (Parameter.GetSignatureForError): Returns
+ correct name even if was not defined.
+
+2004-10-13 Raja R Harinath <rharinath@novell.com>
+
+ Fix #65816.
+ * class.cs (TypeContainer.EmitContext): New property.
+ (DefineNestedTypes): Create an emitcontext for each part.
+ (MethodCore.DoDefineParameters): Use container's emitcontext.
+ Pass type array to InternalParameters.
+ (MemberBase.DoDefine): Use container's emitcontext.
+ (FieldMember.Define): Likewise.
+ (Event.Define): Likewise.
+ (SetMethod.GetParameterInfo): Change argument to EmitContext.
+ Pass type array to InternalParameters.
+ (SetIndexerMethod.GetParameterInfo): Likewise.
+ (SetMethod.Define): Pass emitcontext to GetParameterInfo.
+ * delegate.cs (Define): Pass emitcontext to
+ ComputeAndDefineParameterTypes and GetParameterInfo. Pass type
+ array to InternalParameters.
+ * expression.cs (ParameterReference.DoResolveBase): Pass
+ emitcontext to GetParameterInfo.
+ (ComposedCast.DoResolveAsTypeStep): Remove check on
+ ec.ResolvingTypeTree.
+ * parameter.cs (Parameter.Resolve): Change argument to
+ EmitContext. Use ResolveAsTypeTerminal.
+ (Parameter.GetSignature): Change argument to EmitContext.
+ (Parameters.ComputeSignature): Likewise.
+ (Parameters.ComputeParameterTypes): Likewise.
+ (Parameters.GetParameterInfo): Likewise.
+ (Parameters.ComputeAndDefineParameterTypes): Likewise.
+ Re-use ComputeParameterTypes. Set ec.ResolvingTypeTree.
+ * support.cs (InternalParameters..ctor): Remove variant that takes
+ a DeclSpace.
+ * typemanager.cs (system_intptr_expr): New.
+ (InitExpressionTypes): Initialize it.
+
+2004-10-12 Chris Toshok <toshok@ximian.com>
+
+ * cs-parser.jay: fix location for try_statement and catch_clause.
+
+2004-10-18 Martin Baulig <martin@ximian.com>
+
+ * class.cs (FieldMember.Define): Don't access the TypeExpr's
+ `Type' directly, but call ResolveType() on it.
+ (MemberBase.DoDefine): Likewise.
+
+ * expression.cs (New.DoResolve): Don't access the TypeExpr's
+ `Type' directly, but call ResolveType() on it.
+ (ComposedCast.DoResolveAsTypeStep): Likewise.
+
+ * statement.cs (LocalInfo.Resolve): Don't access the TypeExpr's
+ `Type' directly, but call ResolveType() on it.
+
+2004-10-17 John Luke <john.luke@gmail.com>
+
+ * class.cs (Operator.GetSignatureForError): use CSharpName
+
+ * parameter.cs (Parameter.GetSignatureForError): Returns
+ correct name even if was not defined.
+
+2004-10-13 Raja R Harinath <rharinath@novell.com>
+
+ Fix #65816.
+ * class.cs (TypeContainer.EmitContext): New property.
+ (DefineNestedTypes): Create an emitcontext for each part.
+ (MethodCore.DoDefineParameters): Use container's emitcontext.
+ Pass type array to InternalParameters.
+ (MemberBase.DoDefine): Use container's emitcontext.
+ (FieldMember.Define): Likewise.
+ (Event.Define): Likewise.
+ (SetMethod.GetParameterInfo): Change argument to EmitContext.
+ Pass type array to InternalParameters.
+ (SetIndexerMethod.GetParameterInfo): Likewise.
+ (SetMethod.Define): Pass emitcontext to GetParameterInfo.
+ * delegate.cs (Define): Pass emitcontext to
+ ComputeAndDefineParameterTypes and GetParameterInfo. Pass type
+ array to InternalParameters.
+ * expression.cs (ParameterReference.DoResolveBase): Pass
+ emitcontext to GetParameterInfo.
+ (ComposedCast.DoResolveAsTypeStep): Remove check on
+ ec.ResolvingTypeTree.
+ * parameter.cs (Parameter.Resolve): Change argument to
+ EmitContext. Use ResolveAsTypeTerminal.
+ (Parameter.GetSignature): Change argument to EmitContext.
+ (Parameters.ComputeSignature): Likewise.
+ (Parameters.ComputeParameterTypes): Likewise.
+ (Parameters.GetParameterInfo): Likewise.
+ (Parameters.ComputeAndDefineParameterTypes): Likewise.
+ Re-use ComputeParameterTypes. Set ec.ResolvingTypeTree.
+ * support.cs (InternalParameters..ctor): Remove variant that takes
+ a DeclSpace.
+ * typemanager.cs (system_intptr_expr): New.
+ (InitExpressionTypes): Initialize it.
+
+2004-10-12 Chris Toshok <toshok@ximian.com>
+
+ * cs-parser.jay: fix location for try_statement and catch_clause.
+
+2004-10-07 Raja R Harinath <rharinath@novell.com>
+
+ More DeclSpace.ResolveType avoidance.
+ * decl.cs (MemberCore.InUnsafe): New property.
+ * class.cs (MemberBase.DoDefine): Use ResolveAsTypeTerminal
+ with newly created EmitContext.
+ (FieldMember.Define): Likewise.
+ * delegate.cs (Delegate.Define): Likewise.
+ * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup with alias
+ only if normal name-lookup fails.
+ (TypeExpr.DoResolve): Enable error-checking.
+ * expression.cs (ArrayCreation.DoResolve): Use ResolveAsTypeTerminal.
+ (SizeOf.DoResolve): Likewise.
+ (ComposedCast.DoResolveAsTypeStep): Likewise.
+ (StackAlloc.DoResolve): Likewise.
+ * statement.cs (Block.Flags): Add new flag 'Unsafe'.
+ (Block.Unsafe): New property.
+ (Block.EmitMeta): Set ec.InUnsafe as appropriate.
+ (Unsafe): Set 'unsafe' flag of contained block.
+ (LocalInfo.Resolve): Use ResolveAsTypeTerminal.
+ (Fixed.Resolve): Likewise.
+ (Catch.Resolve): Likewise.
+ (Using.ResolveLocalVariableDecls): Likewise.
+ (Foreach.Resolve): Likewise.
+
+2004-10-05 John Luke <john.luke@gmail.com>
+
+ * cs-parser.jay: add location to error CS0175
+
+2004-10-04 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (Expression.Constantity): Add support for turning null
+ into a constant.
+
+ * const.cs (Const.Define): Allow constants to be reference types
+ as long as the value is Null.
+
+2004-10-04 Juraj Skripsky <js@hotfeet.ch>
+
+ * namespace.cs (NamespaceEntry.Using): No matter which warning
+ level is set, check if this namespace name has already been added.
+
+2004-10-03 Ben Maurer <bmaurer@ximian.com>
+
+ * expression.cs: reftype [!=]= null should always use br[true,false].
+ # 67410
+
+2004-10-03 Marek Safar <marek.safar@seznam.cz>
+
+ Fix #67108
+ * attribute.cs: Enum conversion moved to
+ GetAttributeArgumentExpression to be applied to the all
+ expressions.
+
+2004-10-01 Raja R Harinath <rharinath@novell.com>
+
+ Fix #65833, test-300.cs, cs0122-5.cs, cs0122-6.cs.
+ * class.c (TypeContainer.DefineType): Flag error if
+ base types aren't accessible due to access permissions.
+ * decl.cs (DeclSpace.ResolveType): Move logic to
+ Expression.ResolveAsTypeTerminal.
+ (DeclSpace.ResolveTypeExpr): Thin layer over
+ Expression.ResolveAsTypeTerminal.
+ (DeclSpace.CheckAccessLevel, DeclSpace.FamilyAccess):
+ Refactor code into NestedAccess. Use it.
+ (DeclSpace.NestedAccess): New.
+ * ecore.cs (Expression.ResolveAsTypeTerminal): Add new
+ argument to silence errors. Check access permissions.
+ (TypeExpr.DoResolve, TypeExpr.ResolveType): Update.
+ * expression.cs (ProbeExpr.DoResolve): Use ResolveAsTypeTerminal.
+ (Cast.DoResolve): Likewise.
+ (New.DoResolve): Likewise.
+ (InvocationOrCast.DoResolve,ResolveStatement): Likewise.
+ (TypeOf.DoResolve): Likewise.
+
+ * expression.cs (Invocation.BetterConversion): Return the Type of
+ the better conversion. Implement section 14.4.2.3 more faithfully.
+ (Invocation.BetterFunction): Make boolean. Make correspondence to
+ section 14.4.2.2 explicit.
+ (Invocation.OverloadResolve): Update.
+ (Invocation): Remove is_base field.
+ (Invocation.DoResolve): Don't use is_base. Use mg.IsBase.
+ (Invocation.Emit): Likewise.
+
+2004-09-24 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Reverted 642 warning fix.
+
+2004-09-23 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #66615
+ * decl.cs (FindMemberWithSameName): Indexer can have more than
+ 1 argument.
+
+2004-09-23 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (LocalVariableReference.DoResolveLValue):
+ Do not report warning 219 for out values.
+ (EmptyExpression.Null): New member to avoid extra allocations.
+
+2004-09-23 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Fix wrong warning 642 report.
+
+ * cs-tokenizer.cs (CheckNextToken): New helper;
+ Inspect next character if is same as expected.
+
+2004-09-23 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ImplicitReferenceConversion): Some code cleanup.
+ (Convert.ImplicitReferenceConversionExists): Likewise.
+
+2004-11-09 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (DISTFILES): Comment out a few missing files.
+
+2004-10-29 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (bootstrap_libs,bootstrap_libfiles): New.
+ (bootstrap-libs): New target. Invokes the net_2_0_bootstrap profile.
+ (gmcs.exe): Invoke bootstrap-libs.
+ (clean-local): Clean the net_2_0_bootstrap profile too.
+ (PROGRAM_INSTALL_DIR): New.
+ (install-local): Use it.
+
+2004-10-13 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeManager.InflatedConstraints): New nested class.
+ (TypeParameter.DefineType): If we're a method type parameter and
+ that method is overriding something, "inflate" its constraints.
+
+2004-10-12 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.DoResolve): If we're a SimpleName
+ and have type arguments, create and resolve a ConstructedType.
+
+2004-10-12 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCache.FindMemberToOverride): Use
+ TypeManager.IsEqual() to compare the parameters and Type.Equals()
+ to compare the invocationType.
+
+ * typemanager.cs (TypeManager.IsEqual): Added support for arrays.
+ When comparing two type parameters, only do the signature-only
+ comparision for method type parameters.
+
+2004-10-11 Martin Baulig <martin@ximian.com>
+
+ * report.cs: Don't make --fatal abort on warnings, we have
+ -warnaserror for that.
+
+2004-10-11 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.IsEqualGenericType): Removed, use IsEqual() instead.
+ (TypeManager.IsEqual): Call ourself recursively instead of using
+ Type.IsEqual().
+
+2004-10-11 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineType): Only call TypeParameter.Define()
+ on our own type parameters, not on the ones we inherit from a containing
+ class.
+
+ * expression.cs (Invocation.InferType): Use `==', not `Equals()' for
+ the comparision.
+
+ * generic.cs (TypeParameter.Define): We may only be called once.
+
+ * pending.cs (Pending.InterfaceMethod): Call TypeManager.Real_IsEqual()
+ instead of TypeManager.IsEqual().
+
+2004-09-28 Martin Baulig <martin@ximian.com>
+
+ * generic.cs
+ (GenericConstraints.EffectiveBaseClass): New public property.
+ (TypeParameter.GenericConstraints): New public property.
+ (ConstructedType.CheckConstraints): Improved.
+
+ * convert.cs (Convert.TypeParam_EffectiveBaseType): New private method.
+ (Convert.TypeParameterConversion): New private method; use this in
+ ImplicitReferenceConversion() and ImplicitReferenceConversionExists()
+ for all conversions related to type parameters.
+
+2004-09-24 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ImplicitReferenceConversion): Added implicit
+ type parameter conversions for type parameters which are known to
+ be reference types.
+
+2004-09-24 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericConstraints): Added `IsReferenceType' and
+ `IsValueType' properties.
+
+ * support.cs (ReflectionConstraints): Use
+ Type.GetGenericParameterConstraints() instead of the old hack.
+
+2004-09-24 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericConstraints): Moved here and made it an
+ abstract class.
+
+ * support.cs (GenericConstraints): Moved to generic.cs.
+
+2004-09-24 Martin Baulig <martin@ximian.com>
+
+ * support.cs
+ (ReflectionConstraints): Un-nested this class and made it public.
+
+ * typemanager.cs
+ (TypeManager.GetTypeParameterConstraints): New public method.
+ (TypeManager.HasConstructorConstraint): Use the attributes.
+
+2004-09-24 Martin Baulig <martin@ximian.com>
+
+ * support.cs (GenericConstraints): Replaced `HasConstructor',
+ `IsReferenceType' and `IsValueType' with `Attributes'.
+ (ReflectionParameters.ReflectionConstraints): Removed the Create()
+ method and made the .ctor public.
+
+ * generic.cs (Constraints.Attributes): New public property.
+ (Constraints): Renamed `HasConstructor' -> `HasConstructorConstraint',
+ `IsReferenceType' -> `HasReferenceTypeConstraint' and
+ `IsValueType' -> `HasValueTypeConstraint'.
+
+2004-09-23 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (Constraints): Reflect latest runtime changes.
+
+2004-09-23 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ImplicitReferenceConversion): Some code cleanup.
+ (Convert.ImplicitReferenceConversionExists): Likewise.
+
+2004-09-23 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (Operator.Define): Add error 448 and 559 report.
+
+2004-09-22 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MemberBase.IsTypePermitted): New protected
+ method for checking error CS0610.
+
+2004-09-22 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (TypeContainer.HasExplicitLayout): New property
+ Returns whether container has StructLayout attribute set Explicit.
+ (FieldMember): New abstract class for consts and fields.
+ (FieldMember.ApplyAttributeBuilder): Add error 636 and 637 report.
+ (Field): Reuse FieldMember.
+
+ * const.cs (Const): Reuse FieldMember.
+
+ * rootcontext.cs: EmitConstants call moved to class.
+
+2004-09-22 Martin Baulig <martin@ximian.com>
+
+ Marek and me just fixed one of our oldest bugs: #28562 :-)
+
+ * ecore.cs (EnumConstant.GetValueAsEnumType): New public method.
+
+ * attribute.cs (Attribute.GetAttributeArgumentExpression): If
+ we're an EnumConstant, just return that.
+ (Attribute.Resolve): GetAttributeArgumentExpression() may give us
+ an EnumConstant. In this case, we need to use GetValueAsEnumType()
+ to get the value which'll actually be written into the attribute.
+ However, we have to use GetValue() to access the attribute's value
+ in the compiler.
+
+2004-09-22 Marek Safar <marek.safar@seznam.cz>
+
+ * constant.cs (Constant.IsNegative): New abstract property
+ IsNegative.
+
+ * expression.cs (ArrayAccess.DoResolve): Add warning 251.
+ (StackAlloc.DoResolve): Reused IsNegative.
+
+2004-09-22 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.LookupGenericTypeContainer): New
+ public method; like LookupTypeContainer, but also works for
+ generic instances.
+
+ * report.cs (Report.SymbolRelatedToPreviousError): Use
+ TypeManager.LookupGenericTypeContainer().
+
+2004-09-22 Martin Baulig <martin@ximian.com>
+
+ Thanks to Peter Sestoft for this bug report.
+
+ * expression.cs (Conditional): If both the `trueExpr' and the
+ `falseExpr' is a NullLiteral, return a NullLiteral.
+
+2004-09-22 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Foreach.EmitCollectionForeach): If we're in an
+ iterator, use `enumerator.EmitThis()' instead of `ec.EmitThis()'
+ for the "get_Current" call.
+
+2004-09-21 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ImplicitReferenceConversion): When
+ converting to an interface type, first check whether we're
+ converting from a reference type.
+
+2004-09-14 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCore.Emit): Always call VerifyObsoleteAttribute().
+
+2004-09-14 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #61902
+ * codegen.cs (TestObsoleteMethodUsage): Trace when method is
+ called and is obsolete then this member suppress message
+ when call is inside next [Obsolete] method or type.
+
+ * expression.cs: Use TestObsoleteMethodUsage member.
+
+2004-09-14 Martin Baulig <martin@ximian.com>
+
+ * genericparser.cs: Removed.
+
+2004-09-13 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MethodCore.CheckBase): Fix bug #65757.
+
+2004-09-12 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute.Resolve): Add error 653 report.
+
+ * class.cs (Class.ApplyAttributeBuilder): Add error 641
+ report.
+ (Method.ApplyAttributeBuilder): Add error 685 report.
+ (Operator.Define): Add error 564 report.
+
+ * cs-tokenizer.cs (handle_hex): Add error 1013 report.
+
+ * expression.cs (Invocation.DoResolve): Add error
+ 245 and 250 report.
+
+ * parameter.cs (Parameter.ApplyAttributeBuilder): Add
+ error 674 report.
+
+2004-09-11 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (ConstructorInitializer.Resolve):
+ Wrong error number (515->516).
+
+2004-09-11 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (Indexer.Define): Add error 631 report.
+
+2004-09-11 Marek Safar <marek.safar@seznam.cz>
+
+ * ecore.cs (Error_NegativeArrayIndex): Fix 248 error.
+
+2004-09-11 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Probe.DoResolve): Add error CS0241 report.
+
+2004-09-10 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added error CS0241 report.
+
+2004-09-10 Raja R Harinath <rharinath@novell.com>
+
+ * cs-parser.jay (fixed_statement): Introduce a scope for the
+ declaration in the 'fixed' statement.
+
+2004-09-09 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added CS0230 error report.
+
+2004-09-09 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added errors CS0231 and CS0257 report.
+
+2004-09-09 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (Argument.Resolve): Added error CS0192 and
+ CS0199 report.
+
+2004-09-09 Marek Safar <marek.safar@seznam.cz>
+
+ C# 2.0 #pragma warning feature
+
+ * cs-tokenizer.cs (PreProcessPragma): New method;
+ Handles #pragma directive.
+
+ * report.cs (WarningRegions): New class; Support
+ class for #pragma warning directive. It tests whether
+ warning is enabled for a given line.
+
+2004-09-08 Miguel de Icaza <miguel@ximian.com>
+
+ * const.cs: Add more descriptive error report, tahnks to
+ Sebastien.
+
+2004-09-08 Marek Safar <marek.safar@seznam.cz>
+
+ * ecore.cs (FieldExpr.DoResolveLValue): Fixed CS0198 report.
+
+2004-09-07 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs: Apply patch from Ben: Remove dead code from
+ ArrayCreation, and remove the TurnintoConstant call in const.cs,
+ as that code just threw an exception anwyays.
+
+ * const.cs: Remove the call to the turnintoconstant, for details
+ see bug: #63144
+
+ * literal.cs: The type of the null-literal is the null type; So
+ we use a placeholder type (literal.cs:System.Null, defined here)
+ for it.
+
+ * expression.cs (Conditional.DoResolve): Remove some old code that
+ is no longer needed, conversions have been fixed.
+
+ (ArrayCreationExpression.DoResolve): Return false if we fail to
+ resolve the inner expression.
+
+2004-09-07 Raja R Harinath <rharinath@novell.com>
+
+ Fix test-290.cs.
+ * cs-parser.jay (delegate_declaration): Record a delegate
+ declaration as a type declaration.
+ Reported by Jo Vermeulen <jo@lumumba.luc.ac.be>.
+
+2004-09-06 Miguel de Icaza <miguel@ximian.com>
+
+ * parameter.cs: Do not crash if the type can not be resolved.
+
+ * expression.cs: Report errors with unsafe pointers, fixes #64896
+
+2004-09-06 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Pointer arith always needs to do a conv.i
+ if the operand is a long. fix 65320
+
+2004-09-04 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed cs0619-37.cs, cs0619-38.cs
+
+ * enum.cs (GetObsoleteAttribute): Removed.
+
+ * expression.cs (MemberAccess.DoResolve): Test for [Obsolete]
+ on Enum member is double staged. The first is tested member
+ and then enum.
+
+2004-09-04 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed #56986, #63631, #65231
+
+ * class.cs: (TypeContainer.AddToMemberContainer): New method,
+ adds member to name container.
+ (TypeContainer.AddToTypeContainer): New method, adds type to
+ name container.
+ (AddConstant, AddEnum, AddClassOrStruct, AddDelegate, AddMethod,
+ AddConstructor, AddInterface, AddField, AddProperty, AddEvent,
+ AddOperator): Simplified by reusing AddToMemberContainer.
+ (TypeContainer.UserDefinedStaticConstructor): Changed to property
+ instead of field.
+ (Method.CheckForDuplications): Fixed implementation to test all
+ possibilities.
+ (MemberBase): Detection whether member is explicit interface
+ implementation is now in constructor.
+ (MemberBase.UpdateMemberName): Handles IndexerName.
+ (Accessor): Changed to keep also location information.
+ (AbstractPropertyEventMethod): Is derived from MemberCore.
+ (AbstractPropertyEventMethod.IsDummy): Says whether accessor
+ will be emited or not.
+ (PropertyBase.AreAccessorsDuplicateImplementation):
+ Tests whether accessors are not in collision with some method.
+ (Operator): Is derived from MethodCore to simplify common
+ operations.
+
+ * decl.cs (Flags.TestMethodDuplication): Test for duplication
+ must be performed.
+ (DeclSpace.AddToContainer): Adds the member to defined_names
+ table. It tests for duplications and enclosing name conflicts.
+
+ * enum.cs (EnumMember): Clean up to reuse the base structures
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ Merged latest changes into gmcs. Please keep this comment in
+ here, it makes it easier for me to see what changed in MCS since
+ the last time I merged.
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineDefaultConstructor): Put this back
+ into TypeContainer, to make partial classes work again.
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs (RootContext.V2): Removed.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.OverloadResolve): Added `bool
+ may_fail' argument and use it instead of the Location.IsNull() hack.
+
+2004-09-09 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (namespace_declaration): Fixed CS0134 reporting.
+
+2004-09-09 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeParameter.DefineType): Added support for
+ explicit interface methods.
+
+2004-09-09 Martin Baulig <martin@ximian.com>
+
+ * README.Changes: New document. Started to list important changes
+ between MCS and GMCS here.
+
+2004-09-08 Martin Baulig <martin@ximian.com>
+
+ * class.cs
+ (TypeContainer.CheckRecursiveDefinition): New protected method.
+ (TypeContainer.DefineType): Move the CS0146 check into
+ CheckRecursiveDefinition().
+
+2004-09-06 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Allow builtin
+ types for the constructor constraint.
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineDefaultConstructor): Put this back
+ into TypeContainer, to make partial classes work again.
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs (RootContext.V2): Removed.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.OverloadResolve): Added `bool
+ may_fail' argument and use it instead of the Location.IsNull() hack.
+
+2004-09-03 Martin Baulig <martin@ximian.com>
+
+ Merged latest changes into gmcs. Please keep this comment in
+ here, it makes it easier for me to see what changed in MCS since
+ the last time I merged.
+
+2004-09-03 Raja R Harinath <rharinath@novell.com>
+
+ Fix #61128.
+ * expression.cs (BetterConversion): Don't allow either conversion
+ to be null. Remove redundant implicit conversion test when 'q ==
+ null' -- when this function is invoked, we already know that the
+ implicit conversion exists.
+ (BetterFunction): Assume that 'best' is non-null. Remove
+ redundant reimplementation of IsApplicable when 'best' is null.
+ (IsParamsMethodApplicable, IsApplicable): Add new parameter for
+ number of arguments.
+ (IsAncestralType): Extract from OverloadResolve.
+ (OverloadResolve): Make robust to the MethodGroupExpr being
+ unsorted. Implement all the logic of Section 14.5.5.1, and
+ support overloading of methods from multiple applicable types.
+ Clean up logic somewhat. Don't pass null methods to BetterFunction.
+
+ * report.cs (SymbolRelatedToPreviousError): Cleanup output.
+ (RealError, Warning): Append type of report to related symbol.
+
+2004-09-03 Marek Safar <marek.safar@seznam.cz>
+
+ * enum.cs: Fixed CLS-Compliance checks for enum members.
+ Error tests cs3008-8.cs, cs3014-8.cs
+
+2004-09-02 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #62342, #63102
+ * class.cs: ImplementIndexer uses member.IsExplicitImpl
+ like ImplementMethod.
+
+2004-09-02 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute.GetAttributeArgumentExpression):
+ Fixed bug #65170.
+
+2004-09-02 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Using.EmitLocalVariableDeclFinally): Use
+ TypeManager.GetArgumentTypes() rather than calling GetParameters()
+ on the MethodBase.
+
+2004-09-01 Marek Safar <marek.safar@seznam.cz>
+
+ C# 2.0 Static classes implemented
+
+ * class.cs (TypeContainer): instance_constructors,
+ initialized_fields, initialized_static_fields,
+ default_constructor, base_inteface_types are protected to be
+ accessible from StaticClass.
+ (TypeContainer.DefineDefaultConstructor): New virtual method
+ for custom default constructor generating
+ (StaticClass): New class to handle "Static classes" feature.
+
+ * cs-parser.jay: Handle static keyword on class like instance
+ of StaticClass.
+
+ * driver.cs: Added "/langversion" command line switch with two
+ options (iso-1, default).
+
+2004-08-31 Marek Safar <marek.safar@seznam.cz>
+
+ * ecore.cs (FieldExpr.Resolve): Fixed bug #64689.
+
+2004-08-31 Miguel de Icaza <miguel@ximian.com>
+
+ * delegate.cs: Style.
+
+2004-08-31 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * delegate.cs: Add seperate instance expr field for miguel.
+
+2004-08-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * PointerArithmetic (Resolve): make sure we are not doing
+ pointer arith on void*. Also, make sure we are resolved
+ by not setting eclass until resolve.
+
+ All callers: Make sure that PointerArithmetic gets resolved.
+
+2004-08-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * ArrayCreation (LookupType): If the type does not resolve
+ to an array, give an error.
+
+2004-08-27 Marek Safar <marek.safar@seznam.cz>
+
+ * statement.cs (Try.Resolve): Fixed bug #64222
+
+2004-08-27 Martin Baulig <martin@ximian.com>
+
+ * class.cs
+ (TC.OperatorArrayList.OperatorEntry.CheckPairedOperators): Don't
+ crash here.
+
+2004-08-26 Marek Safar <marek.safar@seznam.cz>
+
+ * ecore.cs (Constantify): Get underlying type via
+ System.Enum.GetUnderlyingType to avoid StackOverflow on the
+ Windows in special cases.
+
+2004-08-26 Marek Safar <marek.safar@seznam.cz>
+
+ * typemanager.cs (GetAddMethod): Used GetAddMethod (true)
+ for obtaining also private methods.
+ (GetRemoveMethod): Used GetRemoveMethod (true)
+ for obtaining also private methods.
+
+2004-09-02 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Using.EmitLocalVariableDeclFinally): Use
+ TypeManager.GetArgumentTypes() rather than calling GetParameters()
+ on the MethodBase.
+
+2004-08-27 Martin Baulig <martin@ximian.com>
+
+ * class.cs
+ (TC.OperatorArrayList.OperatorEntry.CheckPairedOperators): Don't
+ crash here.
+
+2004-08-25 Martin Baulig <martin@ximian.com>
+
+ * support.cs (ReflectionParameters..ctor): If this is a generic
+ method, retrieve and store its type parameters.
+ (InternalParameters..ctor): Added `TypeParameter[]' argument.
+ (ReflectionParameters.GenericConstraints): The argument specifies
+ the type parameter, not the method parameter.
+ (InternalParameters.GenericConstraints): Likewise.
+
+ * generic.cs (TypeParameter.DefineType): Correctly handle
+ constraints wrt. generic methods in interfaces and their
+ implementations.
+
+2004-08-24 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeParameter.IsSubclassOf): New public method.
+ (Constraints.IsSubclassOf): New internal method.
+
+ * typemanager.cs (TypeManager.FindMembers): Added special support
+ for GenericTypeParameterBuilder's.
+ (TypeManager.IsSubclassOf, IsFamilyAccessible): Added support for
+ type parameters.
+
+2004-08-24 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.IsSubclassOf): Renamed to IsFamilyAccessible; use
+ this for accessibility checks.
+ (TypeManager.IsSubclassOrNestedChildOf): Renamed to
+ IsNestedFamilyAccessible.
+ (TypeManager.IsSubclassOf): New method, do what the name actually
+ says.
+
+2004-08-24 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.DoResolve): When resolving ourselves
+ as a SimpleName, include the generic arity.
+
+2004-08-24 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Method.Define): Set MethodAttributes.SpecialName and
+ MethodAttributes.HideBySig for operators.
+
+2004-08-23 Martin Baulig <martin@ximian.com>
+
+ Back to the old error reporting system :-)
+
+ * report.cs (Message): Removed.
+ (Report.MessageData, ErrorData, WarningData): Removed.
+ (Report.Error, Warning): Back to the old system.
+
+2004-08-23 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (IMemberContainer.Parent): Renamed to ParentContainer.
+
+ * class.cs (TypeContainer.ParentContainer): New public virtual
+ method; replaces the explicit interface implementation.
+ (ClassPart.ParentContainer): Override.
+
+2004-08-23 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Switch): Added support for constant switches; see
+ #59428 or test-285.cs.
+
+2004-08-22 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #62740.
+ * statement.cs (GetEnumeratorFilter): Removed useless
+ logic because C# specs is strict. GetEnumerator must be
+ public.
+
+2004-08-22 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're
+ a switch and may break, reset the barrier. Fixes #59867.
+
+2004-08-22 Marek Safar <marek.safar@seznam.cz>
+
+ CLS-Compliance speed up (~5% for corlib)
+
+ * attribute.cs (AttributeTester.VerifyTopLevelNameClsCompliance):
+ New method. Tests container for CLS-Compliant names
+
+ * class.cs (TypeContainer.VerifyClsName): New method.
+ Checks whether container name is CLS Compliant.
+ (Constructor): Implements IMethodData.
+
+ * decl.cs (MemberCache.GetPublicMembers ): New method. Builds
+ low-case table for CLS Compliance test.
+ (MemberCache.VerifyClsParameterConflict): New method.
+ Checks method parameters for CS3006 error.
+
+ * enum.cs (EnumMember): Is derived from MemberCore.
+ (Enum.VerifyClsName): Optimized for better performance.
+
+2004-08-06 Marek Safar <marek.safar@seznam.cz>
+
+ * report.cs: Renamed Error_T to Error and changed all
+ references.
+
+2004-08-06 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (TypeContainer.IndexerArrayList): New inner class
+ container for indexers.
+ (TypeContainer.DefaultIndexerName): New constant for default
+ indexer name. Replaced all "Item" with this constant.
+ (TypeContainer.DefineIndexers): Moved to IndexerArrayList class.
+
+ * typemanager.cs (TypeManager.default_member_ctor): Cache here
+ DefaultMemberAttribute constructor.
+
+2004-08-05 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.UsageVector.MergeJumpOrigins):
+ Fix bug #59429.
+
+2004-08-05 Marek Safar <marek.safar@seznam.cz>
+
+ * mcs.exe.sources: $(EXTRA_SOURCES) are now here to avoid
+ multi platforms problem.
+
+ * compiler.csproj: Included shared files.
+
+2004-08-04 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug 60333, 55971 in the more general way
+ * attribute.cs (Attribute.GetAttributeArgumentExpression):
+ Added arg_type argument for constant conversion.
+ (Attribute.Resolve): Reuse GetAttributeArgumentExpression.
+
+2004-08-04 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #59760
+ * class.cs (TypeContainer ): New inner classes MethodArrayList,
+ OperatorArrayList, MethodCoreArrayList for typecontainer
+ containers. Changed class member types to these new types.
+ (MethodArrayList.DefineMembers): Added test for CS0659.
+
+2004-08-04 Miguel de Icaza <miguel@ximian.com>
+
+ * cfold.cs: Synchronize the folding with the code in expression.cs
+ Binary.DoNumericPromotions for uint operands.
+
+ * attribute.cs: Revert patch from Raja, it introduced a regression
+ while building Blam-1.2.1 (hard to isolate a test case).
+
+2004-08-04 Marek Safar <marek.safar@seznam.cz>
+
+ Fix for #55382
+ * class.cs:
+ (TypeContainer.Define): Renamed to DefineContainerMembers because of
+ name collision.
+ (MethodCore.parent_method): New member. The method we're overriding
+ if this is an override method.
+ (MethodCore.CheckBase): Moved from Method class and made common.
+ (MethodCore.CheckMethodAgainstBase): Moved from MemberBase and made
+ private.
+ (MethodCore.CheckForDuplications): New abstract method. For custom
+ member duplication search in a container
+ (MethodCore.FindOutParentMethod): New abstract method. Gets parent
+ method and its return type.
+ (Event.conflict_symbol): New member. Symbol with same name in the
+ parent class.
+
+ * decl.cs:
+ (MemberCache.FindMemberWithSameName): New method. The method
+ is looking for conflict with inherited symbols.
+
+2004-08-04 Martin Baulig <martin@ximian.com>
+
+ * codegen.cs (VariableStorage.EmitLoadAddress): New public method.
+
+ * statement.cs (Foreach.EmitFinally): Make this work for valuetypes.
+
+2004-08-03 Marek Safar <marek.safar@seznam.cz>
+
+ * report.cs (Message): New enum for better error, warning reference in
+ the code.
+ (MessageData): New inner abstract class. It generally handles printing of
+ error and warning messages.
+ Removed unused Error, Warning, Message methods.
+
+2004-08-03 Marek Safar <marek.safar@seznam.cz>
+
+ Fix for cs0592-8.cs test
+ * attribute.cs
+ (Attributable.ValidAttributeTargets): Made public.
+ (Attribute.ExplicitTarget): New member for explicit target value.
+ (Attribute.CheckTargets): Now we translate explicit attribute
+ target to Target here.
+
+2004-08-03 Ben Maurer <bmaurer@ximian.com>
+
+ * ecore.cs (MethodGroupExpr): new IsBase property.
+
+ * expression.cs (BaseAccess): Set IsBase on MethodGroupExpr.
+
+ * delegate.cs (DelegateCreation): store a MethodGroupExpr
+ rather than an instance expr.
+
+ (DelegateCreation.Emit): Use the method group rather than
+ the instance expression. Also, if you have base.Foo as the
+ method for a delegate, make sure to emit ldftn, not ldftnvirt.
+
+ (ResolveMethodGroupExpr): Use the MethodGroupExpr.
+
+ (NewDelegate.DoResolve): Only check for the existance of Invoke
+ if the method is going to be needed. Use MethodGroupExpr.
+
+ (NewDelegate.Emit): Remove, DelegateCreation implements this.
+
+ * expression.cs: For pointer arith., make sure to use
+ the size of the type, not the size of the pointer to
+ the type.
+
+2004-08-03 Marek Safar <marek.safar@seznam.cz>
+
+ Fix for #60722
+ * class.cs (Class): Added error CS0502 test.
+
+2004-08-03 John Luke <jluke@cfl.rr.com>
+ Raja R Harinath <rharinath@novell.com>
+
+ Fix for #60997.
+ * attribute.cs (Attribute.complained_before): New flag.
+ (Attribute.ResolveType, Attribute.Resolve),
+ (Attribute.DefinePInvokeMethod): Set it.
+ (Attributes.Search): Pass 'complain' to Attribute.ResolveType.
+
+2004-08-03 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Binary.ResolveOperator): Don't abort if we can't
+ use a user-defined operator; we still need to do numeric
+ promotions in case one argument is a builtin type and the other
+ one has an implicit conversion to that type. Fixes #62322.
+
+2004-08-18 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Method.Define): Use the correct method name when
+ creating the MethodBuilder for a generic method.
+
+2004-08-17 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (Constraints): Support type parameter constraints.
+
+2004-08-16 Martin Baulig <martin@ximian.com>
+
+ * cs-tokenizer.cs (Tokenizer.TypeOfParsing): New public property.
+ (Token.GENERIC_DIMENSION): New token; this is returned if we
+ encounter an unbound generic type in a typeof() expression.
+
+ * cs-parser.jay (opt_type_argument_list): Added GENERIC_DIMENSION;
+ this token is only generated while parsing a typeof() expression.
+ (typeof_expression): Removed the old unbound_type hack.
+
+ * generic.cs (TypeArguments.IsUnbound): New public property.
+
+ * decl.cs (MemberName): Added support for unbound types.
+
+2004-08-14 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.IsEqualGenericInstance): New static method.
+ (TypeManager.IsSubclassOrNestedChildOf, IsSubclassOf): This is
+ just used to check accessibility, so follow the rules of 26.1.6.
+
+ * expression.cs (MemberAccess.ResolveAsTypeStep): Return a
+ ConstructedType instead of a TypeExpression if we have type arguments.
+
+ * cs-parser.jay (typeof_expression): Support unbound generic types.
+
+ * ecore.cs (UnboundTypeExpression): New public class.
+
+2004-08-12 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IsNestedChildOf): Use
+ TypeManager.IsEqual() rather than `=='.
+
+ * decl.cs (DeclSpace.CheckAccessLevel): Use `tb.FullName' for
+ generic instances as well.
+
+2004-08-12 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): We can only infer method
+ type parameters. Fixes #62647.
+
+2004-08-11 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineType): Create the TypeBuilder
+ before resolving the base classes.
+
+2004-08-06 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * Makefile: install .mdb file too.
+
+2004-08-05 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (FieldExpr.DoResolveLValue): If we're resolving a field
+ initializer, the current type is just the TypeBuilder, not the
+ instantiated generic type.
+ (FieldExpr.IsFieldInitializer): New public property.
+
+2004-08-04 Martin Baulig <martin@ximian.com>
+
+ * codegen.cs (VariableStorage.EmitLoadAddress): New public method.
+
+ * statement.cs (Foreach.EmitFinally): Make this work for valuetypes.
+
+2004-08-03 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodData.Define): If we're an explicit
+ implementation, remove the generic arity from the type name.
+
+2004-08-03 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Binary.ResolveOperator): Don't abort if we can't
+ use a user-defined operator; we still need to do numeric
+ promotions in case one argument is a builtin type and the other
+ one has an implicit conversion to that type. Fixes #62322.
+
+2004-08-02 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.ifaces): Make this a `Type[]', not a
+ `TypeExpr[]' array.
+ (TypeContainer.GetClassBases): Return the unexpanded list of
+ interfaces; we expand them later.
+ (TypeContainer.DefineType): After creating the TypeBuilder, call
+ TypeManager.ExpandInterfaces() to get an expanded and resolved
+ list of interfaces.
+
+ * ecore.cs (TypeExpr.GetInterfaces): Removed
+
+ * generics.cs (Constraints.InterfaceConstraints): Remove.
+ (TypeParameter.DefineType): Call TypeManager.RegisterBuilder() to
+ register the interface constraints.
+
+ * typemanager.cs
+ (TypeManager.AddUserType): Removed the `ifaces' argument.
+ (TypeManager.AddTypeParameter): Likewise.
+ (TypeManager.AddUserInterface): Removed, was unused.
+ (TypeManager.RegisterBuilder): Take a `Type[]' instead of a
+ `TypeExpr[]' array for the interfaces.
+ (TypeManager.ExpandInterfaces): Call this after the TypeBuilder
+ has been defined, returns a list of the resolved interfaces types.
+ (TypeManager.GetInterfaces): Return a `Type[]', not a `TypeExpr[]'.
+ (TypeManager.GetExplicitInterfaces): Likewise.
+
+2004-08-02 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.EmitCall): If we're invoking a method
+ on a type parameter, use the new `Constrained' prefix opcode.
+
+2004-08-02 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (LocalInfo.Flags): Added `IsThis'.
+ (LocalInfo.IsThis): New public property.
+ (Block.EmitMeta): Don't create a LocalBuilder for `this'.
+
+2004-08-01 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Don't set the default
+ here since we may get called from GetPartialBases().
+ (TypeContainer.DefineType): If GetClassBases() didn't return a
+ parent, use the default one.
+
+2004-07-30 Martin Baulig <martin@ximian.com>
+
+ * Makefile (EXTRA_SOURCES): List the symbol writer's sources here.
+
+ * class.cs (SourceMethod): New public class, derive from the
+ symbol writer's ISourceMethod.
+ (Method): Use the new symbol writer API.
+
+ * codegen.cs (CodeGen.InitializeSymbolWriter): Take the filename
+ as argument and use the new symbol writer.
+
+ * location.cs
+ (SourceFile): Implement the symbol writer's ISourceFile.
+ (Location.SymbolDocument): Removed.
+ (Location.SourceFile): New public property.
+
+ * symbolwriter.cs: Use the new symbol writer API.
+
+2004-07-30 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile (install-local): Remove. Functionality moved to
+ executable.make.
+
+2004-07-28 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Makefile: Install mcs.exe.config file together with mcs.exe.
+ * mcs.exe.config: Added supportedRuntime entry to make sure it runs in the
+ correct runtime version.
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * class.cs
+ (TypeContainer.RegisterOrder): Removed, this was unused.
+ (TypeContainer, interface_order): Removed.
+ (TypeContainer.AddClass, AddStruct, AddInterface): Take a
+ TypeContainer as argument since we can also be called with a
+ `PartialContainer' for a partial class/struct/interface.
+ (TypeContainer.IsInterface): Use `Kind == Kind.Interface' instead
+ of checking whether we're an `Interface' - we could be a
+ `PartialContainer'.
+ (PartialContainer.Register): Override; call
+ AddClass()/AddStruct()/AddInterface() on our parent.
+
+ * cs-parser.jay (interface_member_declaration): Add things to the
+ `current_container', not the `current_class'.
+
+ * rootcontext.cs (RegisterOrder): The overloaded version which
+ takes an `Interface' was unused, removed.
+
+ * typemanager.cs (TypeManager.LookupInterface): Return a
+ `TypeContainer', not an `Interface'.
+ (TypeManager.IsInterfaceType): The `builder_to_declspace' may
+ contain a `PartialContainer' for an interface, so check it's
+ `Kind' to figure out what it is.
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Class.DefaultTypeAttributes): New public constant.
+ (Struct.DefaultTypeAttributes): Likewise.
+ (Interface.DefaultTypeAttributes): Likewise.
+ (PartialContainer.TypeAttr): Override this and add the
+ DefaultTypeAttributes.
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.Emit): Removed the `TypeContainer' argument,
+ we can just use the `Parent' field instead.
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.Emit): Renamed to EmitType().
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineMembers): Call DefineMembers() on
+ our parts before defining any methods.
+ (TypeContainer.VerifyImplements): Make this virtual.
+ (ClassPart.VerifyImplements): Override and call VerifyImplements()
+ on our PartialContainer.
+
+2004-07-25 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs (Iterator.Define): Renamed to DefineIterator().
+
+ * decl.cs (DeclSpace.Define): Removed the `TypeContainer'
+ argument, we can just use the `Parent' field instead.
+
+ * class.cs
+ (MemberBase.CheckBase): Removed the `TypeContainer' argument.
+ (MemberBase.DoDefine): Likewise.
+
+2004-07-24 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCore.Parent): New public field.
+ (DeclSpace.Parent): Moved to MemberCore.
+
+ * class.cs (MethodCore.ds): Removed; use `Parent' instead.
+ (MemberBase.ctor): Added TypeContainer argument, pass it to our
+ parent's .ctor.
+ (FieldBase, Field, Operator): Likewise.
+ (EventProperty.ctor): Take a TypeContainer instead of a DeclSpace.
+ (EventField, Event): Likewise.
+
+2004-07-23 Martin Baulig <martin@ximian.com>
+
+ * class.cs (PartialContainer): New public class.
+ (ClassPart): New public class.
+ (TypeContainer): Added support for partial classes.
+ (TypeContainer.GetClassBases): Splitted some of the functionality
+ out into GetNormalBases() and GetPartialBases().
+
+ * cs-tokenizer.cs (Token.PARTIAL): New token.
+ (Tokenizer.consume_identifier): Added some hacks to recognize
+ `partial', but only if it's immediately followed by `class',
+ `struct' or `interface'.
+
+ * cs-parser.jay: Added support for partial clases.
+
+2004-07-23 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodCore.ds): Made this a `TypeContainer' instead of
+ a `DeclSpace' and also made it readonly.
+ (MethodCore.ctor): Take a TypeContainer instead of a DeclSpace.
+ (Method.ctor, Constructor.ctor, Destruktor.ctor): Likewise.
+ (PropertyBase.ctor, Property.ctor, Indexer.ctor): Likewise.
+
+ * cs-parser.jay: Pass the `current_class', not the
+ `current_container' (at the moment, this is still the same thing)
+ to a new Method, Property, Event, Indexer or Constructor.
+
+2004-07-23 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (CSharpParser): Added a new `current_class' field
+ and removed the `current_interface' one.
+ (struct_declaration, class_declaration, interface_declaration):
+ Set `current_class' to the newly created class/struct/interface;
+ set their `Bases' and call Register() before parsing their body.
+
+2004-07-23 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Kind): New public enum.
+ (TypeContainer): Made this class abstract.
+ (TypeContainer.Kind): New public readonly field.
+ (TypeContainer.CheckDef): New public method; moved here from
+ cs-parser.jay.
+ (TypeContainer.Register): New public abstract method.
+ (TypeContainer.GetPendingImplementations): New public abstract
+ method.
+ (TypeContainer.GetClassBases): Removed the `is_class' and
+ `is_iface' parameters.
+ (TypeContainer.DefineNestedTypes): Formerly known as
+ DoDefineType().
+ (ClassOrStruct): Made this class abstract.
+
+ * tree.cs (RootTypes): New public type.
+
+2004-07-20 Martin Baulig <martin@ximian.com>
+
+ * tree.cs (Tree.RecordNamespace): Removed.
+ (Tree.Namespaces): Removed.
+
+ * rootcontext.cs (RootContext.IsNamespace): Removed.
+
+ * cs-parser.jay (namespace_declaration): Just create a new
+ NamespaceEntry here.
+
+2004-07-21 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Makefile: Install gmcs.exe.config file together with gmcs.exe.
+ * gmcs.exe.config: Renamed from mcs.exe.config. Added supportedRuntime
+ entry to make sure it runs in the correct runtime version.
+
+2004-07-18 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Improved
+ constraints checking.
+
+2004-07-18 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.BetterMethod): Call
+ TypeManager.TypeToCoreType() on all types and removed my previous
+ hack; we're already doig the right thing here.
+
+2004-07-17 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberName.MakeName): Create the "class`1" names here.
+
+2004-07-16 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs: Added generics support.
+
+2004-07-16 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs: Rewrote this. We're now using one single Proxy
+ class for both the IEnumerable and the IEnumerator interface and
+ `Iterator' derives from Class so we can use the high-level API.
+
+ * class.cs (TypeContainer.AddIterator): New method.
+ (TypeContainer.DoDefineType): New protected virtual method, which
+ is called from DefineType().
+ (TypeContainer.DoDefineMembers): Call DefineType() and
+ DefineMembers() on all our iterators.
+ (TypeContainer.Emit): Call Emit() on all our iterators.
+ (TypeContainer.CloseType): Call CloseType() on all our iterators.
+
+ * codegen.cs (EmitContext.CurrentIterator): New public field.
+
+2004-07-15 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.not_supported_exception_type): New type.
+
+2004-07-14 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs
+ (TypeManager.generic_ienumerable_type): New type.
+ (TypeManager.generic_ienumerator_type): New type.
+
+ * rootcontext.cs
+ (RootContext.interfaces_first_stage): Added
+ "System.Collections.Generic.IEnumerator`1" and
+ "System.Collections.Generic.IEnumerable`1".
+
+2004-07-14 Martin Baulig <martin@ximian.com>
+
+ * iterators.cs: Use real error numbers.
+
+2004-07-14 Martin Baulig <martin@ximian.com>
+
+ * iterator.cs (IteratorHandle.IsIEnumerable): The spec explicitly
+ requires this to be a System.Collection.IEnumerable and not a
+ class implementing that interface.
+ (IteratorHandle.IsIEnumerator): Likewise, for IEnumerator.
+
+2004-07-13 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs: Fixed previous fix, it broke some error tests.
+
+2004-07-12 Martin Baulig <martin@ximian.com>
+
+ * enum.cs (Enum.Define): Call Emit() to emit the attributes.
+ Fixes #61293.
+
+2004-07-14 Martin Baulig <martin@ximian.com>
+
+ * decl.cs, expression.cs, generic.cs: Use a backqoute (`) and not
+ an exclamation mark (!) for the generic arity to reflect the
+ latest spec changes; ie. use "System.Collections.Generic.IList`1".
+
+2004-07-13 Martin Baulig <martin@ximian.com>
+
+ * cs-tokenizer.cs (Tokenizer.parse_less_than): Allow array rank
+ specifiers being part of a type argument.
+
+2004-07-13 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.ResolveAsTypeStep): Use the full `!'
+ name for generic types.
+
+2004-07-13 Martin Baulig <martin@ximian.com>
+
+ * assign.cs (Assign.DoResolve): Moved the CS0131 check up a little
+ bit to fix #60119.
+
+2004-07-09 Miguel de Icaza <miguel@ximian.com>
+
+ * assign.cs (LocalTemporary): Add new argument: is_address,If
+ `is_address' is true, then the value that we store is the address
+ to the real value, and not the value itself.
+
+ * ecore.cs (PropertyExpr): use the new local temporary
+ stuff to allow us to handle X.Y += z (where X is a struct)
+
+2004-07-08 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Lock.Resolve): Set ec.NeedReturnLabel() if we do
+ not always return, just like we're doing in Using.Resolve().
+
+2004-07-07 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay (fixed_statement): flag this as Pinned.
+
+2004-07-06 Miguel de Icaza <miguel@ximian.com>
+
+ * typemanager.cs (TypeManager): Removed MakePinned method, this
+ mechanism is replaced with the .NET 2.x compatible mechanism of
+ calling `ILGenerator.DeclareLocal (Type t, bool pinned)'.
+
+ * statement.cs (LocalInfo): Remove MakePinned, add Pinned property
+ Rename `Fixed' to `Pinned' as a flag, to distinguish from the
+ `IsFixed' property which has a different meaning.
+
+2004-07-02 Raja R Harinath <rharinath@novell.com>
+
+ * ecore.cs (DoSimpleNameResolve): Expand CS0038 check to all names
+ visible from inside a nested class, not just the names of the
+ immediately enclosing class.
+ Fix for bug #60730.
+
+2004-06-24 Raja R Harinath <rharinath@novell.com>
+
+ * expression.cs (BetterConversion): Remove buggy special-case
+ handling of "implicit constant expression conversions". At this
+ point, we already know that the conversion is possible -- we're
+ only checking to see which is better.
+
+2004-06-24 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added error CS0210 test.
+
+2004-06-24 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added error CS0134 test.
+
+2004-06-24 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #52507
+ * cs-parser.jay: Added error CS0145 test.
+
+2004-06-24 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (Operator.Define): Added test for errors CS0553, CS0554.
+
+2004-06-23 Ben Maurer <bmaurer@ximian.com>
+
+ * expression.cs (StackAlloc.Resolve): The argument may not
+ be a constant; deal with this case.
+
+2004-06-23 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (IndexerName_GetIndexerName): Renamed to
+ GetIndexerAttributeValue.
+ (ScanForIndexerName): Renamed to GetIndexerNameAttribute.
+
+ * class.cs (Indexer.Define): Added error tests for CS0415,
+ CS0609.
+
+2004-06-23 Miguel de Icaza <miguel@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): Keep field code in sync with
+ property code.
+
+2004-06-23 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (UsageVector.MergeChild): If we're a loop and we
+ neither return nor throw, reset the barrier as well. Fixes #60457.
+
+2004-06-22 Atsushi Enomoto <atsushi@ximian.com>
+
+ * class.cs : EventAttributes is now set to None by default.
+ This fixes bug #60459.
+
+2004-06-18 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #60219
+ * class.cs (ConstructorInitializer.GetOverloadedConstructor):
+ Don't throw exception but return null (it's sufficient now).
+
+2004-06-18 Marek Safar <marek.safar@seznam.cz>
+
+ * typemanager.cs (GetArgumentTypes): Faster implementation.
+
+2004-06-18 Martin Baulig <martin@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): Check whether we're an
+ EmptyCast which a Constant child. Fixes #60333.
+
+2004-06-17 Ben Maurer <bmaurer@ximian.com>
+
+ * statement.cs (EmitCollectionForeach): Account for the fact that
+ not all valuetypes are in areas which we can take the address of.
+ For these variables, we store to a temporary variable. Also, make
+ sure that we dont emit a `callvirt' on a valuetype method.
+
+2004-06-15 Marek Safar <marek.safar@seznam.cz>
+
+ * expression.cs (StackAlloc.DoReSolve): Added test for
+ negative parameter (CS0247).
+
+2004-06-15 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #59792
+ * class.cs: (Event.DelegateMethod.Emit): Added synchronization flag.
+
+2004-06-15 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #59781
+ * expression.cs: (Binary.DoNumericPromotions): Added conversion for
+ ulong.
+
+2004-06-14 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #58254 & cs1555.cs, cs1556.cs
+ * driver.cs (MainDriver): Added tests for errors CS1555, CS1556.
+
+2004-06-14 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Added error CS1669 test for indexers.
+
+2004-06-18 Martin Baulig <martin@ximian.com>
+
+ * generics.cs (GenericMethod.ctor): Don't take an Attributes
+ argument. Fixes #60441.
+
+2004-06-16 Ben Maurer <bmaurer@ximian.com>
+ * ecore.cs (MethodGroupExpr.Name): Revert Martin's patch.
+ The name needs to have the actual name of the method in order
+ for other tests (such as the one in OverloadResolve for Invoke
+ on a delegate) to work. As well, it does not really help
+ error reporting because the method group had multiple methods.
+ * Makefile: Remove MCS_DEBUG, you can enable with the DEBUG_FLAGS.
+ Make profiling work.
+
+2004-06-13 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay: Don't allow generic attributes.
+
+2004-06-13 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MemberBase.DoDefineBase): New protected method.
+ (MemberBase.DoDefine): Compute the `flags' in the new
+ DoDefineBase() which must be called first.
+ (Method.Define): Call DoDefineBase() first so we have the flags
+ when defining the generic method.
+
+ * cs-parser.jay (interface_method_declaration): Support generic methods.
+
+2004-06-13 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (TypeName): Removed.
+ (MemberName): Removed TypeName and MemberNow; now we just have
+ MemberName.
+
+ * cs-parser.jay: Don't distinguish between type arguments and type
+ parameters in the grammar and simplified the rules a bit. The
+ reduce/reduce conflicts are now gone (except the one we inherited
+ from mcs).
+
+2004-06-11 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.IsParamsMethodApplicable): We need to
+ call this twice: for params and varargs methods.
+
+2004-06-11 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs:
+ (FieldBase.DoDefine, PropertyBase.DoDefine): Added error test CS0610.
+
+2004-06-11 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute.GetValidTargets): Made public.
+
+ * class.cs:
+ (AbstractPropertyEventMethod): New class for better code sharing.
+ (AbstractPropertyEventMethod.ApplyAttributeBuilder): Add error
+ CS1667 report.
+ (PropertyMethod, DelegateMethod): Derived from AbstractPropertyEventMethod
+
+2004-06-09 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay: Removed a reduce/reduce conflict.
+
+2004-06-03 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.GetMemberAccess): Renamed to
+ GetSimpleName() and return a SimpleName.
+
+ * ecore.cs (SimpleName.Arguments): New public field.
+ (SimpleName): Added overloaded ctor which takes an additional
+ TypeArguments argument.
+ (SimpleName.SimpleNameResolve): Added support for generic methods.
+ (MethodGroupExpr.ResolveGeneric): New public method. The code was
+ formerly in MemberAccess.DoResolve(), but we also need it in
+ SimpleNameResolve().
+
+ * expression.cs (MemberAccess.DoResolve): Use the new
+ MethodGroupExpr.ResolveGeneric().
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs: If possible, use lookuptypedirect here. We can only do
+ this if there is no `.' after the namespace. Avoids using
+ LookupType, which does lots of slow processing.
+ (FindNestedType) New method, does what it says :-).
+ * namespace.cs: use LookupTypeDirect.
+ * rootcontext.cs: use membercache, if possible.
+ * typemanager.cs (LookupTypeDirect): Cache negative hits too.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs:
+ According to the spec,
+
+ In a member access of the form E.I, if E is a single identifier,
+ and if the meaning of E as a simple-name (§7.5.2) is a constant,
+ field, property, localvariable, or parameter with the same type as
+ the meaning of E as a type-name (§3.8), then both possible
+ meanings of E are permitted.
+
+ We did not check that E as a simple-name had the same type as E as
+ a type name.
+
+ This trivial check gives us 5-7% on bootstrap time.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs (Invocation.OverloadResolve): Avoid the
+ use of hashtables and boxing here by allocating on demand.
+
+2004-05-30 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs (RootContext.LookupType): Don't cache things if
+ we're doing a silent lookup. Don't try to lookup nested types in
+ TypeManager.object_type (thanks to Ben Maurer).
+
+2004-05-30 Martin Baulig <martin@ximian.com>
+
+ Committing a patch from Ben Maurer.
+
+ * rootcontext.cs (RootContext.LookupType): Cache negative results.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * convert.cs: add a trivial cache for overload operator resolution.
+
+2004-05-31 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs
+ (AttributeTester.GetObsoleteAttribute): Returns instance of
+ ObsoleteAttribute when type is obsolete.
+
+ * class.cs
+ (TypeContainer.VerifyObsoleteAttribute): Override.
+ (Method.GetSignatureForError): New method for usage when MethodBuilder is null.
+ (MethodCode.VerifyObsoleteAttribute): Override.
+ (MemberBase.VerifyObsoleteAttribute): Override.
+
+ * decl.cs
+ (MemberCore.CheckUsageOfObsoleteAttribute): Tests presence of ObsoleteAttribute
+ and report proper error.
+
+ *delegate.cs
+ (Delegate.VerifyObsoleteAttribute): Override.
+
+ * ecore.cs
+ (Expression.CheckObsoleteAttribute): Tests presence of ObsoleteAttribute
+ and report proper error.
+ (FieldExpr.DoResolve): Added tests for ObsoleteAttribute.
+
+ * enum.cs
+ (Enum.GetObsoleteAttribute): Returns ObsoleteAttribute for both enum type
+ and enum member.
+
+ * expression.cs
+ (Probe.DoResolve, Cast.DoResolve, LocalVariableReference.DoResolve,
+ New.DoResolve, SizeOf.DoResolve, TypeOf.DoResolce, MemberAccess.DoResolve):
+ Added test for ObsoleteAttribute.
+
+ * statement.cs
+ (Catch): Derived from Statement.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs: If possible, use lookuptypedirect here. We can only do
+ this if there is no `.' after the namespace. Avoids using
+ LookupType, which does lots of slow processing.
+ (FindNestedType) New method, does what it says :-).
+ * namespace.cs: use LookupTypeDirect.
+ * rootcontext.cs: use membercache, if possible.
+ * typemanager.cs (LookupTypeDirect): Cache negative hits too.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs:
+ According to the spec,
+
+ In a member access of the form E.I, if E is a single identifier,
+ and if the meaning of E as a simple-name (§7.5.2) is a constant,
+ field, property, localvariable, or parameter with the same type as
+ the meaning of E as a type-name (§3.8), then both possible
+ meanings of E are permitted.
+
+ We did not check that E as a simple-name had the same type as E as
+ a type name.
+
+ This trivial check gives us 5-7% on bootstrap time.
+
+2004-05-30 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #59071 & cs0160.cs
+ * statement.cs (Try.Resolve): Check here whether order of catch
+ clauses matches their dependencies.
+
+2004-05-30 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #58624
+ * ecore.cs (SimpleName.SimpleNameResolve): Added test for
+ unsafe type.
+
+2004-05-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs (Invocation.OverloadResolve): Avoid the
+ use of hashtables and boxing here by allocating on demand.
+
+2004-05-30 Martin Baulig <martin@ximian.com>
+
+ * rootcontext.cs (RootContext.LookupType): Don't cache things if
+ we're doing a silent lookup. Don't try to lookup nested types in
+ TypeManager.object_type (thanks to Ben Maurer).
+
+2004-05-30 Martin Baulig <martin@ximian.com>
+
+ Committing a patch from Ben Maurer.
+
+ * rootcontext.cs (RootContext.LookupType): Cache negative results.
+
+2004-05-29 Martin Baulig <martin@ximian.com>
+
+ * class.cs (IMethodData.ShouldIgnore): New method.
+
+ * typemanager.cs (TypeManager.MethodFlags): Don't take a
+ `Location' argument, we don't need it anywhere. Use
+ `IMethodData.ShouldIgnore ()' instead of
+ `MethodData.GetMethodFlags ()'.
+ (TypeManager.AddMethod): Removed.
+ (TypeManager.AddMethod2): Renamed to AddMethod.
+
+2004-05-29 Martin Baulig <martin@ximian.com>
+
+ Committing a patch from Benjamin Jemlich <pcgod@gmx.net>.
+
+ * convert.cs (Convert.ImplicitReferenceConversion): If we're
+ converting from a class type S to an interface type and we already
+ have an object on the stack, don't box it again. Fixes #52578.
+
+2004-05-29 Martin Baulig <martin@ximian.com>
+
+ * class.cs (ConstructorInitializer.GetOverloadedConstructor):
+ Added support for `params' parameters. Fixes #59267.
+
+2004-05-29 Martin Baulig <martin@ximian.com>
+
+ * literal.cs (NullPointer): Provide a private .ctor which sets
+ `type' to TypeManager.object_type. Fixes #59048.
+
+2004-05-29 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.ResolveMemberAccess): If we're an
+ EventExpr, set `ee.InstanceExpression = left'. Fixes #59188.
+
+ * ecore.cs (EventExpr.instance_expr): Make the field private.
+
+2004-05-26 Marek Safar <marek.safar@seznam.cz>
+
+ Fixed bug #50080 & cs0214-2.cs
+ * expression.cs (Cast.DoResolve): Check unsafe context here.
+
+ * statement.cs (Resolve.DoResolve): Likewise.
+
+2004-05-26 Martin Baulig <martin@ximian.com>
+
+ * namespace.cs (NamespaceEntry.Lookup): Added `bool silent'.
+
+ * rootcontext.cs (RootContext.NamespaceLookup): Added `bool silent'.
+ (RootContext.LookupType): Pass down the `silent' flag.
+
+2004-05-25 Martin Baulig <martin@ximian.com>
+
+ * expression.cs
+ (MethodGroupExpr.IdenticalTypeName): New public property.
+ (Invocation.DoResolve): Don't report a CS0176 if the "instance"
+ expression actually refers to a type.
+
+2004-05-25 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.DoResolve): Applied Ben Maurer's patch
+ for #56176 and made it actually work.
+
+2004-05-25 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (Expression.CacheTemporaries): Make this virtual.
+ (FieldExpr, PropertyExpr): Override and implement
+ CacheTemporaries. Fixes #52279.
+
+2004-05-25 Miguel de Icaza <miguel@ximian.com>
+
+ * location.cs: In the new compiler listing a file twice is a
+ warning, not an error.
+
+2004-05-24 Martin Baulig <martin@ximian.com>
+
+ * enum.cs (Enum.DefineType): For the `BaseType' to be a
+ TypeLookupExpression; otherwise, report a CS1008. Fixes #58571.
+
+2004-05-24 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.FindType): Try doing an alias lookup before
+ walking the `using' list. Fixes #53921.
+
+2004-05-24 Martin Baulig <martin@ximian.com>
+
+ * const.cs (Const.LookupConstantValue): Added support for
+ EmptyCast's; fixes #55251.
+
+2004-05-24 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (SimpleName.SimpleNameResolve): Renamed to
+ DoSimpleNameResolve() and provide a SimpleNameResolve() wrapper
+ which does the CS0135 check. The reason is that we first need to
+ check whether the variable actually exists.
+
+2004-05-24 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MemberBase.DoDefine): Use DeclSpace.FindType() rather
+ than RootContext.LookupType() to find the explicit interface
+ type. Fixes #58584.
+
+2004-05-24 Raja R Harinath <rharinath@novell.com>
+
+ * Makefile: Simplify. Use executable.make.
+ * mcs.exe.sources: New file. List of sources of mcs.exe.
+
+2004-05-24 Anders Carlsson <andersca@gnome.org>
+
+ * decl.cs:
+ * enum.cs:
+ Use the invariant culture when doing String.Compare for CLS case
+ sensitivity.
+
+2004-05-23 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.FindType): Only check the `using' list if we
+ don't have any dots. Fixes #52622, added cs0246-8.cs.
+
+ * namespace.cs (NamespaceEntry.Lookup): Likewise.
+
+2004-05-23 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (MemberBase.Define): Reuse MemberType member for
+ resolved type. Other methods can use it too.
+
+2004-05-23 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (SimpleName.SimpleNameResolve): Only report a CS0135 if
+ the variable also exists in the current block (otherwise, we need
+ to report a CS0103). Fixes #58670.
+
+2004-05-23 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (Reachability.Reachable): Compute this
+ on-the-fly rather than storing it as a field.
+
+2004-05-23 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (Reachability.And): Manually compute the
+ resulting `barrier' from the reachability.
+
+2004-05-23 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #57835
+ * attribute.cs (AttributeTester.GetMethodObsoleteAttribute): Returns
+ instance of ObsoleteAttribute when symbol is obsolete.
+
+ * class.cs
+ (IMethodData): Extended interface for ObsoleteAttribute support.
+
+2004-05-22 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs: Fix bug #55970
+
+2004-05-22 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #52705
+ * attribute.cs
+ (GetObsoleteAttribute): New method. Creates the instance of
+ ObsoleteAttribute.
+ (AttributeTester.GetMemberObsoleteAttribute): Returns instance of
+ ObsoleteAttribute when member is obsolete.
+ (AttributeTester.Report_ObsoleteMessage): Common method for
+ Obsolete error/warning reporting.
+
+ * class.cs
+ (TypeContainer.base_classs_type): New member for storing parent type.
+
+ * decl.cs
+ (MemberCore.GetObsoleteAttribute): Returns instance of ObsoleteAttribute
+ for this MemberCore.
+
+2004-05-21 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs, const.cs: Fix bug #58590
+
+2004-05-21 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.MergeTopBlock): Don't check for
+ out parameters if the end of the method is unreachable. Fixes
+ #58098.
+
+2004-05-21 Marek Safar <marek.safar@seznam.cz>
+
+ * codegen.cs, cs-parser.jay: Removed SetAttributes method.
+ Hari was right, why extra method.
+
+2004-05-21 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs, cs-parser.jay: Fix errors/cs0579-7.cs.
+
+2004-05-20 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs: Convert this file to Unix mode - like the original
+ version in mcs is.
+
+2004-05-20 Martin Baulig <martin@ximian.com>
+
+ * attribute.cs: Convert this file to Unix mode - like the original
+ version in mcs is.
+
+2004-05-19 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #58688 (MCS does not report error when the same attribute
+ is assigned twice)
+
+ * attribute.cs (Attribute.Emit): Distinction between null and default.
+
+2004-05-19 Raja R Harinath <rharinath@novell.com>
+
+ * cs-parser.jay (attribute): Create a GlobalAttribute for the case
+ of a top-level attribute without an attribute target.
+ * attribute.cs (Attribute.Error_AttributeConstructorMismatch):
+ Make non-static.
+ (Attribute.Conditional_GetConditionName),
+ (Attribute.Obsolete_GetObsoleteMessage): Update.
+ (Attribute.IndexerName_GetIndexerName): New. Attribute-specific
+ part of ScanForIndexerName.
+ (Attribute.CanIgnoreInvalidAttribute): New function.
+ (Attribute.ScanForIndexerName): Move to ...
+ (Attributes.ScanForIndexerName): ... here.
+ (Attributes.Attrs): Rename from now-misnamed AttributeSections.
+ (Attributes.Search): New internal variant that can choose not to
+ complain if types aren't resolved. The original signature now
+ complains.
+ (Attributes.GetClsCompliantAttribute): Use internal variant, with
+ complaints suppressed.
+ (GlobalAttribute.CheckAttributeType): Overwrite ds.NamespaceEntry
+ only if it not useful.
+ (CanIgnoreInvalidAttribute): Ignore assembly attribute errors at
+ top-level for attributes that are shared between the assembly
+ and a top-level class.
+ * parameter.cs (ImplicitParameter): Rename from ParameterAtribute.
+ * class.cs: Update to reflect changes.
+ (DefineIndexers): Fuse loops.
+ * codegen.cs (GetAssemblyName): Update to reflect changes. Accept
+ a couple more variants of attribute names.
+
+2004-05-18 Marek Safar <marek.safar@seznam.cz>
+
+ Fix bug #52585 (Implemented explicit attribute declaration)
+
+ * attribute.cs:
+ (Attributable.ValidAttributeTargets): New abstract method. It gets
+ list of valid attribute targets for explicit target declaration.
+ (Attribute.Target): It holds target itself.
+ (AttributeSection): Removed.
+ (Attribute.CheckTargets): New method. It checks whether attribute
+ target is valid for the current element.
+
+ * class.cs:
+ (EventProperty): New class. For events that are declared like
+ property (with add and remove accessors).
+ (EventField): New class. For events that are declared like field.
+ class.cs
+
+ * cs-parser.jay: Implemented explicit attribute target declaration.
+
+ * class.cs, decl.cs, delegate.cs, enum.cs, parameter.cs:
+ Override ValidAttributeTargets.
+
+ * parameter.cs:
+ (ReturnParameter): Class for applying custom attributes on
+ the return type.
+ (ParameterAtribute): New class. Class for applying custom
+ attributes on the parameter type.
+
+2004-05-17 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (MemberBase.DoDefine): Pass UNSAFE on interface
+ definitions.
+
+ (Method): Allow UNSAFE here.
+
+ * modifiers.cs: Support unsafe reporting.
+
+2004-05-17 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs: Fix bug #58478.
+
+2004-05-17 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * statement.cs: When checking for unreachable code on an EmptyStatement,
+ set the location. Fixes bug #58488.
+
+2004-05-13 Miguel de Icaza <miguel@ximian.com>
+
+ * driver.cs: Add -pkg handling.
+
+ From Gonzalo: UseShelLExecute=false
+
+2004-05-12 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs:
+ (Attribute.GetAttributeTargets): New method. Gets AttributeTargets
+ for attribute.
+ (Attribute.IsClsCompliaceRequired): Moved to base for better
+ accesibility.
+ (Attribute.UsageAttribute): New property for AttributeUsageAttribute
+ when attribute is AttributeUsageAttribute.
+ (Attribute.GetValidTargets): Simplified.
+ (Attribute.GetAttributeUsage): New method returns AttributeUsage
+ attribute for this type.
+ (Attribute.ApplyAttributes): Method renamed to Emit and make
+ non-static.
+ (GlobalAttributeSection): New class for special handling of global
+ attributes (assembly, module).
+ (AttributeSection.Emit): New method.
+
+ * class.cs: Implemented Attributable abstract methods.
+ (MethodCore.LabelParameters): Moved to Parameter class.
+ (Accessor): Is back simple class.
+ (PropertyMethod): Implemented Attributable abstract class.
+ (DelegateMethod): Implemented Attributable abstract class.
+ (Event): New constructor for disctintion between normal Event
+ and Event with accessors.
+
+ * cs-parser.jay: Used new Event ctor and GlobalAttributeSection.
+
+ * codegen.cs, const.cs, decl.cs, delegate.cs:
+ (CommonAssemblyModulClass): Implemented Attributable abstract class
+ and simplified.
+
+ * enum.cs: Implement IAttributeSupport interface.
+ (EnumMember): New class for emum members. Implemented Attributable
+ abstract class
+
+ * parameter.cs:
+ (ParameterBase): Is abstract.
+ (ReturnParameter): New class for easier [return:] attribute handling.
+
+ * typemanager.cs: Removed builder_to_attr.
+
+2004-05-11 Raja R Harinath <rharinath@novell.com>
+
+ Fix bug #57151.
+ * attribute.cs (Attribute.GetPositionalValue): New function.
+ * class.cs (TypeContainer.VerifyMembers): New function.
+ (TypeContainer.Emit): Use it.
+ (ClassOrStruct): New base class for Class and Struct.
+ (ClassOrStruct.ApplyAttributeBuilder): New function. Note if
+ StructLayout(LayoutKind.Explicit) was ascribed to the struct or
+ class.
+ (ClassOrStruct.VerifyMembers): If the struct is explicitly laid out,
+ then each non-static field should have a FieldOffset attribute.
+ Otherwise, none of the fields should have a FieldOffset attribute.
+ * rootcontext.cs (RootContext.ResolveCore): Resolve StructLayout
+ and FieldOffset attributes.
+ * typemanager.cs (TypeManager.struct_layout_attribute_type)
+ (TypeManager.field_offset_attribute_type): New core types.
+ (TypeManager.InitCoreTypes): Initialize them.
+
+2004-05-11 Michal Moskal <malekith@pld-linux.org>
+
+ * class.cs (Event.RemoveDelegateMethod.DelegateMethodInfo):
+ Return correct type.
+ From bug #58270.
+
+2004-05-09 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Binary.DoNumericPromotions): 0 long constant can
+ be implicitly converted to ulong.
+
+ * expression.cs: The logic for allowing operator &, | and ^ worked
+ was wrong, it worked before because we did not report an error in
+ an else branch. Fixes 57895.
+
+ * class.cs: Applied patch from iain@mccoy.id.au Iain McCoy to
+ allow volatile fields to be reference types.
+
+2004-05-07 Miguel de Icaza <miguel@ximian.com>
+
+ * driver.cs: Add support for /debug-
+
+2004-05-07 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType, Attribute.ResolveType):
+ Add a 'complain' parameter to silence errors.
+ (Attribute.Resolve): Update to changes. Put in sanity check to catch
+ silently overlooked type-resolutions.
+ (Attribute.ScanForIndexerName, Attribute.DefinePInvokeMethod): Update
+ to reflect changes.
+ (Attributes.Search): New function.
+ (Attributes.Contains, Attributes.GetClsCompliantAttribute): Use Search.
+ (Attributes.GetAttributeFullName): Remove hack.
+ * class.cs (MethodCore.LabelParameters, MethodData.ApplyAttributes):
+ Update to reflect changes.
+ * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute):
+ Use Attributes.Search instead of nested loops.
+
+2004-05-07 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs:
+ (MemberCore.Flags): Extended for caching presence of CLSCompliantAttribute.
+ (MemberCore.VerifyClsCompliance): Implemented CS3019 error report.
+ (DeclSpace.GetClsCompliantAttributeValue): Returns simple bool.
+
+ * report.cs: (Report.Warning): Renamed to Warning_T because of
+ parameter collision.
+
+2004-05-05 Raja R Harinath <rharinath@novell.com>
+
+ * expression.cs (MemberAccess.ResolveMemberAccess):
+ Exit with non-zero status after Report.Error.
+ * rootcontext.cs (RootContext.BootstrapCorlib_ResolveDelegate):
+ Likewise.
+ * typemanager.cs (TypeManager.CoreLookupType): Likewise.
+
+2004-05-04 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * support.cs: Don't hang when the file is empty.
+
+2004-05-04 Lluis Sanchez Gual <lluis@ximian.com>
+
+ * support.cs: In SeekableStreamReader, compute the preamble size of the
+ underlying stream. Position changes should take into account that initial
+ count of bytes.
+
+2004-05-03 Todd Berman <tberman@sevenl.net>
+
+ * driver.cs: remove unused GetSysVersion function.
+
+2004-05-03 Todd Berman <tberman@sevenl.net>
+
+ * driver.cs: Remove the hack from saturday, as well as the hack
+ from jackson (LoadAssemblyFromGac), also adds the CWD to the
+ link_paths to get that bit proper.
+
+2004-05-01 Todd Berman <tberman@sevenl.net>
+
+ * driver.cs: Try a LoadFrom before a Load, this checks the current
+ path. This is currently a bug in mono that is be fixed, however, this
+ provides a workaround for now. This will be removed when the bug
+ is fixed.
+
+2004-05-01 Sebastien Pouliot <sebastien@ximian.com>
+
+ * CryptoConvert.cs: Updated to latest version. Fix issue with
+ incomplete key pairs (#57941).
+
+2004-05-01 Todd Berman <tberman@sevenl.net>
+
+ * driver.cs: Remove '.' from path_chars, now System.* loads properly
+ from the GAC
+
+2004-04-30 Jackson Harper <jackson@ximian.com>
+
+ * codegen.cs: Open keys readonly.
+
+2004-04-30 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * typemanager.cs: don't report cyclic struct layout when a struct
+ contains 2 or more fields of the same type. Failed for Pango.AttrShape
+ which has 2 Pango.Rectangle fields.
+
+2004-04-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Handle IntPtr comparisons with IL code
+ rather than a method call.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (PropertyExpr.FindAccessor): New private method. Walk
+ the list of PropertyInfo's in class hierarchy and find the
+ accessor. Fixes #56013.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.CheckStructCycles): Fixed.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ Applying a patch from Benjamin Jemlich <pcgod@gmx.net>.
+
+ * ecore.cs (FieldExpr.AddressOf): Make this work for valuetypes.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * class.cs (ConstructorInitializer.Resolve): Check whether the
+ parent .ctor is accessible. Fixes #52146.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ Applying a patch from Benjamin Jemlich <pcgod@gmx.net>.
+
+ * statement.cs (Using.EmitLocalVariableDecls): Use
+ TypeManager.idisposable_type, not typeof (IDisposable).
+ (Foreach.EmitCollectionForeach): Added support for valuetypes.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Event.Define): Don't emit the field and don't set
+ RTSpecialName and SpecialName for events on interfaces. Fixes
+ #57703.
+
+2004-04-29 Raja R Harinath <rharinath@novell.com>
+
+ Refactor Attribute.ApplyAttributes.
+ * attribute.cs (Attributable): New base class for objects that can
+ have Attributes applied on them.
+ (Attribute): Make AttributeUsage fields public.
+ (Attribute.GetFieldValue, Attribute.GetMarshal): Make non-static.
+ (Attribute.IsInternalCall): New property.
+ (Attribute.UsageAttr): Convert to a public read-only property.
+ (Attribute.CheckAttributeType): Use a DeclSpace, not an EmitContext.
+ (Attribute.ResolveType, Attribute.Resolve)
+ (Attribute.ScanForIndexerName): Update to reflect changes.
+ (Attribute.CheckAttributeTarget): Re-format.
+ (Attribute.ApplyAttributes): Refactor, to various
+ Attributable.ApplyAttributeBuilder methods.
+ * decl.cs (MemberCore): Make Attributable.
+ * class.cs (Accessor): Make Attributable.
+ (MethodData.ApplyAttributes): Use proper attribute types, not
+ attribute names.
+ (TypeContainer.LabelParameters): Pass Parameter to ApplyAttributes.
+ (TypeContainer.ApplyAttributeBuilder)
+ (Method.ApplyAttributeBuilder, Constructor.ApplyAttributeBuilder)
+ (Field.ApplyAttributeBuilder, Accessor.ApplyAttributeBuilder)
+ (PropertyBase.ApplyAttributeBuilder, Event.ApplyAttributeBuilder)
+ (Operator.ApplyAttributeBuilder): New factored-out methods.
+ * const.cs (Const.ApplyAttributeBuilder): Likewise.
+ * delegate.cs (Delegate.ApplyAttributeBuilder): Likewise.
+ * enum.cs (Enum.ApplyAttributeBuilder): Likewise.
+ * parameter.cs (ParameterBase): New Attributable base class
+ that can also represent Return types.
+ (Parameter): Update to the changes.
+
+2004-04-29 Jackson Harper <jackson@ximian.com>
+
+ * driver.cs: Prefer the corlib system version when looking for
+ assemblies in the GAC. This is still a hack, but its a better hack
+ now.
+
+2004-04-29 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs, enum.cs: Improved error 3005 reporting.
+
+ * report.cs (SymbolRelatedToPreviousError): New method for error reporting.
+ (related_symbols): New private member for list of symbols
+ related to reported error/warning.
+
+ * tree.cs: Do not use now obsolete Report.LocationOfPreviousError.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (Expression.Constantify): If we're an enum and
+ TypeManager.TypeToCoreType() doesn't give us another type, use
+ t.UnderlyingSystemType. Fixes #56178.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCache.SetupCacheForInterface): Look over all our
+ interfaces and for each interface, only add members directly
+ declared in that interface. Fixes #53255.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (ConditionalLogicalOperator): Use a temporary
+ variable for `left' to avoid that we evaluate it more than once;
+ bug #52588.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (ComposedCast.DoResolveAsTypeStep): Don't allow
+ `void[]' (CS1547).
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (LocalInfo.Resolve): Check whether the type is not
+ void (CS1547).
+
+ * class.cs (MemberBase.CheckParameters, FieldBase.DoDefine): Check
+ whether the type is not void (CS1547).
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Unary.DoResolveLValue): Override this and report
+ CS0131 for anything but Operator.Indirection.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ Committing a patch from Ben Maurer; see bug #50820.
+
+ * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540
+ check for classes.
+
+ * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for
+ classes.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ Committing a patch from Ben Maurer; see bug #50820.
+
+ * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540
+ check for classes.
+
+ * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for
+ classes.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Block.LookupLabel): Also lookup in implicit child blocks.
+ (Block.AddLabel): Call DoLookupLabel() to only search in the
+ current block.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * cfold.cs (ConstantFold.BinaryFold): Added special support for
+ comparing StringConstants and NullLiterals in Equality and Inequality.
+
+2004-04-28 Jackson Harper <jackson@ximian.com>
+
+ * driver.cs: Attempt to load referenced assemblies from the
+ GAC. This is the quick and dirty version of this method that
+ doesnt take into account versions and just takes the first
+ canidate found. Will be good enough for now as we will not have more
+ then one version installed into the GAC until I update this method.
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.CheckStructCycles): New public
+ static method to check for cycles in the struct layout.
+
+ * rootcontext.cs (RootContext.PopulateTypes): Call
+ TypeManager.CheckStructCycles() for each TypeContainer.
+ [Note: We only need to visit each type once.]
+
+2004-04-28 Martin Baulig <martin@ximian.com>
+
+ * constant.cs (StringConstant.Emit): Emit Ldnull if we're null.
+
+ * const.cs (Const.LookupConstantValue): Return a `bool' signalling
+ success and added `out object value'. Use a `bool resolved' field
+ to check whether we've already been called rather than
+ `ConstantValue != null' since this breaks for NullLiterals.
+
+2004-04-28 Raja R Harinath <rharinath@novell.com>
+
+ * driver.cs (Driver.MainDriver) [IsModuleOnly]: Open code the
+ setting of this flag, since the 'set' method may be non-public.
+
+2004-04-28 Raja R Harinath <rharinath@novell.com>
+
+ * flowanalysis.cs (FlowBranchingException.LookupLabel): Add a null
+ check on current_vector.Block.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (BaseAccess.CommonResolve): Don't allow `base' in
+ a field initializer. Fixes #56459.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (PropertyExpr.DoResolve/DoResolveLValue): Check whether
+ we're not attempting to use an indexer. Fixes #52154.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Return): Don't create a return label if we don't
+ need it; reverts my change from January 20th. Thanks to Ben
+ Maurer for this.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ According to the spec, `goto' can only leave a nested scope, but
+ never enter it.
+
+ * statement.cs (Block.LookupLabel): Only lookup in the current
+ block, don't recurse into parent or child blocks.
+ (Block.AddLabel): Check in parent and child blocks, report
+ CS0140/CS0158 if we find a duplicate.
+ (Block): Removed this indexer for label lookups.
+ (Goto.Resolve): Call LookupLabel() on our current FlowBranching;
+ this already does the error reporting for us.
+
+ * flowanalysis.cs
+ (FlowBranching.UsageVector.Block): New public variable; may be null.
+ (FlowBranching.CreateSibling): Added `Block' argument.
+ (FlowBranching.LookupLabel): New public virtual method. Lookup a
+ label for the target of a `goto' and check whether we're not
+ leaving a `finally'.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're
+ a finite loop block, also do the ALWAYS->SOMETIMES for throws (not
+ just for returns).
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Block.AddLabel): Also check for implicit blocks
+ and added a CS0158 check.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranchingLoop): New class.
+ (FlowBranching.UsageVector.MergeJumpOrigins): Take a list of
+ UsageVector's instead of an ArrayList.
+ (FlowBranching.Label): Likewise.
+ (FlowBranching.UsageVector.MergeBreakOrigins): New method.
+ (FlowBranching.AddBreakVector): New method.
+
+2004-04-27 Miguel de Icaza <miguel@ximian.com>
+
+ * attribute.cs: Small regression fix: only convert the type if we
+ the type is different, fixes System.Drawing build.
+
+2004-04-27 Martin Baulig <martin@ximian.com>
+
+ * attribute.cs (Attribute.Resolve): If we have a constant value
+ for a named field or property, implicity convert it to the correct
+ type.
+
+2004-04-27 Raja R Harinath <rharinath@novell.com>
+
+ * statement.cs (Block.Block): Implicit blocks share
+ 'child_variable_names' fields with parent blocks.
+ (Block.AddChildVariableNames): Remove.
+ (Block.AddVariable): Mark variable as "used by a child block" in
+ every surrounding block.
+ * ecore.cs (SimpleName.SimpleNameResolve): If the name has already
+ been used in a child block, complain about violation of "Invariant
+ meaning in blocks" rule.
+ * cs-parser.jay (declare_local_variables): Don't use
+ AddChildVariableNames.
+ (foreach_statement): Don't create an implicit block: 'foreach'
+ introduces a scope.
+
+2004-04-23 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ImplicitNumericConversion): 0 is also positive when
+ converting from 0L to ulong. Fixes 57522.
+
+2004-04-22 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs (FindMemberToOverride): Fix wrong warning for case when
+ derived class hides via 'new' keyword field from base class (test-242.cs).
+ TODO: Handle this in the more general way.
+
+ * class.cs (CheckBase): Ditto.
+
+2004-04-22 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs (caching_flags): New member for storing cached values
+ as bit flags.
+ (MemberCore.Flags): New enum where bit flags for caching_flags
+ are defined.
+ (MemberCore.cls_compliance): Moved to caching_flags.
+ (DeclSpace.Created): Moved to caching_flags.
+
+ * class.cs: Use caching_flags instead of DeclSpace.Created
+
+2004-04-21 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (PropertyExpr.GetAccesor): Only perform the 1540 check
+ if we are only a derived class, not a nested class.
+
+ * typemanager.cs: Same as above, but do this at the MemberLookup
+ level (used by field and methods, properties are handled in
+ PropertyExpr). Allow for the qualified access if we are a nested
+ method.
+
+2004-04-21 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs: Refactoring.
+ (IMethodData): New inteface; Holds links to parent members
+ to avoid member duplication (reduced memory allocation).
+ (Method): Implemented IMethodData interface.
+ (PropertyBase): New inner classes for get/set methods.
+ (PropertyBase.PropertyMethod): Implemented IMethodData interface
+ (Event): New inner classes for add/remove methods.
+ (Event.DelegateMethod): Implemented IMethodData interface.
+
+ * cs-parser.jay: Pass DeclSpace to Event class for creation of valid
+ EmitContext (related to class.cs refactoring).
+
+2004-04-21 Raja R Harinath <rharinath@novell.com>
+
+ * delegate.cs (Delegate.VerifyApplicability): If the number of
+ arguments are the same as the number of parameters, first try to
+ verify applicability ignoring any 'params' modifier on the last
+ parameter.
+ Fixes #56442.
+
+2004-04-08 Martin Baulig <martin@ximian.com>
+
+ Merged latest changes into gmcs. Please keep this comment in
+ here, it makes it easier for me to see what changed in MCS since
+ the last time I merged.
+
+2004-04-16 Raja R Harinath <rharinath@novell.com>
+
+ * class.cs (TypeContainer.AddIndexer): Use
+ 'ExplicitInterfaceName' to determine if interface name was
+ explicitly specified. 'InterfaceType' is not initialized at this time.
+ (TypeContainer.DefineIndexers): Remove use of temporary list. The
+ Indexers array is already in the required order. Initialize
+ 'IndexerName' only if there are normal indexers.
+ (TypeContainer.DoDefineMembers): Don't initialize IndexerName.
+ (TypeContainer.Emit): Emit DefaultMember attribute only if
+ IndexerName is initialized.
+ Fixes #56300.
+
+2004-04-15 Benjamin Jemlich <pcgod@gmx.net>
+
+ * enum.cs (Enum.DefineType): Don't allow char as type for enum.
+ Fixes #57007
+
+2004-04-15 Raja R Harinath <rharinath@novell.com>
+
+ * attribute.cs (Attribute.CheckAttributeType): Check for ambiguous
+ attributes.
+ Fix for #56456.
+
+ * attribute.cs (Attribute.Resolve): Check for duplicate named
+ attributes.
+ Fix for #56463.
+
+2004-04-15 Miguel de Icaza <miguel@ximian.com>
+
+ * iterators.cs (MarkYield): track whether we are in an exception,
+ and generate code accordingly. Use a temporary value to store the
+ result for our state.
+
+ I had ignored a bit the interaction of try/catch with iterators
+ since their behavior was not entirely obvious, but now it is
+ possible to verify that our behavior is the same as MS .NET 2.0
+
+ Fixes 54814
+
+2004-04-14 Miguel de Icaza <miguel@ximian.com>
+
+ * iterators.cs: Avoid creating temporaries if there is no work to
+ do.
+
+ * expression.cs (ArrayAccess.EmitLoadOpcode): If dealing with
+ Enumerations, use TypeManager.EnumToUnderlying and call
+ recursively.
+
+ Based on the patch from Benjamin Jemlich (pcgod@gmx.net), fixes
+ bug #57013
+
+ (This.Emit): Use EmitContext.EmitThis to emit our
+ instance variable.
+
+ (This.EmitAssign): Ditto.
+
+ * ecore.cs (FieldExpr.Emit): Remove RemapToProxy special
+ codepaths, we will move all the functionality into
+ Mono.CSharp.This
+
+ (FieldExpr.EmitAssign): Ditto.
+
+ This fixes several hidden bugs that I uncovered while doing a code
+ review of this today.
+
+ * codegen.cs (EmitThis): reworked so the semantics are more clear
+ and also support value types "this" instances.
+
+ * iterators.cs: Changed so that for iterators in value types, we
+ do not pass the value type as a parameter.
+
+ Initialization of the enumerator helpers is now done in the caller
+ instead of passing the parameters to the constructors and having
+ the constructor set the fields.
+
+ The fields have now `assembly' visibility instead of private.
+
+2004-04-11 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Argument.Resolve): Check if fields passed as ref
+ or out are contained in a MarshalByRefObject.
+
+ * typemanager.cs, rootcontext.cs: Add System.Marshalbyrefobject as
+ another compiler type.
+
+2004-04-06 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs (Indexer.Define): use the new name checking method.
+ Also, return false on an error.
+ * cs-tokenizer.cs (IsValidIdentifier): Checks for a valid identifier.
+ (is_identifier_[start/part]_character): make static.
+
+2004-04-10 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Binary.ResolveOperator): Do no append strings
+ twice: since we can be invoked more than once (array evaluation)
+ on the same concatenation, take care of this here. Based on a fix
+ from Ben (bug #56454)
+
+2004-04-08 Sebastien Pouliot <sebastien@ximian.com>
+
+ * codegen.cs: Fix another case where CS1548 must be reported (when
+ delay-sign isn't specified and no private is available #56564). Fix
+ loading the ECMA "key" to delay-sign an assembly. Report a CS1548
+ error when MCS is used on the MS runtime and we need to delay-sign
+ (which seems unsupported by AssemblyBuilder - see #56621).
+
+2004-04-08 Marek Safar <marek.safar@seznam.cz>
+
+ * typemanager.cs (TypeManager.TypeToCoreType): Handle IntPtr too.
+ (TypeManager.ComputeNamespaces): Faster implementation for
+ Microsoft runtime.
+
+ * compiler.csproj: Updated AssemblyName to mcs.
+
+2004-05-11 Jackson Harper <jackson@ximian.com>
+
+ * Makefile: Preserve MONO_PATH
+
+2004-05-11 Jackson Harper <jackson@ximian.com>
+
+ * Makefile: Use mono and mcs to build gmcs
+
+2004-05-03 Miguel de Icaza <miguel@ximian.com>
+
+ * codegen.cs: Add patch from Robert Shade
+ <rshade@dvsconsulting.com>, use FileAccess.Read on the keyfile, to
+ sync with mcs.
+
+2004-05-02 Sebastien Pouliot <sebastien@ximian.com>
+
+ * CryptoConvert.cs: Updated to latest version. Fix issue with
+ incomplete key pairs (#57941).
+
+2004-04-08 Sebastien Pouliot <sebastien@ximian.com>
+
+ * codegen.cs: Fix another case where CS1548 must be reported (when
+ delay-sign isn't specified and no private is available #56564). Fix
+ loading the ECMA "key" to delay-sign an assembly. Report a CS1548
+ error when MCS is used on the MS runtime and we need to delay-sign
+ (which seems unsupported by AssemblyBuilder - see #56621).
+
+2004-04-29 Jackson Harper <jackson@ximian.com>
+
+ * Makefile: Set MONO_PATH to use the bootstrap corlib
+ * driver.cs: Check the GAC for referenced assemblies.
+
+2004-04-29 Martin Baulig <martin@ximian.com>
+
+ * Makefile (gmcs.exe): Set MONO_PATH to use `../class/lib/net_2_0'.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Binary.ResolveOperator): Added special case for
+ Equality/Inequality between a type parameter and a null literal.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Check null literal -> type parameter conversions.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Enforce the
+ `class' and `struct' constraints.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (SpecialConstraint): New public enum.
+ (Constraints.Resolve): Added support for the `class' and `struct'
+ constraints.
+
+ * cs-parser.jay (type_parameter_constraint): Added support for the
+ `class' and `struct' constraints.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * support.cs (GenericConstraints): Replaced `Types' by
+ `ClassConstraint' and `InterfaceConstraints'; added
+ `HasClassConstraint'.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * generic.cs
+ (Constraints.InterfaceConstraints): New public property.
+ (Constraints.Types): Make this property public
+ (TypeParameter): Implement IMemberContainer.
+ (TypeParameter.Define): Take a `GenericTypeParameterBuilder'
+ instead of a TypeBuilder/MethodBuilder; pass the interface
+ constraints to TypeManager.AddTypeParameter().
+ (TypeParameter.DefineType): Just take an EmitContext and no
+ TypeBuilder/MethodBuilder. Use the new public API.
+
+ * typemanager.cs (TypeManager.AddTypeParameter): Added
+ `TypeExpr[]' argument; add the interfaces to the
+ `builder_to_ifaces' hash.
+ (TypeManager.LookupMemberContainer): For
+ GenericTypeParameterBuilders, get the TypeParameter from the
+ `builder_to_type_param'.
+ (TypeManager.FindMembers): For GenericTypeParameterBuilders, get
+ the TypeParameter and call FindMembers on it.
+
+2004-04-07 Martin Baulig <martin@ximian.com>
+
+ * class.cs
+ (MethodCore.GenericMethod): Moved this field here from Method.
+ (MethodCore.IsDuplicateImplementation): Take the number of type
+ parameters into account if we're a generic method.
+
+ * expression.cs (Invocation.InferTypeArguments): Don't return true
+ if `arguments' is null; we still need to check whether we actually
+ don't need to infer anything in this case.
+ (MemberAccess): Merged the functionality from GenericMemberAccess
+ into this class.
+
+ * generic.cs (GenericMemberAccess): Removed.
+
+2004-04-05 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCore): For generic classes, interfaces and
+ structs, `Name' now includes the number of type parameters
+ ("Stack!1.Node!1").
+ (DeclSpace.FindType): Removed the `num_type_args' argument; we now
+ encode the number of type arguments in the type name.
+
+ * expression.cs (Expression.MemberLookup): Removed the
+ `num_type_args' argument; we now encode the number of type
+ arguments in the type name.
+
+ * ecore.cs (SimpleName): Encode the number of type arguments in
+ the type name itself.
+
+ * generic.cs (ConstructedType): Likewise.
+
+ * tree.cs (Tree.RecordDecl): Take a `string' instead of a
+ `MemberName'; we now include the number of type parameters in the
+ type name.
+
+ * typemanager.cs (TypeManager.CheckGeneric): Removed.
+ (TypeManager.MemberLookup): Removed the
+ `num_type_args' argument; we now encode the number of type
+ arguments in the type name.
+
+2004-04-03 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCore.ctor): Take a MemberName instead of a sting.
+ (MemberCore.MemberName): Moved here from MemberBase.
+ (DeclSpace.SetParameterInfo): Just take the constraints as an
+ ArrayList; we already have the type parameters in our
+ `MemberName'; also do the CS0080 reporting here.
+
+ * cs-parser.jay (struct_declaration): Use `member_name' instead of
+ `IDENTIFIER opt_type_parameter_list'; when constructing our
+ `MemberName', it'll already include our type parameters.
+ (class_declaration, interface_declaration): Likewise.
+ (delegate_declaration): Likewise.
+ (MakeName): Take a MemberName and return a MemberName.
+ The following two changes are required to avoid shift/reduce conflicts:
+ (member_name): Don't include a TypeName anymore; ie. this is now
+ just 'IDENTIFIER opt_type_parameter_list'.
+ (property_declaration, event_declaration): Use a
+ `namespace_or_type_name' instead of a `member_name'.
+
+2004-04-03 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberName): Renamed to `TypeName' and created a new
+ `MemberName' class.
+ (TypeName): Formerly known as MemberName.
+
+ * namespace.cs (NamespaceEntry.UsingAlias): Take a `TypeName'
+ instead of a `MemberName'.
+
+ * cs-parser.jay (namespace_or_type_name): Create a TypeName.
+ (member_name): New rule; create a MemberName.
+
+2004-04-02 Martin Baulig <martin@ximian.com>
+
+ * namespace.cs (NamespaceEntry.VerifyUsing): Added error checking
+ (CS0305 and CS0308).
+
+2004-04-02 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericMemberAccess.ResolveAsTypeStep): Added
+ support for nested types.
+
+2004-04-02 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (IAlias): New public interface.
+ (TypeExpr, TypeExpression): Implement IAlias.
+ (TypeAliasExpression): New public class.
+
+ * namespace.cs (Namespace): Implement IAlias.
+ (Namespace.Lookup): Return an IAlias instead on an object.
+ (Namespace.DefineName): Take an IAlias instead of an object.
+ (NamespaceEntry.AliasEntry.Resolve): Return an IAlias instead of
+ an object.
+ (NamespaceEntry.UsingAlias): Take a Membername instead of an
+ Expression.
+ (NamespaceEntry.LookupAlias): Return an IAlias instead on an
+ object.
+ (NamespaceEntry.Lookup): Likewise.
+
+ * rootcontext.cs (RootContext.LookupType): Return a TypeExpr
+ instead of a Type.
+
+ * decl.cs (DeclSpace): Implement IAlias.
+ (DeclSpace.LookupAlias): Return an IAlias instead of a string.
+
+ * generic.cs (ConstructedType): Improved error checking.
+
+2004-04-02 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Added type parameter conversions.
+
+ * ecore.cs
+ (UnboxCast.Emit): Emit an `unbox.any' for type params.
+ (ClassCast.Emit): If the source type is a type parameter, box it.
+ If the target type is a type parameter, emit an `unbox.any'
+ instead of a `classcast'.1
+
+2004-04-01 Martin Baulig <martin@ximian.com>
+
+ * cs-tokenizer.cs (parse_less_than): Allow Token.DOT.
+
+2004-04-01 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Use
+ Convert.ImplicitStandardConversionExists(); user-defined implicit
+ conversions are not allowed according to the spec.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (New): Added support for type parameters.
+
+ * typemanager.cs
+ (TypeManager.activator_type): New public static field.
+ (TypeManager.activator_create_instance): Likewise.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.HasConstructorConstraint): New
+ public method.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.CheckConstraints): Actually follow
+ the spec here: the argument type must be convertible to the
+ constraints.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * generic.cs
+ (TypeParameter.Define, TypeParameter.DefineMethod): Call
+ TypeManager.AddTypeParameter().
+ (ConstructedType.CheckConstraints): Re-enable this and actually
+ check whether we have a constructor constraint.
+
+ * typemanager.cs
+ (TypeManager.builder_to_type_param): New static field.
+ (TypeManager.AddTypeParameter): New static method.
+ (TypeManager.LookupTypeParameter): New public method.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeParameter.DefineType): Return a boolean and use
+ the new API to actually define the constructor constraint.
+
+ * typemanager.cs
+ (TypeManager.new_constraint_attr_type): New static field.
+ (TypeManager.InitCoreTypes): Initialize it.
+
+2004-03-30 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (Constraints): Completed error checking, use correct
+ error numbers.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * delegate.cs (Delegate.VerifyMethod): Infer type arguments.
+
+ * expression.cs (Invocation.InferTypeArguments): Added overloaded
+ public version which takes a `ParameterData pd' instead of an
+ `ArrayList args'.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IsGenericMethod): Take a MethodBase,
+ not a MethodInfo.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Argument.ResolveMethodGroup): If we're a
+ ConstructedType, call GetMemberAccess() on it.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodBase.CheckGenericOverride): New abstract method.
+ (MethodCore.CheckGenericOverride): When overriding a generic
+ method, check whether the constraints match.
+
+ * support.cs (GenericConstraints): New public interface.
+ (ParameterData.GenericConstraints): New public method.
+
+ * parameter.cs (Parameter.Resolve): Check whether we're a generic
+ method parameter and compute our constraints if appropriate.
+ (Parameter.GenericConstraints): New public property.
+
+ * generic.cs (Constraints): Implement GenericConstraints.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCache.FindMemberToOverride): Use
+ `paramTypes [j].Equals (cmpAttrs [j])' instead of `=='.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericMethod.Define): Resolve our type parameters.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay: Report CS0080 instead of -200 ("Constraints are
+ not allowed on non-generic declarations").
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferTypeArguments): Added overloaded
+ public version of this method.
+
+ * class.cs (MethodCore.IsDuplicateImplementation): Use
+ Invocation.InferTypeArguments() to check this.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Use TypeManager.IsDelegateType() instead of
+ comparing types correctly.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Use TypeManager.IsSubclassOf() instead of comparing
+ types directly to make it work for generic instances.
+
+ * typemanager.cs (TypeManager.IsSubclassOf): New static method.
+
+2004-03-29 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.MayBecomeEqualGenericTypes): Added
+ support for arrays.
+
+2004-03-24 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.FindType): Also use
+ TypeManager.CheckGeneric() for types from the using clauses.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.OverloadResolve): Added `bool
+ may_fail' argument and use it instead of the Location.IsNull() hack.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferType): Use correct type inference
+ rules here.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (MethodGroupExpr.Name): Use
+ TypeManager.CSharpSignature() instead of just the name.
+
+ * expression.cs (Invocation.OverloadResolve): Provide better error
+ reporting.
+ (Invocation.DoResolve): OverloadResolve() never returns null
+ without reporting an error, so removed the error -6 reporting here.
+
+2004-03-23 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.GetMethodFlags): Fixed the FIXME for
+ generic methods.
+
+ * cs-parser.jay (delegate_declaration): Support generic delegates.
+
+ * delegate.cs: Support generic delegates.
+
+2004-03-22 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.InferParamsTypeArguments): New static
+ method; does type inference for params arguments.
+
+2004-03-21 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IsGenericMethod): New public static
+ method; checks whether a method is a generic method.
+
+ * expression.cs (Invocation.InferTypeArguments): New static method;
+ infer type arguments for generic method invocation.
+
+ * ecore.cs (MethodGroupExpr.HasTypeArguments): New public
+ property; we set this to true if we're resolving a generic method
+ invocation and the user specified type arguments, ie. we're not
+ doing type inference.
+
+2004-03-20 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodData.DeclaringType): New public property.
+ (MethodData.Define): Set DeclaringType here.
+ (Operator.Define): Use OperatorMethod.MethodData.DeclaringType
+ instead of OperatorMethodBuilder.DeclaringType.
+
+2004-03-20 Martin Baulig <martin@ximian.com>
+
+ * cs-tokenizer.cs (xtoken): Return a special
+ Token.DEFAULT_OPEN_PARENS for "`default' followed by open parens".
+
+ * cs-parser.jay (default_value_expression): Switch to the new
+ syntax (14.5.13).
+
+2004-03-19 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberName): New class. We use this to "construct"
+ namespace_or_type_name's.
+
+ * generics.cs (TypeArguments.GetDeclarations): New public method;
+ returns the type arguments as a string[] and reports a CS0081 if
+ one of them is not an identifier.
+
+ * class.cs (MemberBase): The .ctor now takes the name as a
+ MemberName instead of a string.
+ (MemberBase.ExplicitInterfaceName): Changed type from string to
+ Expression.
+ (MemberBase.DoDefine): If we're an explicit implementation, the
+ InterfaceType may be a generic instance.
+
+ * cs-parser.jay (namespace_or_type_name): Return a MemberName.
+ (namespace_name): Call MemberName.GetName () to transform the
+ MemberName into a string and ensure we don't have any type
+ arguments.
+ (type_name): Call MemberName.GetTypeExpression() to transfrom the
+ MemberName into an expression.
+ (method_header): Use namespace_or_type_name instead of member_name.
+
+2004-04-07 Miguel de Icaza <miguel@ximian.com>
+
+ * rootcontext.cs: Add new types to the boot resolution.
+
+ * ecore.cs (TypeExpr.CanInheritFrom): Inheriting from
+ MulticastDelegate is not allowed.
+
+ * typemanager.cs: Add new types to lookup: System.TypedReference
+ and ArgIterator.
+
+ * paramter.cs (Parameter.Resolve): if we are an out/ref parameter,
+ check for TypedReference or ArgIterator, they are not allowed.
+
+ * ecore.cs (BoxedCast): Set the eclass to ExprClass.Value, this
+ makes us properly catch 1510 in some conditions (see bug 56016 for
+ details).
+
+2004-04-06 Bernie Solomon <bernard@ugsolutions.com>
+
+ * CryptoConvert.cs: update from corlib version
+ with endian fixes.
+
+2004-04-05 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (Indexer.Define): Check indexername declaration
+
+2004-04-05 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (IsClsCompliant): Fixed problem with handling
+ all three states (compliant, not-compliant, undetected).
+
+2004-03-30 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute): Location is now public.
+ (Resolve): Store resolved arguments (pos_values) in attribute class.
+ Attribute extractors (now GetClsCompliantAttributeValue) can reuse them.
+ (GetClsCompliantAttributeValue): New method that gets
+ CLSCompliantAttribute value.
+ (GetClsCompliantAttribute): Returns CLSCompliantAttribute for DeclSpace
+ if exists else null.
+ (AttributeTester): New class for CLS-Compliant verification routines.
+
+ * class.cs (Emit): Add CLS-Compliant verification.
+ (Method.GetSignatureForError): Implemented.
+ (Constructor.GetSignatureForError): Implemented
+ (Constructor.HasCompliantArgs): Returns if constructor has
+ CLS-Compliant arguments.
+ (Constructor.Emit): Override.
+ (Construcor.IsIdentifierClsCompliant): New method; For constructors
+ is needed to test only parameters.
+ (FieldBase.GetSignatureForError): Implemented.
+ (TypeContainer): New member for storing base interfaces.
+ (TypeContainer.FindMembers): Search in base interfaces too.
+
+ * codegen.cs (GetClsComplianceAttribute): New method that gets
+ assembly or module CLSCompliantAttribute value.
+ (ResolveClsCompliance): New method that resolve CLSCompliantAttribute
+ for assembly.
+ (ModuleClass.Emit): Add error 3012 test.
+
+ * const.cs (Emit): Override and call base for CLS-Compliant tests.
+
+ * decl.cs (ClsComplianceValue): New enum that holds CLS-Compliant
+ state for all decl types.
+ (MemberCore.Emit): Emit is now virtual and call VerifyClsCompliance
+ if CLS-Compliant tests are required.
+ (IsClsCompliaceRequired): New method. Analyze whether code
+ must be CLS-Compliant.
+ (IsExposedFromAssembly): New method. Returns true when MemberCore
+ is exposed from assembly.
+ (GetClsCompliantAttributeValue): New method. Resolve CLSCompliantAttribute
+ value or gets cached value.
+ (HasClsCompliantAttribute): New method. Returns true if MemberCore
+ is explicitly marked with CLSCompliantAttribute.
+ (IsIdentifierClsCompliant): New abstract method. This method is
+ used to testing error 3005.
+ (IsIdentifierAndParamClsCompliant): New method. Common helper method
+ for identifier and parameters CLS-Compliant testing.
+ (VerifyClsCompliance): New method. The main virtual method for
+ CLS-Compliant verifications.
+ (CheckAccessLevel): In one special case (System.Drawing) was TypeBuilder
+ null. I don't know why is null (too many public members !).
+ (GetClsCompliantAttributeValue). New method. Goes through class hierarchy
+ and get value of first CLSCompliantAttribute that found.
+
+ * delegate.cs (Emit): Override and call base for CLS-Compliant tests.
+ (VerifyClsCompliance): Override and add extra tests.
+
+ * driver.cs (CSCParseOption): New command line options (clscheck[+|-]).
+ clscheck- disable CLS-Compliant verification event if assembly is has
+ CLSCompliantAttribute(true).
+
+ * enum.cs (Emit): Override and call base for CLS-Compliant tests.
+ ApllyAttribute is now called in emit section as in the other cases.
+ Possible future Emit integration.
+ (IsIdentifierClsCompliant): New override.
+ (VerifyClsCompliance): New override.
+ (GetEnumeratorName): Returns full enum name.
+
+ * parameter.cs (GetSignatureForError): Implemented.
+
+ * report.cs (WarningData): New struct for Warning message information.
+ (LocationOfPreviousError): New method.
+ (Warning): New method. Reports warning based on the warning table.
+ (Error_T): New method. Reports error based on the error table.
+
+ * rootcontext.cs (EmitCode): Added new Emit(s) because CLS-Compliant
+ verifications are done here.
+
+ * tree.cs (RecordDecl): Used new LocationOfPreviousError method.
+
+ * typemanager.cs (cls_compliant_attribute_type): New member thath holds
+ CLSCompliantAttribute.
+ (all_imported_types): New member holds all imported types from other
+ assemblies.
+ (LoadAllImportedTypes): New method fills static table with exported types
+ from all referenced assemblies.
+ (Modules): New property returns all assembly modules.
+
+2004-03-30 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Add a rule to catch wrong event syntax instead of
+ throwing a parser error.
+
+ * ecore.cs (PropertyExpr.GetAccessor): Apply patch from Patrik Reali
+ which removes the hardcoded get_/set_ prefixes for properties, as
+ IL allows for the properties to be named something else.
+
+ Bug #56013
+
+ * expression.cs: Do not override operand before we know if it is
+ non-null. Fix 56207
+
+2004-03-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * typemanager.cs: support for pinned variables.
+
+2004-03-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs, typemanager.cs: Avoid using an arraylist
+ as a buffer if there is only one result set.
+
+2004-03-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Make sure you cant call a static method
+ with an instance expression, bug #56174.
+
+2004-03-29 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (IsDuplicateImplementation): Improve error reporting to
+ flag 663 (method only differs in parameter modifier).
+
+ * cs-tokenizer.cs: Do not require whitespace when a ( or " will do
+ in preprocessor directives.
+
+ * location.cs (LookupFile): Allow for the empty path.
+
+ * attribute.cs (DefinePInvokeMethod): Fix 56148; I would like a
+ better approach for some of that patch, but its failing with the
+ CharSet enumeration. For now try/catch will do.
+
+ * typemanager.cs: Do not crash if a struct does not have fields.
+ Fixes 56150.
+
+2004-03-28 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: cs0213, cant fix a fixed expression.
+ fixes 50231.
+
+2004-03-28 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * cs-parser.jay: detect invalid embeded statements gracefully.
+ bug #51113.
+
+2004-03-28 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * ecore.cs, typemanager.cs: Correct impl of cs1540 check.
+ As a regex:
+ s/
+ the invocation type may not be a subclass of the tye of the item/
+ The type of the item must be a subclass of the invocation item.
+ /g
+
+ Fixes bug #50820.
+
+2004-03-25 Sebastien Pouliot <sebastien@ximian.com>
+
+ * attribute.cs: Added methods to get a string and a bool from an
+ attribute. Required to information from AssemblyKeyFileAttribute,
+ AttributeKeyNameAttribute (string) and AssemblyDelaySign (bool).
+ * codegen.cs: Modified AssemblyName creation to include support for
+ strongnames. Catch additional exceptions to report them as CS1548.
+ * compiler.csproj: Updated include CryptoConvert.cs.
+ * compiler.csproj.user: Removed file - user specific configuration.
+ * CryptoConvert.cs: New. A COPY of the class CryptoConvert from
+ Mono.Security assembly. The original class is maintained and tested in
+ /mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoConvert.cs.
+ * drivers.cs: Added support for /keyfile, /keycontainer and /delaysign
+ like CSC 8.0 (C# v2) supports.
+ * Makefile: Added CryptoConvert.cs to mcs sources.
+ * rootcontext.cs: Added new options for strongnames.
+
+2004-03-24 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * driver.cs: For --expect-error, report error code `2'
+ if the program compiled with no errors, error code `1' if
+ it compiled with an error other than the one expected.
+
+2004-03-24 Sebastien Pouliot <sebastien@ximian.com>
+
+ * compiler.csproj: Updated for Visual Studio .NET 2003.
+ * compiler.csproj.user: Updated for Visual Studio .NET 2003.
+ * compiler.sln: Updated for Visual Studio .NET 2003.
+
+2004-03-24 Ravi Pratap M <ravi@ximian.com>
+
+ * expression.cs: Fix bug #47234. We basically need to apply the
+ rule that we prefer the conversion of null to a reference type
+ when faced with a conversion to 'object' (csc behaviour).
+
+2004-03-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * statement.cs: Shorter form for foreach, eliminates
+ a local variable. r=Martin.
+
+2004-03-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * constant.cs, ecore.cs, literal.cs: New prop IsZeroInteger that
+ checks if we can use brtrue/brfalse to test for 0.
+ * expression.cs: use the above in the test for using brtrue/brfalse.
+ cleanup code a bit.
+
+2004-03-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Rewrite string concat stuff. Benefits:
+
+ - "a" + foo + "b" + "c" becomes "a" + foo + "bc"
+ - "a" + foo + "b" + bar + "c" + baz ... uses concat (string []).
+ rather than a concat chain.
+
+ * typemanager.cs: Add lookups for more concat overloads.
+
+2004-03-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Emit shorter il code for array init.
+
+ newarr
+ dup
+ // set 1
+
+ // set 2
+
+ newarr
+ stloc.x
+
+ ldloc.x
+ // set 1
+
+ ldloc.x
+ // set 2
+
+2004-03-22 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * statement.cs: Before, two switch blocks would be merged if the
+ total size of the blocks (end_item - begin_item + 1) was less than
+ two times the combined sizes of the blocks.
+
+ Now, it will only merge if after the merge at least half of the
+ slots are filled.
+
+ fixes 55885.
+
+2004-03-20 Atsushi Enomoto <atsushi@ximian.com>
+
+ * class.cs : csc build fix for GetMethods(). See bug #52503.
+
+2004-03-20 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Make sure fp comparisons work with NaN.
+ This fixes bug #54303. Mig approved this patch a long
+ time ago, but we were not able to test b/c the runtime
+ had a related bug.
+
+2004-03-19 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (TypExpr.GetHashCode): implement this overload.
+
+2004-03-19 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MemberCore.IsDuplicateImplementation): Check whether
+ two overloads may unify for some type parameter substitutions and
+ report a CS0408 if appropriate.
+
+2004-03-19 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MemberCore.IsDuplicateImplementation): Report the
+ error here and not in our caller.
+
+2004-03-19 Martin Baulig <martin@ximian.com>
+
+ * interface.cs: Completely killed this file.
+ (Interface): We're now a TypeContainer and live in class.cs.
+
+ * class.cs (TypeContainer.GetClassBases): Added `bool is_iface'
+ argument; we're now also called for interfaces.
+ (TypeContainer.DefineMembers): Allow this method being called
+ multiple times.
+ (TypeContainer.GetMethods): New public method; formerly known as
+ Interface.GetMethod(). This is used by PendingImplementation.
+ (TypeContainer.EmitDefaultMemberAttr): Moved here from Interface;
+ it's now private and non-static.
+ (Interface): Moved this here; it's now implemented similar to
+ Class and Struct.
+ (Method, Property, Event, Indexer): Added `bool is_interface'
+ argument to their .ctor's.
+ (MemberBase.IsInterface): New public field.
+
+ * cs-parser.jay: Create normal Method, Property, Event, Indexer
+ instances instead of InterfaceMethod, InterfaceProperty, etc.
+ (opt_interface_base): Removed; we now use `opt_class_base' instead.
+ (InterfaceAccessorInfo): Create `Get' and `Set' Accessor's.
+
+2004-03-19 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodCore.IsDuplicateImplementation): New private
+ method which does the CS0111 checking.
+ (Method.CheckBase, Constructor.CheckBase, PropertyBase.CheckBase):
+ Use IsDuplicateImplementation().
+
+2004-03-17 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs (FindMemberToOverride): New method to find the correct
+ method or property to override in the base class.
+ * class.cs
+ - Make Method/Property use the above method to find the
+ version in the base class.
+ - Remove the InheritableMemberSignatureCompare as it is now
+ dead code.
+
+ This patch makes large code bases much faster to compile, as it is
+ O(n) rather than O(n^2) to do this validation.
+
+ Also, it fixes bug 52458 which is that nested classes are not
+ taken into account when finding the base class member.
+
+ Reviewed/Approved by Martin.
+
+2004-03-17 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.DoResolve): Take the parent's number
+ of type arguments into account; use the `real_num_type_args'
+ approach like in DoResolveAsTypeStep().
+
+ * generic.cs (GenericMemberAccess.DoResolve): Make this work for
+ nested types.
+
+2004-03-17 Marek Safar <marek.safar@seznam.cz>
+
+ * interface.cs: In all interface classes removed redundant
+ member initialization.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Fix the CS0528 check.
+
+2004-03-15 Miguel de Icaza <miguel@ximian.com>
+
+ * decl.cs (DefineTypeAndParents): New helper method to define a
+ type's containers before the type itself is defined; This is a
+ bug exposed by the recent changes to Windows.Forms when an
+ implemented interface was defined inside a class that had not been
+ built yet.
+
+ * modifiers.cs (MethodAttr): All methods in C# are HideBySig.
+
+ (Check): Loop correctly to report errors modifiers
+ (UNSAFE was not in the loop, since it was the same as TOP).
+
+ * interface.cs: Every interface member now takes a ModFlags,
+ instead of a "is_new" bool, which we set on the base MemberCore.
+
+ Every place where we called "UnsafeOk" in the interface, now we
+ call the proper member (InterfaceMethod.UnsafeOK) instead to get
+ the unsafe settings from the member declaration instead of the
+ container interface.
+
+ * cs-parser.jay (opt_new): Allow unsafe here per the spec.
+
+ * pending.cs (TypeAndMethods): Add `get_indexer_name' and
+ `set_indexer_name' to the pending bits (one per type).
+
+ We fixed a bug today that was picking the wrong method to
+ override, since for properties the existing InterfaceMethod code
+ basically ignored the method name. Now we make sure that the
+ method name is one of the valid indexer names.
+
+2004-03-14 Gustavo Giráldez <gustavo.giraldez@gmx.net>
+
+ * support.cs (SeekableStreamReader): Keep track of stream byte
+ positions and don't mix them with character offsets to the buffer.
+
+ Patch from Gustavo Giráldez
+
+2004-03-15 Marek Safar <marek.safar@seznam.cz>
+
+ * interface.cs (InterfaceSetGetBase): Removed double member
+ initialization, base class does it as well.
+
+2004-03-13 Martin Baulig <martin@ximian.com>
+
+ * class.cs: Reverted Miguel's latest commit; it makes mcs crash
+ when compiling corlib.
+
+2004-03-13 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ExplicitConversion): We were reporting an error on
+ certain conversions (object_type source to a value type, when the
+ expression was `null') before we had a chance to pass it through
+ the user defined conversions.
+
+ * driver.cs: Replace / and \ in resource specifications to dots.
+ Fixes 50752
+
+ * class.cs: Add check for duplicate operators. Fixes 52477
+
+2004-03-11 Miguel de Icaza <miguel@ximian.com>
+
+ * statement.cs (Switch.SimpleSwitchEmit): Deal with default labels
+ that are in the middle of the statements, not only at the end.
+ Fixes #54987
+
+ * class.cs (TypeContainer.AddField): No longer set the
+ `HaveStaticConstructor' flag, now we call it
+ `UserDefineStaticConstructor' to diferentiate the slightly
+ semantic difference.
+
+ The situation is that we were not adding BeforeFieldInit (from
+ Modifiers.TypeAttr) to classes that could have it.
+ BeforeFieldInit should be set to classes that have no static
+ constructor.
+
+ See:
+
+ http://www.yoda.arachsys.com/csharp/beforefieldinit.html
+
+ And most importantly Zoltan's comment:
+
+ http://bugzilla.ximian.com/show_bug.cgi?id=44229
+
+ "I think beforefieldinit means 'it's ok to initialize the type sometime
+ before its static fields are used', i.e. initialization does not need
+ to be triggered by the first access to the type. Setting this flag
+ helps the JIT to compile better code, since it can run the static
+ constructor at JIT time, and does not need to generate code to call it
+ (possibly lots of times) at runtime. Unfortunately, mcs does not set
+ this flag for lots of classes like String.
+
+ csc sets this flag if the type does not have an explicit static
+ constructor. The reasoning seems to be that if there are only static
+ initalizers for a type, and no static constructor, then the programmer
+ does not care when this initialization happens, so beforefieldinit
+ can be used.
+
+ This bug prevents the AOT compiler from being usable, since it
+ generates so many calls to mono_runtime_class_init that the AOT code
+ is much slower than the JITted code. The JITted code is faster,
+ because it does not generate these calls if the vtable is type is
+ already initialized, which is true in the majority of cases. But the
+ AOT compiler can't do this."
+
+2004-03-10 Miguel de Icaza <miguel@ximian.com>
+
+ * class.cs (MethodData.Emit): Refactor the code so symbolic
+ information is generated for destructors; For some reasons we
+ were taking a code path that did not generate symbolic information
+ before.
+
+2004-03-11 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs: Create a Constructor.CheckBase method that
+ takes care of all validation type code. The method
+ contains some code that was moved from Define.
+
+ It also includes new code that checks for duplicate ctors.
+ This fixes bug #55148.
+
+2004-03-09 Joshua Tauberer <tauberer@for.net>
+
+ * expression.cs (ArrayCreation): Fix: More than 6 nulls in
+ a { ... }-style array creation invokes EmitStaticInitializers
+ which is not good for reference-type arrays. String, decimal
+ and now null constants (NullCast) are not counted toward
+ static initializers.
+
+2004-03-05 Martin Baulig <martin@ximian.com>
+
+ * location.cs (SourceFile.HasLineDirective): New public field;
+ specifies whether the file contains or is referenced by a "#line"
+ directive.
+ (Location.DefineSymbolDocuments): Ignore source files which
+ either contain or are referenced by a "#line" directive.
+
+2004-02-29 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs (Method.CheckBase): Avoid using FindMembers, we have
+ direct access to our parent, so check the method inline there.
+
+2004-02-27 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs (Invocation.EmitCall): Miguel's last commit
+ caused a regression. If you had:
+
+ T t = null;
+ t.Foo ();
+
+ In Foo the implict this would be null.
+
+2004-02-27 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Invocation.EmitCall): If the method is not
+ virtual, do not emit a CallVirt to it, use Call.
+
+ * typemanager.cs (GetFullNameSignature): Improve the method to
+ cope with ".ctor" and replace it with the type name.
+
+ * class.cs (ConstructorInitializer.Resolve): Now the method takes
+ as an argument the ConstructorBuilder where it is being defined,
+ to catch the recursive constructor invocations.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (MemberAccess.DoResolve): If `expr' resolved to a
+ ConstructedType, call ResolveType() on it to get the type rather
+ than just using `expr.Type'.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * generics.cs (ConstructedType.GetMemberAccess): Take the
+ EmitContext instead on the TypeExpr and use
+ ec.TypeContainer.CurrentType/ec.ContainerType.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (SimpleName.DoResolveAsTypeStep): Lookup type
+ parameters before aliases.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.MayBecomeEqualGenericInstances):
+ New oublic function; checks whether two generic instances may become
+ equal under some instantiations (26.3.1).
+
+ * class.cs (TypeContainer.Define): Call
+ TypeManager.MayBecomeEqualGenericInstances() and report CS0695 on
+ error.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Moved
+ Error_TypeParameterAsBase() here and also check whether the base
+ class is not an attribute.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Fix the CS0528 check.
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Error_TypeParameterAsBase): Use correct error number
+ here (CS0689).
+
+2004-03-16 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.ResolveTypeExpr): Added more error checking
+ for generics.
+
+ * generics.cs (ConstructedType.DoResolveAsTypeStep): Added better
+ error reporting.
+
+2004-03-15 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.GetFullName): New public method.
+ (TypeManager.MemberLookup): Added `int_num_type_arguments'
+ argument; only return members with the correct number of type
+ arguments.
+ (TypeManager.CheckGeneric): Allow -1 to bypass the check.
+ (TypeManager.FilterWithClosure): Call CheckGeneric() to check
+ whether the number of type arguments matches.
+
+ * generic.cs (GenericMemberAccess.ResolveAsTypeStep): Allow `expr'
+ not being a ConstructedType; we can now do "typeof (Foo.Bar<U>)".
+
+ * expression.cs (MemberAccess): Added public `NumTypeArguments'
+ field; it's set by the protected .ctor when we're actually a
+ GenericMemberAccess.
+ (MemberAccess.ResolveAsTypeStep): Compute the total number of type
+ arguments and pass it to MemberLookupFinal ().
+
+ * ecore.cs (Expression.MemberLookup): Added `int
+ num_type_arguments' argument; only return members with the correct
+ number of type arguments.
+ (Expression.MemberLookupFailed): Check whether the MemberLookup
+ failed because we did not have the correct number of type
+ arguments; report CS0305 in this case.
+
+ * decl.cs (DeclSpace.ResolveTypeExpr): Don't report an error if
+ `e.ResolveAsTypeTerminal()' already did so.
+
+2004-03-15 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (Expression.ResolveLValue): Allow e.type being null if
+ we're a ConstructedType; in this case, the caller must report an
+ error (for instance CS0131).
+
+ * generic.cs (TypeArguments): Added Location argument to the .ctor.
+ (TypeArguments.Resolve): Actually report errors here.
+
+2004-03-15 Miguel de Icaza <miguel@ximian.com>
+
+ * pending.cs (TypeAndMethods): Add `get_indexer_name' and
+ `set_indexer_name' to the pending bits (one per type).
+
+ We fixed a bug today that was picking the wrong method to
+ override, since for properties the existing InterfaceMethod code
+ basically ignored the method name. Now we make sure that the
+ method name is one of the valid indexer names.
+
+2004-03-15 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IndexerPropertyName): Added support
+ for generic instances.
+
+2004-03-13 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineType): Call
+ TypeManager.AddUserType() immediately after creating the
+ TypeBuilder; pass all type parameters when creating the
+ CurrentType.
+
+ * decl.cs (DeclSpace.FindNestedType): New public method.
+ (DeclSpace.FindType): Added `int num_type_args' argument; only
+ return types with the correct number of type parameters.
+ (DeclSpace.CountTypeParams): New public property.
+
+ * ecore.cs (SimpleName.ctor): Added overloaded version which takes
+ the number of type parameters; defaults to zero.
+
+ * generic.cs (TypeArguments.Count): New public property.
+ (ConstructedType.DoResolveAsTypeStep): First call
+ ds.FindNestedType() to find out whether we're nested in the
+ current generic type; in this case, we inherit all type parameters
+ from the current class.
+
+ * rootcontext.cs (RootContext.NamespaceLookup): Added `int
+ num_type_args' argument.
+ (RootContext.LookupType): Added overloaded version which takes the
+ number of type arguments; only return types with the correct
+ number of type arguments.
+
+ * typemanager.cs (TypeManager.CheckGeneric): New public function;
+ checks whether `Type t' has `int num_type_args'.
+
+2004-03-13 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericMethod.DefineType): New method; calls
+ DefineType() on all the type parameters.
+
+ * class.cs (MethodData.ctor): Added `GenericMethod generic' argument.
+ (MethodData.Define): If we're a generic method, call
+ GenericMethod.DefineType() to define the type parameters.
+
+2004-03-10 Martin Baulig <martin@ximian.com>
+
+ * pending.cs (Pending.InterfaceMethod): Use TypeManager.IsEqual()
+ instead of IsAssignableFrom.
+
+2004-03-10 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (FieldExpr.ctor): Use TypeManager.TypeToCoreType().
+
+ * support.cs (ParameterData.HasArrayParameter): New property.
+ (ReflectionParameters.ctor): Take a MethodBase instead of a
+ ParameterInfo[]. If we have any type parameters, get the generic
+ method definition and ask it whether we have variable arguments.
+
+2004-02-26 Miguel de Icaza <miguel@ximian.com>
+
+ * iterators.cs (IteratorHandler.IsIEnumerator, IsIEnumerable): New
+ routines to check if a type is an enumerable/enumerator allow
+ classes that implement the IEnumerable or IEnumerator interfaces.
+
+ * class.cs (Property, Operator): Implement IIteratorContainer, and
+ implement SetYields.
+
+ (Property.Define): Do the block swapping for get_methods in the
+ context of iterators. We need to check if Properties also
+ include indexers or not.
+
+ (Operator): Assign the Block before invoking the
+ OperatorMethod.Define, so we can trigger the Iterator code
+ replacement.
+
+ * cs-parser.jay (SimpleIteratorContainer): new helper class. Both
+ Property and Operator classes are not created when we parse the
+ declarator but until we have the block completed, so we use a
+ singleton SimpleIteratorContainer.Simple to flag whether the
+ SetYields has been invoked.
+
+ We propagate this setting then to the Property or the Operator to
+ allow the `yield' to function.
+
+2004-02-25 Marek Safar <marek.safar@seznam.cz>
+
+ * codegen.cs: Implemented attribute support for modules.
+ New AssemblyClass, ModuleClass and CommonAssemblyModulClass for
+ Assembly/Module functionality.
+
+ * attribute.cs, class.cs, cs-parser.jay, delegate.cs, driver.cs, enum.cs
+ interface.cs, rootcontext.cs, statement.cs, typemanager.cs:
+ Updated dependencies on CodeGen.ModuleBuilder and CodeGen.AssemblyBuilder.
+
+2004-02-16 Marek Safar <marek.safar@seznam.cz>
+
+ * interface.cs (FindMembers): The operation is performed on all base
+ interfaces and not only on the first. It is required for future CLS Compliance patch.
+
+2004-02-12 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * statement.cs, codegen.cs:
+ This patch deals with patterns such as:
+
+ public class List : IEnumerable {
+
+ public MyEnumerator GetEnumerator () {
+ return new MyEnumerator(this);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator () {
+ ...
+ }
+
+ public struct MyEnumerator : IEnumerator {
+ ...
+ }
+ }
+
+ Before, there were a few things we did wrong:
+ 1) we would emit callvirt on a struct, which is illegal
+ 2) we emited ldarg when we needed to emit ldarga
+ 3) we would mistakenly call the interface methods on an enumerator
+ type that derived from IEnumerator and was in another assembly. For example:
+
+ public class MyEnumerator : IEnumerator
+
+ Would have the interface methods called, even if there were public impls of the
+ method. In a struct, this lead to invalid IL code.
+
+2004-02-11 Marek Safar <marek.safar@seznam.cz>
+
+ * const.cs: Const is now derived from FieldBase. Method EmitConstant name
+ renamed to Emit.
+
+ * delegate.cs (Define): Fixed crash when delegate type is undefined.
+
+2004-02-11 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Fix small regression: we were not testing V2
+ compiler features correctly.
+
+ * interface.cs: If the emit context is null, then create one
+
+2004-02-09 Marek Safar <marek.safar@seznam.cz>
+
+ * decl.cs (GetSignatureForError): New virtual method to get full name
+ for error messages.
+
+ * attribute.cs (IAttributeSupport): New interface for attribute setting.
+ Now it is possible to rewrite ApplyAttributes method to be less if/else.
+
+ * interface.cs : All InterfaceXXX classes are now derived from MemberCore.
+ Duplicated members and code in these classes has been removed.
+ Better encapsulation in these classes.
+
+2004-02-07 Miguel de Icaza <miguel@ximian.com>
+
+ * assign.cs (Assign.DoResolve): When dealing with compound
+ assignments, there is a new rule in ECMA C# 2.4 (might have been
+ there before, but it is documented here) that states that in:
+
+ a op= b;
+
+ If b is of type int, and the `op' is a shift-operator, then the
+ above is evaluated as:
+
+ a = (int) a op b
+
+ * expression.cs (Binary.ResolveOperator): Instead of testing for
+ int/uint/long/ulong, try to implicitly convert to any of those
+ types and use that in pointer arithmetic.
+
+ * delegate.cs (Error_NoMatchingMethodForDelegate): Compute the
+ method to print information for from the type, not from the
+ null-method we were given.
+
+2004-02-01 Duncan Mak <duncan@ximian.com>
+
+ * cs-tokenizer.cs (get_cmd_arg): Skip over whitespace before
+ parsing for cmd, fixes bug #53694.
+
+2004-02-04 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs, decl.cs: Fixed problem where IndexerName attribute was ignored
+ in the member name duplication tests. Property and operator name duplication
+ was missing too (error tests cs0102-{2,3,4,5}.cs, cs0111-{3,4}.cs).
+
+2004-02-03 Marek Safar <marek.safar@seznam.cz>
+
+ * interface.cs (PopulateMethod): Fixed crash when interface method
+ returns not existing type (error test cs0246-3.cs).
+
+2004-02-02 Ravi Pratap M <ravi@ximian.com>
+
+ * cs-parser.jay (interface_accessors): Re-write actions to also
+ store attributes attached to get and set methods. Fix spelling
+ while at it.
+
+ (inteface_property_declaration): Modify accordingly.
+
+ (InterfaceAccessorInfo): New helper class to store information to pass
+ around between rules that use interface_accessors.
+
+ * interface.cs (Emit): Apply attributes on the get and set
+ accessors of properties and indexers too.
+
+ * attribute.cs (ApplyAttributes): Modify accordingly to use the
+ right MethodBuilder when applying attributes to the get and set accessors.
+
+2004-01-31 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-tokenizer.cs: Applied patch from Marek Safar to fix bug 53386
+
+2004-01-26 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-tokenizer.cs: Handle #line hidden from PDC bits.
+
+2004-01-25 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Remove YIELD token, instead use the new grammar
+ changes that treat `yield' specially when present before `break'
+ or `return' tokens.
+
+ * cs-tokenizer.cs: yield is no longer a keyword.
+
+2004-01-23 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay, class.cs (DefineDefaultConstructor): Fixed ModFlags
+ setting for default constructors.
+ For default constructors are almost every time set wrong Modifier. The
+ generated IL code has been alright. But inside mcs this values was
+ wrong and this was reason why several of my CLS Compliance tests
+ failed.
+
+2004-02-27 Martin Baulig <martin@ximian.com>
+
+ * generics.cs (ConstructedType.ResolveType): Make the nested type
+ stuff actually work.
+
+2004-02-25 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.CurrentTypeParameters): New protected
+ property; returns the type parameters just from the current type,
+ ie. with the ones from outer classes.
+ (DeclSpace.LookupGeneric): First search in the current class, then
+ in outer classes.
+ (DeclSpace.initialize_type_params): When hiding a type parameter
+ from an outer class, put it into the `type_param_list' anyways.
+
+ * expression.cs (MemberAccess.expr): Made this field protected.
+
+ * class.cs (TypeContainer.Define): The `CurrentType' just contains
+ the type parameters from the current class.
+
+ * generic.cs (ConstructedType.ResolveType): Support nested generic
+ types by taking the type parameters which we inherit from outer
+ classes into account.
+ (GenericMemberAccess.ResolveAsTypeStep): Override this and added
+ support for nested generic types.
+
+2004-02-23 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.IsGeneric): Make this a property instead of a
+ field and check whether we're nested inside a generic type.
+ (DeclSpace.ResolveType): If we're resolving to a generic type
+ definition, create a ConstructedType and return its resolved type.
+ (DeclSpace.initialize_type_params): New private method;
+ initializes the `type_param_list' field from the type parameters
+ from this and all enclosing classes.
+ (DeclSpace.TypeParameters): Call initialize_type_params() unless
+ we're already initialized.
+
+2004-02-23 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Method.Define): Create the generic method before
+ calling DoDefine().
+ (Memberbase.DoDefine): Added DeclSpace argument (in addition to
+ the TypeContainer one); we use this for generic methods.
+
+ * decl.cs (CheckAccessLevel): If we're a GenericMethod, use our
+ parent's TypeBuilder.
+
+2004-02-18 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (FieldExpr.DoResolveLValue): Use TypeManager.IsEqual()
+ to check for equality.
+
+2004-02-05 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (FieldExpr.DoResolveLValue): If we have an
+ `ec.TypeContainer.CurrentType', use it instead of
+ `ec.ContainerType' to check whether we're in the type's ctor.
+
+2004-01-29 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.DoResolve): If we're a
+ `ConstructedType', then we're actually a generic method, so
+ rewrite the expr as a GenericMemberAccess.
+
+ * cs-parser.jay (member_name): Don't use `namespace_or_type_name'
+ here; manually parse it into a string.
+
+2004-01-28 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IsEqual): New static method.
+ (TypeManager.FilterWithClosure): Call TypeManager.IsEqual() to
+ check for equality instead of using `=='.
+
+2004-01-26 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.CurrentType): New public field.
+
+ * expression.cs (This.ResolveBase): If we have an
+ `ec.TypeContainer.CurrentType', use it instead of
+ `ec.ContainerType'.
+
+ * class.cs (TypeContainer.DefineType): If we're a generic type,
+ create the `CurrentType' (unresolved).
+ (TypeContainer.GenericType): New private field.
+ (TypeContainer.DefineMembers): If we have a `CurrentType', resolve
+ it and store it in `GenericType' before creating the MemberCache.
+ (TypeContainer.GetMembers): If we have a `GenericType', call
+ TypeManager.FindMembers() on it.
+
+ * interface.cs (Interface.GenericType): New private field.
+ (Interface.DefineType): If we're a generic type, create the
+ `CurrentType' (unresolved).
+ (Interface.DefineMembers): If we have a `CurrentType', resolve it
+ and store it in `GenericType' before creating the MemberCache.
+ (Interface.GetMembers): If we have a `GenericType', call
+ TypeManager.FindMembers() on it.
+
+2004-01-22 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (namespace_or_type_name): Return an Expression,
+ not a QualifiedIdentifier. This is what `type_name_expression'
+ was previously doing.
+ (type_name_expression): Removed; the code is now in
+ `namespace_or_type_name'.
+ (qualified_identifier): Removed, use `namespace_or_type_name'
+ instead.
+ (QualifiedIdentifier): Removed this class.
+
+2004-01-22 Martin Baulig <martin@ximian.com>
+
+ * namespace.cs (NamespaceEntry.UsingAlias): Take an Expression,
+ not a string as alias name.
+
+2004-01-21 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (FieldInfo.AddressOf): Revert patch from previous
+ #52730 bug, and instead compute correctly the need to use a
+ temporary variable when requesting an address based on the
+ static/instace modified of the field and the constructor.
+
+2004-01-21 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup in the current
+ class and namespace before looking up aliases. Fixes #52517.
+
+2004-01-21 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (UsageVector.Merge): Allow variables being
+ assinged in a 'try'; fixes exception4.cs.
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+ * class.cs : Implemented parameter-less constructor for TypeContainer
+
+ * decl.cs: Attributes are now stored here. New property OptAttributes
+
+ * delegate.cs, enum.cs, interface.cs: Removed attribute member.
+
+ * rootcontext.cs, tree.cs: Now use parameter-less constructor of TypeContainer
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+
+ * typemanager.cs (CSharpSignature): Now reports also inner class name.
+ (CSharpSignature): New method for indexer and property signature.
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+
+ * pending.cs (IsVirtualFilter): Faster implementation.
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+
+ * typemanager.cs: Avoid inclusion of same assembly more than once.
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+
+ * cs-parser.jay: Fixed problem where the last assembly attribute
+ has been applied also to following declaration (class, struct, etc.)
+
+2004-01-21 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs: Added error CS0538, CS0539 reporting.
+ Fixed crash on Microsoft runtime when field type is void.
+
+ * cs-parser.jay: Added error CS0537 reporting.
+
+ * pending.cs: Added error CS0535 reporting.
+ Improved error report for errors CS0536, CS0534.
+
+2004-01-20 Miguel de Icaza <miguel@ximian.com>
+
+ Merge a few bits from the Anonymous Method MCS tree.
+
+ * statement.cs (ToplevelBlock): New class for toplevel methods,
+ will hold anonymous methods, lifted variables.
+
+ * cs-parser.jay: Create toplevel blocks for delegates and for
+ regular blocks of code.
+
+2004-01-20 Martin Baulig <martin@ximian.com>
+
+ * codegen.cs (EmitContext): Removed `InTry', `InCatch',
+ `InFinally', `InLoop', `TryCatchLevel', `LoopBeginTryCatchLevel'
+ and `NeedExplicitReturn'; added `IsLastStatement'.
+ (EmitContext.EmitTopBlock): Emit the explicit "ret" if we either
+ have a `ReturnLabel' or we're not unreachable.
+
+ * flowanalysis.cs (FlowBranching.MergeChild): Actually merge the
+ child's reachability; don't just override ours with it. Fixes
+ #58058 (lluis's example).
+ (FlowBranching): Added public InTryOrCatch(), InCatch(),
+ InFinally(), InLoop(), InSwitch() and
+ BreakCrossesTryCatchBoundary() methods.
+
+ * statement.cs (Return): Do all error checking in Resolve().
+ Unless we are the last statement in a top-level block, always
+ create a return label and jump to it.
+ (Break, Continue): Do all error checking in Resolve(); also make
+ sure we aren't leaving a `finally'.
+ (Block.DoEmit): Set `ec.IsLastStatement' when emitting the last
+ statement in a top-level block.
+ (Block.Flags): Added `IsDestructor'.
+ (Block.IsDestructor): New public property.
+
+2004-01-20 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Break.DoEmit): Set ec.NeedExplicitReturn; fixes #52427.
+
+2004-01-20 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Statement.ResolveUnreachable): New public method.
+ (If, While): Do the dead-code elimination in Resolve(), not in Emit().
+ (Block.Resolve): Resolve unreachable statements.
+
+2004-01-19 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: We need to fix the case where we do
+ not have a temp variable here.
+
+ * assign.cs: Only expression compound assignments need
+ temporary variables.
+
+2004-01-19 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * flowanalysis.cs: Reduce memory allocation in a few ways:
+ - A block with no variables should not allocate a bit
+ vector for itself.
+ - A method with no out parameters does not need any tracking
+ for assignment of the parameters, so we need not allocate
+ any data for it.
+ - The arrays:
+ public readonly Type[] VariableTypes;
+ public readonly string[] VariableNames;
+ Are redundant. The data is already stored in the variable
+ map, so we need not allocate another array for it.
+ - We need to add alot of checks for if (params | locals) == null
+ due to the first two changes.
+
+2004-01-18 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (FieldExpr.AddressOf): For ValueTypes that do not
+ implement IMemoryLocation, we store a copy on a local variable and
+ take the address of it. Patch from Benjamin Jemlich
+
+ * cs-parser.jay: Applied patch from Ben Maurer to the "type" rule
+ to use a special "type_name_expression" rule which reduces the
+ number of "QualifiedIdentifier" classes created, and instead
+ directly creates MemberAccess expressions.
+
+2004-01-17 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs: Applied patch from Benjamin Jemlich (pcgod@gmx.net)
+ that fixes #52853. Null literal assignment to ValueType
+
+ * class.cs (MethodData.Emit): Instead of checking the name of the
+ method to determine if its a destructor, create a new derived
+ class from Method called Destructor, and test for that.
+
+ * cs-parser.jay: Create a Destructor object instead of a Method.
+
+ Based on a fix from Benjamin Jemlich (pcgod@gmx.net)
+
+ Fixes: 52933
+
+2004-01-16 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Binary.ResolveOperator): Perform an implicit
+ conversion from MethodGroups to their delegate types on the
+ Addition operation.
+
+ * delegate.cs: Introduce a new class DelegateCreation that is the
+ base class for `NewDelegate' and `ImplicitDelegateCreation',
+ factor some code in here.
+
+ * convert.cs (Convert.ImplicitConversionStandard): Add an implicit
+ conversion from MethodGroups to compatible delegate types.
+
+ * ecore.cs (Expression.Resolve): Do not flag error 654
+ (Methodgroupd needs parenthesis) if running on the V2 compiler, as
+ we allow conversions from MethodGroups to delegate types now.
+
+ * assign.cs (Assign.DoResolve): Do not flag errors on methodgroup
+ assignments in v2 either.
+
+2004-01-10 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs (FieldExpr.AddressOf): Fix generated IL for accessing
+ static read-only fields in ctors.
+
+ Applied patch from Benjamin Jemlich
+
+ * expression.cs (UnaryMutator): Avoid leaking local variables.
+
+2004-01-09 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-tokenizer.cs (IsCastToken): Allow the various native types
+ here to return true, as they can be used like this:
+
+ (XXX) int.MEMBER ()
+
+ Fixed 49836 and all the other dups
+
+2004-01-09 Zoltan Varga <vargaz@freemail.hu>
+
+ * driver.cs: Implement /win32res and /win32icon.
+
+2004-01-08 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Add a rule to improve error handling for the
+ common mistake of placing modifiers after the type.
+
+2004-01-07 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay (interface_event_declaration): Catch
+ initialization of events on interfaces, and report cs0068
+
+ * cs-parser.jay (interface_event_declaration): Catch
+ initialization of events.
+
+ * ecore.cs: Better report missing constructors.
+
+ * expression.cs (Binary.ResolveOperator): My previous bug fix had
+ the error reporting done in the wrong place. Fix.
+
+ * expression.cs (Binary.ResolveOperator): Catch the
+ operator + (E x, E y) error earlier, and later allow for implicit
+ conversions in operator +/- (E e, U x) from U to the underlying
+ type of E.
+
+ * class.cs (TypeContainer.DefineDefaultConstructor): Fix bug
+ 52596, if the container class is abstract, the default constructor
+ is protected otherwise its public (before, we were always public).
+
+ * statement.cs (Fixed.Resolve): Catch a couple more errors in the
+ fixed statement.
+
+ (Using.EmitLocalVariableDecls): Applied patch from Benjamin
+ Jemlich that fixes bug #52597, MCS was generating invalid code for
+ idisposable structs. Thanks to Ben for following up with this
+ bug as well.
+
+2004-01-06 Miguel de Icaza <miguel@ximian.com>
+
+ * driver.cs: Allow assemblies without code to be generated, fixes
+ 52230.
+
+2004-01-07 Nick Drochak <ndrochak@gol.com>
+
+ * attribute.cs: Remove unneeded catch variables. Eliminates a warning.
+
+2004-01-05 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Add rules to improve error reporting if fields or
+ methods are declared at the namespace level (error 116)
+
+ * Add rules to catch event add/remove
+
+2004-01-04 David Sheldon <dave-mono@earth.li>
+
+ * expression.cs: Added matching ")" to error message for
+ CS0077
+
+2004-01-03 Todd Berman <tberman@gentoo.org>
+
+ * ecore.cs, attribute.cs:
+ Applying fix from #52429.
+
+2004-01-03 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * ecore.cs, expression.cs, statement.cs:
+ Total rewrite of how we handle branching. We
+ now handle complex boolean expressions with fewer
+ jumps. As well if (x == 0) no longer emits a ceq.
+
+ if (x is Foo) is much faster now, because we generate
+ better code.
+
+ Overall, we get a pretty big improvement on our benchmark
+ tests. The code we generate is smaller and more readable.
+
+ I did a full two-stage bootstrap. The patch was reviewed
+ by Martin and Miguel.
+
+2004-01-03 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * cs-parser.jay: Make primary_expression not take a QI.
+ we dont need this because the member_access rule covers
+ us here. So we replace the rule with just IDENTIFIER.
+
+ This has two good effects. First, we remove a s/r conflict.
+ Second, we allocate many fewer QualifiedIdentifier objects.
+
+2004-01-03 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * attribute.cs: Handle MarshalAs attributes as pseudo, and
+ set the correct information via SRE. This prevents
+ hanging on the MS runtime. Fixes #29374.
+
+2004-01-03 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * convert.cs: correctly handle conversions to value types
+ from Enum and ValueType as unboxing conversions.
+
+ Fixes bug #52569. Patch by Benjamin Jemlich.
+
+2004-01-02 Ravi Pratap <ravi@ximian.com>
+
+ * expression.cs (BetterConversion): Prefer int -> uint
+ over int -> ulong (csc's behaviour). This fixed bug #52046.
+
+2004-01-02 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs (MemberCache.FindMembers): now returns a
+ MemberInfo [].
+
+ * typemanager.cs: In general, go with with ^^.
+ (CopyNewMethods): take an IList.
+ (RealMemberLookup): Only allocate an arraylist
+ if we copy from two sets of methods.
+
+ This change basically does two things:
+ 1) Fewer array lists allocated due to CopyNewMethods.
+ 2) the explicit cast in MemberList costed ALOT.
+
+2004-01-02 Zoltan Varga <vargaz@freemail.hu>
+
+ * cs-tokenizer.cs (consume_identifier) driver.cs: Cache identifiers in
+ a hashtable to avoid needless string allocations when an identifier is
+ used more than once (the common case).
+
+2004-01-01 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * pending.cs: MS's TypeBuilder.GetInterfaces ()
+ is broken, it will not return anything. So, we
+ have to use the information we have in mcs to
+ do the task.
+
+ * typemanager.cs: Add a cache for GetInterfaces,
+ since this will now be used more often (due to ^^)
+
+ (GetExplicitInterfaces) New method that gets the
+ declared, not effective, interfaces on a type
+ builder (eg, if you have interface IFoo, interface
+ IBar, Foo : IFoo, Bar : Foo, IBar, GetExplInt (Bar) ==
+ { IBar }.
+
+ This patch makes MCS able to bootstrap itself on
+ Windows again.
+
+2004-01-01 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Remove the Nop's that Miguel put
+ in by mistake.
+
+2003-12-31 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * report.cs, codegen.cs: Give the real stack trace to
+ the error when an exception is thrown.
+
+2003-12-31 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs: only allocate hashtables for ifaces if
+ it is an iface!
+
+2003-12-31 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: fix the error from cs0121-2.cs
+ (a parent interface has two child interfaces that
+ have a function with the same name and 0 params
+ and the function is called through the parent).
+
+2003-12-30 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs, rootcontext.cs, typmanager.cs: do not
+ leak pointers.
+
+2003-12-28 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * codegen.cs: remove stack for the ec flow branching.
+ It is already a linked list, so no need.
+
+2003-12-27 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * Makefile: Allow custom profiler here.
+
+2003-12-26 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * typemanager.cs (LookupType):
+ - Use a static char [], because split takes
+ a param array for args, so it was allocating
+ every time.
+ - Do not store true in a hashtable, it boxes.
+
+2003-12-26 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * flowanalysis.cs: bytify common enums.
+
+2003-12-25 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * modifiers.cs: Add a new set of flags for the
+ flags allowed on explicit interface impls.
+ * cs-parser.jay: catch the use of modifiers in
+ interfaces correctly.
+ * class.cs: catch private void IFoo.Blah ().
+
+ All related to bug #50572.
+
+2003-12-25 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs: Rewrite the consistant accessability checking.
+ Accessability is not linear, it must be implemented in
+ a tableish way. Fixes #49704.
+
+2003-12-25 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * expression.cs: Handle negation in a checked context.
+ We must use subtraction from zero. Fixes #38674.
+
+2003-12-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs: Ignore static void main in DLLs.
+ * rootcontext.cs: Handle the target type here,
+ since we are have to access it from class.cs
+ * driver.cs: account for the above.
+
+2003-12-23 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * report.cs: Give line numbers and files if available.
+
+2003-12-20 Zoltan Varga <vargaz@freemail.hu>
+
+ * driver.cs: Implement /addmodule.
+
+ * typemanager.cs: Change 'modules' field so it now contains Modules not
+ ModuleBuilders.
+
+2003-12-20 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineMembers): Don't do the CS0649 check here.
+ (FieldBase.IsAssigned): Removed this field.
+ (FieldBase.SetAssigned): New public method.
+ (TypeContainer.Emit): Make the CS0169/CS0649 checks actually work.
+
+2003-12-20 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (LocalVariableReference.DoResolve): Don't set
+ `vi.Used' if we're called from DoResolveLValue().
+
+ * statement.cs (Block.DoResolve): `ec.DoEndFlowBranching()' now
+ returns the usage vector it just merged into the current one -
+ pass this one to UsageWarning().
+ (Block.UsageWarning): Take the `FlowBranching.UsageVector' instead
+ of the `EmitContext', don't call this recursively on our children.
+
+2003-12-19 Zoltan Varga <vargaz@freemail.hu>
+
+ * driver.cs: Implement /target:module.
+
+2003-12-18 Zoltan Varga <vargaz@freemail.hu>
+
+ * support.cs (CharArrayHashtable): New helper class.
+
+ * cs-tokenizer.cs: Store keywords in a hashtable indexed by
+ char arrays, not strings, so we can avoid creating a string in
+ consume_identifier if the identifier is a keyword.
+
+2003-12-16 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (LocalInfo.Assigned): Removed this property.
+ (LocalInfo.Flags): Removed `Assigned'.
+ (LocalInfo.IsAssigned): New public method; takes the EmitContext
+ and uses flow analysis.
+ (Block.UsageWarning): Made this method private.
+ (Block.Resolve): Call UsageWarning() if appropriate.
+
+ * expression.cs (LocalVariableReference.DoResolve): Always set
+ LocalInfo.Used here.
+
+2003-12-13 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Statement.DoEmit, Statement.Emit): Don't return
+ any value here; we're now using flow analysis to figure out
+ whether a statement/block returns a value.
+
+2003-12-13 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (UsageVector.MergeFinallyOrigins): Made this
+ working again.
+ (FlowBranching.MergeFinally): Don't call
+ `branching.CheckOutParameters()' here, this is called in
+ MergeTopBlock().
+ (FlowBranchingException.AddSibling): Call MergeFinallyOrigins()
+ when adding the `finally' vector.
+
+2003-12-13 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs
+ (UsageVector.MergeJumpOrigins, FlowBranching.Label): Make this
+ actually work and also fix #48962.
+
+2003-12-12 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * decl.cs: Do not check System.Object for nested types,
+ since we know it does not have any. Big bang for buck:
+
+ BEFORE:
+ Run 1: 8.35 seconds
+ Run 2: 8.32 seconds
+ corlib: 17.99 seconds
+ AFTER:
+ Run 1: 8.17 seconds
+ Run 2: 8.17 seconds
+ corlib: 17.39 seconds
+
+2003-12-11 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs (FindMembers): Allocate arraylists on demand. Most of the
+ time we are returning 0 members, so we save alot here.
+
+2003-12-11 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (UsageVector.MergeResult): Renamed this back to
+ `MergeChild()', also just take the `FlowBranching' as argument;
+ call Merge() on it and return the result.
+ (FlowBranching.Merge): We don't need to do anything if we just
+ have one sibling.
+
+2003-12-11 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs: Use a list of `UsageVector's instead of storing
+ them in an `ArrayList' to reduce memory usage. Thanks to Ben
+ Maurer for this idea.
+
+2003-12-11 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (MergeResult): This class is now gone; we now
+ use the `UsageVector' for this. The reason for this is that if a
+ branching just has one sibling, we don't need to "merge" them at
+ all - that's the next step to do.
+ (FlowBranching.Merge): We now return a `UsageVector' instead of a
+ `MergeResult'.
+
+2003-12-11 Martin Baulig <martin@ximian.com>
+
+ Reworked flow analyis and made it more precise and bug-free. The
+ most important change is that we're now using a special `Reachability'
+ class instead of having "magic" meanings of `FlowReturns'. I'll
+ do some more cleanups and optimizations and also add some more
+ documentation this week.
+
+ * flowanalysis.cs (Reachability): Added `Throws' and `Barrier';
+ largely reworked this class.
+ (FlowReturns): Removed `Unreachable' and `Exception'; we now use
+ the new `Reachability' class instead of having "magic" values here.
+ (FlowBranching): We're now using an instance of `Reachability'
+ instead of having separate `Returns', `Breaks' etc. fields.
+
+ * codegen.cs (EmitContext.EmitTopBlock): Set `has_ret' solely
+ based on flow analysis; ignore the return value of block.Emit ().
+
+2003-12-10 Zoltan Varga <vargaz@freemail.hu>
+
+ * driver.cs typemanager.cs: Find the mono extensions to corlib even
+ if they are private.
+
+2003-12-09 Martin Baulig <martin@ximian.com>
+
+ * flowanalyis.cs (FlowBranching.Return, Goto, Throw): Removed;
+ call them directly on the UsageVector.
+
+2003-12-09 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.MergeChild, MergeTopBlock):
+ Changed return type from `FlowReturns' to `Reachability'.
+
+2003-12-09 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranching.Reachability): New sealed class.
+ (FlowBranching.MergeResult): Replaced the `Returns', `Breaks' and
+ `Reachable' fields with a single `Reachability' one.
+
+2003-12-08 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * class.cs (FindMembers): Remove foreach's.
+
+ Bootstrap times:
+
+ BEFORE
+ Run 1: 8.74 seconds
+ Run 2: 8.71 seconds
+
+ AFTER
+ Run 1: 8.64 seconds
+ Run 2: 8.58 seconds
+
+
+2003-12-08 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * cs-parser.jay:
+ * gen-treedump.cs:
+ * statement.cs:
+ This patch does a few things:
+ 1. EmptyStatement is now a singleton, so it is never reallocated.
+ 2. All blah is EmptyStatement constructs have been changed to
+ blah == EmptyStatement.Value, which is much faster and valid
+ now that EmptyStatement is a singleton.
+ 3. When resolving a block, rather than allocating a new array for
+ the non-empty statements, empty statements are replaced with
+ EmptyStatement.Value
+ 4. Some recursive functions have been made non-recursive.
+ Mainly the performance impact is from (3), however (1) and (2) are needed for
+ this to work. (4) does not make a big difference in normal situations, however
+ it makes the profile look saner.
+
+ Bootstrap times:
+
+ BEFORE
+ 9.25user 0.23system 0:10.28elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
+ 9.34user 0.13system 0:10.23elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
+ Total memory allocated: 56397 KB
+
+ AFTER
+ 9.13user 0.09system 0:09.64elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k
+ 8.96user 0.24system 0:10.13elapsed 90%CPU (0avgtext+0avgdata 0maxresident)k
+ Total memory allocated: 55666 KB
+
+2003-12-08 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * support.cs: Rewrite DoubleHash to use its own impl. Is faster
+ than the hashtable in a hashtable version
+
+ * decl.cs: Right now, whenever we try to lookup a type inside a namespace,
+ we always end up concating a string. This results in a huge perf
+ loss, because many strings have to be tracked by the GC. In this
+ patch, we first use a hashtable that works with two keys, so that
+ the strings do not need to be concat'ed.
+
+ Bootstrap times:
+ BEFORE
+ Run 1: 8.74 seconds
+ Run 2: 8.71 seconds
+
+ AFTER
+ Run 1: 8.65 seconds
+ Run 2: 8.56 seconds
+
+2003-12-08 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * Makefile: Add a new target `do-time' that does a quick and simple
+ profile, leaving easy to parse output.
+
+2003-12-08 Zoltan Varga <vargaz@freemail.hu>
+
+ * codegen.cs (Init): Create the dynamic assembly with
+ AssemblyBuilderAccess.Save, to enable some optimizations in the runtime.
+
+2003-12-02 Ben Maurer <bmaurer@users.sourceforge.net>
+
+ * support.cs: Make the PtrHashtable use only one
+ instance of its comparer.
+
+2003-11-30 Zoltan Varga <vargaz@freemail.hu>
+
+ * typemanager.cs: Fix lookup of GetNamespaces.
+
+2003-11-29 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs: Removed redundant line.
+
+ * statement.cs (Block.Resolve, Block.Emit): Avoid foreach on
+ ArrayLists, use for loops with bounds.
+
+ * flowanalysis.cs (FlowBranching.Merge): Avoid foreach on
+ arraylist.
+
+ * expression.cs (Invocation.OverloadResolve): Avoid foreach on
+ arraylists, use for loop with bounds.
+
+ The above three changes give us a 0.071 second performance
+ improvement out of 3.294 seconds down to 3.223. On my machine
+ the above changes reduced the memory usage by 1,387 KB during
+ compiler bootstrap.
+
+ * cs-parser.jay (QualifiedIdentifier): New class used to represent
+ QualifiedIdentifiers. Before we created a new string through
+ concatenation, and mostly later on, the result would be
+ manipulated by DecomposeQI through string manipulation.
+
+ This reduced the compiler memory usage for bootstrapping from
+ 59380 KB to 59007 KB on my machine, 373 KB, and also reduced the
+ compile times in 0.05 seconds.
+
+2003-11-28 Dick Porter <dick@ximian.com>
+
+ * support.cs: Do string compares with the Invariant culture.
+
+ * rootcontext.cs:
+ * gen-treedump.cs:
+ * expression.cs:
+ * driver.cs:
+ * decl.cs:
+ * codegen.cs:
+ * class.cs: Use the char forms of IndexOf and LastIndexOf, so that
+ the comparison is done with the Invariant culture.
+
+2003-11-27 Miguel de Icaza <miguel@ximian.com>
+
+ * statement.cs (Foreach.TryType): Use DeclaredOnly to find the
+ GetEnumerator method.
+
+ (ProbeCollectionType): Iterate starting at the most specific type
+ upwards looking for a GetEnumerator
+
+ * expression.cs: Shift count can be up to 31 for int/uint and 63
+ for long/ulong.
+
+2003-11-26 Miguel de Icaza <miguel@ximian.com>
+
+ * statement.cs (Block.LookupLabel): Also look for the label on the
+ children blocks. Use a hash table to keep track of visited
+ nodes.
+
+ * cfold.cs (IntConstant to UIntConstant mapping): Only return if
+ we actually did transform the other operand, otherwise fall back
+ to the common codepath that casts to long.
+
+ * cs-tokenizer.cs: Use the same code pattern as the int case.
+ Maybe I should do the parsing myself, and avoid depending on the
+ Parse routines to get this done.
+
+2003-11-25 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti),
+ which fixes bug 51347. This time test it.
+
+ * expression.cs: Make TypeOfVoid derive from TypeOf, so code in
+ attributes for example can not tell the difference between these.
+ The difference was only a syntax feature of the language.
+
+ * attribute.cs: Apply attributes to delegates.
+
+ * delegate.cs: Call the apply attributes method.
+
+2003-11-24 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (TryImplicitIntConversion): One line bug fix: we were
+ comparing 0 vs Byte.MinValue, not the value
+
+ (ImplicitConversionRequired): When reporting a conversion error,
+ use error 31 to print out the constant error instead of the
+ simpler 29.
+
+ * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti),
+ which fixes bug 51347.
+
+2003-11-22 Miguel de Icaza <miguel@ximian.com>
+
+ * driver.cs: Applied patch from gert.driesen@pandora.be (Gert Driesen)
+ which fixes the -warnaserror command line option.
+
+2003-11-21 Miguel de Icaza <miguel@ximian.com>
+
+ * cfold.cs (DoNumericPromotions): During constant folding of
+ additions on UIntConstant, special case intconstants with
+ IntConstants like we do on the expression binary operator.
+
+2003-11-12 Miguel de Icaza <miguel@ximian.com>
+
+ * convert.cs (ImplicitReferenceConversion): We were missing a case
+ (System.Enum are not value types or class types, so we need to
+ classify them separatedly).
+
+ * driver.cs: We do not support error 2007.
+
+2003-11-12 Jackson Harper <jackson@ximian.com>
+
+ * driver.cs: Use corlib.dll or mscorlib.dll when looking up the
+ system directory. Also use the full file name so users can
+ libraries names mscorlib-o-tron.dll in a non system dir.
+
+2004-01-04 David Sheldon <dave-mono@earth.li>
+
+ * expression.cs: Added matching ")" to error message for CS0077.
+
+2003-12-19 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.IsEqualGenericType): New public
+ static method; see documentation in the method.
+ (TypeManager.IsSubclassOrNestedChild): Allow IsEqualGenericType().
+
+ * convert.cs (Convert.ImplicitReferenceConversion,
+ Convert.ImplicitReferenceConversionExists): Add support for
+ generic type declarations; see gen-36.cs.
+
+2003-12-19 Martin Baulig <martin@ximian.com>
+
+ * pending.cs (Pending.InterfaceMethod): Use
+ `Type.IsAssignableFrom()' instead of `=='.
+
+2003-12-18 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.AsAccessible): Check for array, pointer and
+ byref types first.
+
+ * convert.cs (Convert.ImplicitStandardConversionExists): Use
+ `expr_type.Equals (target_type)' instead of `=='.
+
+2003-12-08 Martin Baulig <martin@ximian.com>
+
+ * generics.cs (Constraints.Types): Removed.
+ (Constraints.Resolve): Just resolve everything to TypeExpr's, not
+ to Type's.
+ (Constraints.ResolveTypes): New public method; resolves the
+ TypeExpr's to Type's.
+ (TypeParameter.Define): TypeBuilder.DefineGenericParameter() no
+ longer takes the constraints.
+ (TypeParameter.DefineMethod): Likewise.
+ (TypeParameter.DefineType): New public method. Calls
+ `TypeBuilder/MethodBuilder.SetGenericParameterConstraints()' to set
+ the constraints.
+
+2003-12-08 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ImplicitConversionStandard): Use
+ `expr_type.Equals (target_type)' instead of `=='.
+
+2003-12-08 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.GetReferenceType): Call
+ `Type.MakeByRefType ()'.
+
+2003-12-08 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay, cs-tokenizer.cs: `where' is not a keyword, it
+ just has some special meaning in some situations. For instance,
+ it is allowed to use `where' as the name of a variable etc.
+
+2003-12-04 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (ComposedCast.DoResolveAsTypeStep): Use
+ `Type.MakeArrayType()' for array types.
+
+2003-11-18 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Invocation.VerifyArgumentsCompat): Remove
+ debugging message.
+
+ (SizeOf.DoResolve): assign the `type_queried' field. This gets
+ corlib to compile.
+
+2003-11-16 Martin Baulig <martin@ximian.com>
+
+ * codegen.cs (EmitContext.IsGeneric): Removed.
+
+ * ecore.cs (SimpleName.ResolveAsTypeStep): Always call
+ ResolveGeneric() on the DeclSpace.
+
+2003-11-16 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (TypeArguments.Resolve):
+ `Expression.ResolveAsTypeTerminal()' returns a TypeExpr; call
+ `ResolveType()' on it to get the Type.
+
+2003-11-15 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.GetInterfaces): Override this.
+
+2003-11-14 Martin Baulig <martin@ximian.com>
+
+ * interface.cs (Interface.DefineType): Define all type parameters
+ before adding the interfaces we inherit.
+
+2003-11-11 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.ResolveType): Always call
+ `gt.BindGenericParameters (atypes)'; also if `args.HasTypeArguments'.
+
+2003-11-10 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.ResolveExpressionTypes): Removed.
+ (TypeManager.InitCoreTypes): Initialize them here, but instead of
+ calling `ResolveType()' on them, directly assign their `Type'.
+
+2003-11-08 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType): Override `IsClass' etc.
+
+2003-11-08 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Use TypeExpr's for the
+ return value and the `out parent' parameter.
+ (TypeContainer.DefineType): Moved the CS0644 check into
+ GetClassBases(). Don't pass the interface types to the
+ `builder.DefineType()'/`builder.DefineNestedType()', but resolve
+ them later and then call `TypeBuilder.AddInterfaceImplementation()'.
+
+ * ecore.cs (TypeExpr.IsAttribute): New property.
+ (TypeExpr.GetInterfaces): New method.
+
+ * interface.cs (Interface.GetInterfaceTypeByName): Return a
+ TypeExpr instead of a Type.
+ (Interface.GetInterfaceBases): Return TypeExpr's instead of Type's.
+ (Interface.DefineType): Don't pass the interface types to the
+ `builder.Definetype()'/`builder.DefineNestedType()', but resolve
+ them later and then call `TypeBulider.AddInterfaceImplementation()'.
+
+ * typemanager.cs (TypeManager.AddUserType): Take a `TypeExpr[]'
+ instead of a `Type[]'.
+ (TypeManager.RegisterBuilder): Likewise.
+ (TypeManager.AddUserInterface): Likewise.
+ (TypeManager.ExpandInterfaces): Take a `Type[]' instead of a
+ `Type[]' and also return a `TypeExpr[]'.
+ (TypeManager.GetInterfaces): Return a `TypeExpr[]'.
+
+2003-11-08 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.ResolveTypeExpr): Return a TypeExpr, not an
+ Expression.
+
+2003-11-08 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.GetTypeResolveEmitContext): Call
+ TypeManager.ResolveExpressionTypes().
+
+ * ecore.cs (Expression.ResolveAsTypeTerminal): Return a TypeExpr
+ instead of an Expression.
+ (TypeExpr): This is now an abstract base class for `TypeExpression'.
+ (TypeExpression): New public class; formerly known as `TypeExpr'.
+
+ * expression.cs (ComposedCast): Derive from TypeExpr.
+
+ * typemanager.cs (TypeManager.system_*_expr): These are now
+ TypExpr's instead of Expression's.
+ (TypeManager.ResolveExpressionTypes): New public static function;
+ called from DeclSpace.GetTypeResolveEmitContext() to resolve all
+ of them.
+
+2003-11-06 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (New.DoResolve): Do not dereference value that
+ might be a null return.
+
+ * statement.cs (Block.EmitMeta): Use the Const.ChangeType to make
+ sure that the constant value has the right type. Fixes an
+ unreported bug, similar to 50425.
+
+ * const.cs (Const.LookupConstantValue): Call
+ ImplicitStandardConversionExists before doing a conversion to
+ avoid havng the TypeManager.ChangeType do conversions.
+
+ Reduced the number of casts used
+
+ (Const.ChangeType): New routine to enable reuse of the constant
+ type changing code from statement.
+
+ * typemanager.cs (ChangeType): Move common initialization to
+ static global variables.
+
+ Fixes #50425.
+
+ * convert.cs (ImplicitReferenceConversion): Somehow we allowed
+ every value type to go through, even if it was void. Fix that.
+
+ * cs-tokenizer.cs: Use is_identifier_start_character on the start
+ character of the define, and the is_identifier_part_character for
+ the rest of the string.
+
+2003-11-05 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (UnaryMutator.EmitCode): When I updated
+ LocalVariableReference.DoResolve, I overdid it, and dropped an
+ optimization done on local variable references.
+
+2003-11-04 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs: Convert the return from Ldlen into an int.
+
+2003-10-20 Miguel de Icaza <miguel@ximian.com>
+
+ * decl.cs (DeclSpace.GetAccessLevel): Handle NotPublic case for
+ the accessibility, this is a special case for toplevel non-public
+ classes (internal for instance).
+
+2003-10-20 Nick Drochak <ndrochak@gol.com>
+
+ * ecore.cs: Fix typo and build. Needed another right paren.
+
+2003-10-19 Miguel de Icaza <miguel@ximian.com>
+
+ * ecore.cs: Applied fix from Ben Maurer. We were handling in the
+ `internal' case regular and protected, but not allowing protected
+ to be evaluated later. Bug 49840
+
+2003-10-15 Miguel de Icaza <miguel@ximian.com>
+
+ * statement.cs (Switch.TableSwitchEmit): Compare the upper bound
+ to kb.Nlast, and not the kb.nFirst to isolate the switch
+ statement.
+
+ Extract the underlying type, so enumerations of long/ulong are
+ treated like long/ulong.
+
+2003-10-14 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (New): Overload the meaning of RequestedType to
+ track the possible creation of the NewDelegate type, since
+ DoResolve is invoked more than once for new constructors on field
+ initialization.
+
+ See bugs: #48800 and #37014
+
+ * cs-parser.jay (declare_local_constants): Take an arraylist
+ instead of a single constant.
+
+ (local_constant_declaration): It should take a
+ constant_declarators, not a constant_declarator. Fixes 49487
+
+ * convert.cs: Fix error report.
+
+2003-10-13 Jackson Harper <jackson@ximian.com>
+
+ * typemanager.cs (TypeToCoreType): Add float and double this fixes
+ bug #49611
+
+2003-11-03 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (ArrayAccess.GetStoreOpcode): Added
+ `out bool has_type_arg'; if set, we need to pass the type to
+ ig.Emit().
+ (ArrayAccess.GetStoreOpcode, ArrayAccess.EmitLoadOpcode): Use
+ Stelem_Any/Ldelem_Any for generic parameters.
+
+2003-11-02 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Invocation.EmitCall): Use
+ `TypeManager.IsValueType()' to check whether it's a value type.
+ Don't set `struct_call' when calling a method on a type parameter.
+
+2003-11-02 Martin Baulig <martin@ximian.com>
+
+ * generics.cs (ConstructedType.Resolve): Renamed to ResolveType()
+ and removed the TypeBuilder argument.
+
+ * typemanager.cs (TypeManager.IsValueType): Return
+ `t.IsGenericParameter || t.IsValueType'.
+
+2003-10-25 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.ResolveType): If we're a ConstructedType,
+ call ConstructedType.Resolve() on it.
+
+ * generic.cs (ConstructedType.Resolve): Set `type' on success.
+
+2003-10-25 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.GetClassBases): Changed
+ `out Type parent' into `out TypeExpr parent'. Moved CS0644 and
+ CS8214 reporting here.
+ (TypeContainer.DefineType): GetClassBases() gives us a `TypeExpr'
+ instead of a `Type' for our parent. In case of a recursive
+ declaration (see tests/gen-23.cs for an example), our parent is a
+ ConstructedType and it doesn't have its type set. So, first
+ create our own TypeBuilder, then call constructed.Resolve() to get
+ the parent's type and finally TypeBuilder.SetParent() it.
+
+ * ecore.cs (TypeExpr.Name): New public virtual property.
+
+ * generic.cs
+ (ConstructedType): We're now a TypeExpr and not just an Expression.
+ (ConstructedType.ResolveAsTypeStep): Don't resolve our type
+ arguments here; this is done later.
+ (ConstructedType.Resolve): New public method to resolve the type
+ arguments and bind them.
+
+2003-10-21 Martin Baulig <martin@ximian.com>
+
+ * convert.cs: Use `TypeManager.IsValueType' instead of
+ 'type.IsValueType' everywhere.
+
+ * typemanager.cs (TypeManager.IsValueType): Return true for type
+ parameters. The reason for this is that we need to box a type
+ parameter when converting it to a reference type.
+
+ * cs-parser.jay: Added support for default value expressions.
+
+ * generics.cs (DefaultValueExpression): New public class.
+
+2003-10-17 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (Constraints.Resolve): Take a DecpSpace instead of a
+ TypeContainer so we can also use this for Interfaces.
+ (TypeParameter.Resolve): Likewise.
+
+ * interface.cs (Interface.DefineType): Added support for generic
+ interfaces.
+
+ * cs-parser.jay: Added support for generic structs and interfaces.
+
+2003-10-17 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (GenericMemberAccess.DoResolve): We can now actually
+ call generic methods :-)
+
+2003-10-16 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (namespace_or_type_name): Only create a
+ GenericMemberAccess if we actually have type arguments.
+
+2003-10-13 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Method.Define): If we're a generic method, call
+ TypeBuilder.DefineGenericMethod () before resolving
+ the parameters.
+ (MethodData): Added .ctor which takes an additional MethodBuilder
+ argument; this is used for generic methods.
+ (MethodData.Define): Call `builder.SetGenericMethodSignature()' if
+ we already have a MethodBuilder.
+
+2003-10-10 Martin Baulig <martin@ximian.com>
+
+ * class.cs (Method): Added .ctor which takes a `GenericMethod'
+ instead of a `DeclSpace'. This is used for generic methods.
+
+ * cs-parser.jay (method_header): Added support for generic
+ methods; create a `GenericMethod' instance and pass it to the
+ `Method's .ctor; it'll be used as the `DeclSpace' to lookup
+ parameters and locals.
+
+ * decl.cs (DeclSpace.SetParameterInfo): Removed Location argument
+ since we already have the location. Check whether we're a generic
+ type declaration or a generic method and create the correct type
+ parameter.
+
+ * generic.cs (TypeParameter.DefineMethod): New public method.
+ (GenericMethod): New public class; derives from DeclSpace and is
+ used for generic methods.
+
+2003-10-09 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodCore): Added additional `DeclSpace ds' argument
+ to the .ctor.
+ (MethodCore.DoDefineParameters): Removed the TypeContainer
+ argument; use the DeclSpace which was passed to the .ctor instead.
+ (MethodCore.CheckParameter): Take a DeclSpace instead of a
+ TypeContainer; we only need a DeclSpace here.
+
+2003-10-09 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodData): Added additional `DeclSpace ds' argument
+ to the .ctor.
+ (MethodData.Define, MethodData.Emit): Pass the `ds' to the
+ EmitContext's .ctor.
+
+2003-10-09 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.AsAccessible): Moved here from TypeContainer.
+ (AccessLevel, CheckAccessLevel, GetAccessLevel): They're used by
+ AsAccessible(), moved them as well.
+
+ * class.cs (TypeContainer.AsAccessible): Moved to DeclSpace.
+
+2003-10-07 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (Binary.Emit.GreatherThanOrEqual): Fix the code
+ generation for >=, as spotted by Paolo, bug 48679.
+ Patch from David Waite.
+
+ * cs-tokenizer.cs: Add handling for #pragma.
+
+ * cs-parser.jay: Allow for both yield and yield return in the
+ syntax. The anti-cobolization of C# fight will go on!
+
+ * class.cs (TypeBuilder.DefineType): Catch error condition here
+ (Parent.DefineType erroring out and returning null).
+
+ * expression.cs (ArrayCreation.EmitDynamicInitializers): When
+ coping with enumerations variables, we were mistakenly processing
+ them as a regular value type instead of built-in types. Fixes the
+ bug #48063
+
+ * typemanager.cs (IsBuiltinOrEnum): New method.
+
+2003-09-30 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: Upgrade: yield now needs the return clause.
+
+2003-10-08 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
+ * cs-parser.jay : Renamed yyName to yyNames related to jay.
+
+2003-09-29 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeManager.GetMethodFlags): Added support for
+ inflated generic methods.
+
+ * generics.cs (ConstructedType): Distinguish between open and
+ closed constructed types; correctly resolve the arguments.
+
+2003-09-22 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.ResolveAsTypeCheck): Check whether
+ all type arguments meet their constraints.
+
+2003-09-19 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCache.SetupCacheForInterface): Take a
+ `MemberCache parent' argument. Normally, an interface doesn't
+ have a parent type except System.Object, but we use this in gmcs
+ for generic type parameters.
+
+2003-09-18 Martin Baulig <martin@ximian.com>
+
+ * typemanager.cs (TypeHandle.ctor): Set `IsInterface' solely based
+ on `type.IsInterface'; don't check whether the type has a parent
+ to determine whether it's an interface.
+
+2003-09-17 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.ToString): Always use `name' as the
+ type name.
+
+2003-09-15 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay: Fix grammar wrt. type_parameter_constraints.
+
+ * generic.cs (Constraints.Resolve): New public method; this is
+ called to resolve the constraint types and to check whether all
+ the constraints are correct.
+ (Constraints.Types): New public property.
+ (TypeParameter.Resolve): New public method; resolves all the
+ type's constraints.
+
+ * class.cs (TypeContainer.DefineType): Call
+ TypeParameter.Resolve() before actually defining the type.
+
+2003-09-15 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.DefineType): Added an error flag to
+ avoid reporting duplicate CS0146's ("class definition is
+ circular.").
+
+ * driver.cs (Driver.MainDriver): Abort if
+ RootContext.ResolveTree() reported any errors.
+
+2003-09-07 Martin Baulig <martin@ximian.com>
+
+ * report.cs (Error, Warning): Added overloaded versions which take
+ a `params object[] args' and call String.Format().
+
+2003-09-07 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace..ctor): Don't call
+ NamespaceEntry.DefineName() here; do it in RecordDecl() which is
+ called from Tree.RecordDecl(). Fixes the CS0101 reporting.
+ (DeclSpace.RecordDecl): New method.
+
+ * tree.cs (Tree.RecordDecl): Call ds.RecordDecl().
+
+2003-09-02 Ravi Pratap <ravi@ximian.com>
+
+ * attribute.cs (CheckAttributeTarget): Ensure that we allow return
+ value attributes to be applied to ParameterBuilders.
+
+ * class.cs (MethodCore.LabelParameters): Make static and more
+ generic so that it can be used from other places - like interface
+ methods, for instance.
+
+ * interface.cs (Interface.Emit): Call LabelParameters before
+ emitting attributes on the InterfaceMethod.
+
+2003-09-07 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.ResolveAsTypeStep): Report a CS8217
+ if the number of type parameters doesn't match.
+
+2003-09-04 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (ComposedCast.ResolveAsTypeStep): Added support
+ for arrays of generic type params (ie. `!0[]').
+
+2003-09-04 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeContainer.AsAccessible): Ignore generic parameters
+ for the moment.
+
+2003-09-04 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.LookupGeneric): New method.
+ (DeclSpace.CheckAccessLevel): Ignore generic parameters for the
+ moment.
+
+ * generic.cs (TypeParameterExpr): Take a TypeParameter as
+ argument, not just a string.
+ (TypeParameter.Define): New public method; this is called to
+ actually define the generic parameter; after this, you can use the
+ new `Type' property to get the type.
+
+2003-09-04 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.SetParameterInfo): The `constraints' argument
+ is now an ArrayList; initialize the result of the `TypeParameters'
+ property here.
+ (DeclSpace.GetGenericData): Removed.
+ (DeclSpace.LookupGeneric): Temporarily removed; we need to
+ implement this in a different way.
+ (DeclSpace.GetTypeParameters): Removed; there's now a
+ `TypeParameters' property.
+ (DeclSpace.TypeParameters): New public property.
+
+ * generic.cs (Constraints): Make this class public.
+ (TypeParameter): New public class.
+
+2003-09-04 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (DeclSpace.GetTypeParameters): New method to return the
+ generic parameters.
+
+ * class.cs (TypeContainer.DefineType): Call
+ TypeBuilder.DefineGenericParameter () on all generic parameters if
+ this is a generic type.
+
+2003-08-28 Martin Baulig <martin@ximian.com>
+
+ * sample-stack.il: Compile this with ilasm: "ilasm /dll
+ sample-stack.il".
+
+ * sample-hello.cs: Compile this with gmcs: "gmcs
+ /r:sample-stack.dll sample-hello.cs".
+
+2003-08-28 Martin Baulig <martin@ximian.com>
+
+ * generic.cs (ConstructedType.ResolveAsTypeStep): Actually bind
+ the parameters to the generic type.
+
+2003-08-28 Martin Baulig <martin@ximian.com>
+
+ * cs-tokenizer.cs (parse_less_than): Also allow all builtin types.
+
+2003-08-28 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (opt_type_argument_list): Use
+ `OP_GENERICS_LT type_arguments OP_GENERICS_GT'.
+ (primary_expression): Replace `qualified_identifier' with `type_name'.
+ (type_parameter_list): Use `OP_GENERICS_LT type_parameters OP_GENERICS_GT'.
+
+ * cs-tokenizer.cs (is_punct): When reading a `<', invoke a custom
+ parser to check whether it is syntactically a type parameter list;
+ return OP_GENERICS_LT/OP_GENERICS_GT instead of OP_LT/OP_GT in
+ this case.
+
+2003-08-26 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (SimpleName.SimpleNameResolve): Look for members before
+ resolving aliases; fixes #47927.
+
+2003-08-26 Martin Baulig <martin@ximian.com>
+
+ * statement.cs (Using.DoResolve): This is internally emitting a
+ try/finally clause, so we need to set ec.NeedExplicitReturn if we
+ do not always return. Fixes #47681.
+
+2003-08-26 Martin Baulig <martin@ximian.com>
+
+ * decl.cs (MemberCore): Moved WarningNotHiding(),
+ Error_CannotChangeAccessModifiers() and CheckMethodAgainstBase()
+ into MemberBase.
+ (AdditionResult): Make this nested in DeclSpace.
+ (DeclSpace.ctor): The .ctor now takes an additional NamespaceEntry
+ argument; call NamespaceEntry.Define() unless we're nested in a
+ class or struct.
+
+ * namespace.cs (Namespace.DefineName): New public function. This
+ is called from DeclSpace's .ctor to add
+ (Namespace.Lookup): Include DeclSpaces in the lookup.
+
+ * class.cs (Operator): Derive from MemberBase, not MemberCore.
+
+ * const.cs (Const): Derive from MemberBase, not MemberCore.
+
+2003-08-25 Martin Baulig <martin@ximian.com>
+
+ * convert.cs (Convert.ExplicitReferenceConversion): When
+ converting from an interface type to a class, unbox if the target
+ type is a struct type. Fixes #47822.
+
+2003-08-24 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * typemanager.cs: fixed the values of MethodFlags. Closes #47855 and
+ #47854.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ * class.cs (TypeManager.DefineType): When defining a nested type,
+ call DefineType() on our parent; fixes #47801.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ * class.cs (MethodData.Define): While checking if a method is an
+ interface implementation, improve the test a bit more to fix #47654.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Probe.DoResolve): Check whether `expr' resolved
+ correctly; fixes #47722.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (UnaryMutator.ResolveVariable): If the target is a
+ LocalVariableReference, ensure it's not read-only. Fixes #47536.
+
+ * statement.cs (Fixed.DoResolve): Make all variables read-only.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ * ecore.cs (FieldExpr.DoResolveLValue): Static read-only fields
+ can only be assigned in static constructors. Fixes #47161.
+
+2003-08-22 Martin Baulig <martin@ximian.com>
+
+ Rewrote and improved the flow analysis code.
+
+ * flowbranching.cs (FlowBranching): Make this class abstract.
+ (FlowBranching.CreateBranching): New static function to create a
+ new flow branching.
+ (FlowBranchingBlock, FlowBranchingException): New classes.
+ (FlowBranching.UsageVector.Type): New public readonly field.
+ (FlowBranching.UsageVector.Breaks): Removed the setter.
+ (FlowBranching.UsageVector.Returns): Removed the setter.
+ (FlowBranching.UsageVector): Added Break(), Return(),
+ NeverReachable() and Throw() methods to modify the reachability.
+ (FlowBranching.UsageVector.MergeChildren): Removed, this is now
+ done by FlowBranching.Merge().
+ (FlowBranching.UsageVector.MergeChild): New method; merges the
+ merge result into the current vector.
+ (FlowBranching.Merge): New abstract method to merge a branching.
+
+2003-08-12 Martin Baulig <martin@ximian.com>
+
+ * expression.cs (Indirection.CacheTemporaries): Create the
+ LocalTemporary with the pointer type, not its element type.
+
+2003-08-10 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay: FIRST_KEYWORD, LAST_KEYWORD: used to know if a
+ token was a keyword or not.
+
+ Add `error' options where an IDENTIFIER was expected; Provide
+ CheckToken and CheckIdentifierToken convenience error reporting
+ functions.
+
+ Do not use `DeclSpace.Namespace', use `DeclSpace.NamespaceEntry'.
+
+ * decl.cs: Rename `NamespaceEntry Namespace' public field into
+ NameSpaceEntry NameSpaceEntry.
+
+ (LookupInterfaceOrClass): Avoid creating a full qualified name
+ from namespace and name: avoid doing lookups when we know the
+ namespace is non-existant. Use new Tree.LookupByNamespace which
+ looks up DeclSpaces based on their namespace, name pair.
+
+ * driver.cs: Provide a new `parser verbose' to display the
+ exception thrown during parsing. This is turned off by default
+ now, so the output of a failure from mcs is more graceful.
+
+ * namespace.cs: Track all the namespaces defined in a hashtable
+ for quick lookup.
+
+ (IsNamespace): New method
+
+2003-08-09 Miguel de Icaza <miguel@ximian.com>
+
+ * namespace.cs: Remove redundant call; Avoid using MakeFQN when
+ we know that we need to concatenate (full typename can never be
+ null).
+
+ * class.cs: ditto.
+
+ * statement.cs: Use a bitfield; Do not initialize to null things
+ which are done by the constructor by default.
+
+ * cs-parser.jay: bug fix, parameter was 4, not 3.
+
+ * expression.cs: Just use the property;
+
+ * statement.cs: No need for GetVariableInfo method.
+
+2003-08-08 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowReturns): This is now nested in the
+ `FlowBranching' class.
+ (MyBitVector): Moved this here from statement.cs.
+ (FlowBranching.SiblingType): New enum type.
+ (FlowBranching.CreateSibling): Added `SiblingType' argument.
+
+2003-08-07 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs (FlowBranchingType): This is now nested in the
+ `FlowBranching' class and called `BranchingType'.
+
+2003-08-07 Martin Baulig <martin@ximian.com>
+
+ * flowanalysis.cs: Moved all the control flow analysis code into
+ its own file.
+
+2003-08-07 Martin Baulig <martin@ximian.com>
+
+ * assign.cs (Assign.DoResolve): `target' must either be an
+ IAssignMethod or an EventAccess; report a CS0131 otherwise. Fixes
+ #37319.
+
+2003-08-07 Miguel de Icaza <miguel@ximian.com>
+
+ * expression.cs (BinaryMethod): This kind of expression is created by the
+ Binary class if it determines that the operator has to be handled
+ by a method.
+
+ (BinaryDelegate): This kind of expression is created if we are
+ dealing with a + or - operator on delegates.
+
+ (Binary): remove method, argumetns, and DelegateOperator: when
+ dealing with methods,
+
+ * ecore.cs (EventExpr.EmitAddOrRemove): Update to new layout.
+
+ * statement.cs (Block): use bitfields for the three extra booleans
+ we had in use. Remove unused topblock parameter.
+
+ * codegen.cs: Remove unecessary argument to Block.EmitTopBlock
+
+ * assign.cs: Drop extra unneeded tests.
+
+2003-08-06 Miguel de Icaza <miguel@ximian.com>
+
+ * iterators.cs (Mapvariable): provide a mechanism to use prefixes.
+
+ * statement.cs (Foreach): Use VariableStorage instead of
+ LocalBuilders.
+
+ * codegen.cs (VariableStorage): New class used by clients that
+ require a variable stored: locals or fields for variables that
+ need to live across yield.
+
+ Maybe provide a convenience api for EmitThis+EmitLoad?
+
+ (GetTemporaryLocal, FreeTemporaryLocal): Recycle
+ these bad boys.
+
+2003-08-05 Miguel de Icaza <miguel@ximian.com>
+
+ * codegen.cs (RemapLocal, RemapLocalLValue, RemapParameter,
+ RemapParameterLValue): New methods that are used to turn a
+ precomputed FieldInfo into an expression like this:
+
+ instance.FieldInfo
+
+ The idea is to use this instead of making LocalVariableReference
+ have more than one meaning.
+
+ * cs-parser.jay: Add error production to BASE.
+
+ * ecore.cs: Deal with TypeManager.GetField returning null, which
+ is now a valid return value.
+
+ (FieldExprNoAddress): New expression for Fields whose address can
+ not be taken.
+
+ * expression.cs (LocalVariableReference): During the resolve
+ phases, create new expressions if we are in a remapping context.
+ Remove code that dealt with remapping here.
+
+ (ParameterReference): same.
+
+ (ProxyInstance): New expression, like the `This' expression, but
+ it is born fully resolved. We know what we are doing, so remove
+ the errors that are targeted to user-provided uses of `this'.
+
+ * statement.cs (Foreach): our variable is now stored as an
+ Expression; During resolution, follow the protocol, dont just
+ assume it will return this.
+
+2003-08-06 Martin Baulig <martin@ximian.com>
+
+ * support.cs (SeekableStreamReader.cs): New public class.
+
+ * cs-tokenizer.cs, cs-parser.jay, driver.cs: Use the new
+ SeekableStreamReader instead of the normal StreamReader.
+
+2003-08-04 Martin Baulig <martin@ximian.com>
+
+ * cs-parser.jay (CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST,
+ CLOSE_PARENS_OPEN_PARENS, CLOSE_PARENS_MINUS): New tokens to
+ deambiguate casts and delegate invocations.
+ (parenthesized_expression): Use the new tokens to ensure this is
+ not a cast of method invocation.
+
+ * cs-tokenizer.cs (is_punct): Return one of the new special tokens
+ when reading a `)' and Deambiguate_CloseParens () was previously
+ called.
+
+ * expression.cs (ParenthesizedExpression): New class. This is
+ just used for the CS0075 test.
+ (Binary.DoResolve): Check for CS0075.
+
+2003-07-29 Ravi Pratap <ravi@ximian.com>
+
+ * expression.cs (Invocation.MakeUnionSet): Patch from Lluis
+ Sanchez : use TypeManager.ArrayContainsMethod instead of a direct
+ reference comparison.
+
+ (TypeManager.ArrayContainsMethod): When we have a MethodInfo, also
+ examine the ReturnType for equality - this is necessary in the
+ cases of implicit and explicit operators whose signature also
+ includes the return type.
+
+2003-07-26 Miguel de Icaza <miguel@ximian.com>
+
+ * namespace.cs: Cache the result of the namespace computation,
+ instead of computing it every time.
+
+2003-07-24 Miguel de Icaza <miguel@ximian.com>
+
+ * decl.cs: Use a global arraylist that we reuse over invocations
+ to avoid excesive memory consumption. Reduces memory usage on an
+ mcs compile by one meg (45 average).
+
+ * typemanager.cs (LookupTypeReflection): In .NET pointers are
+ private, work around that.
+
+2003-07-23 Miguel de Icaza <miguel@ximian.com>
+
+ * literal.cs (IntLiteral): Define Zero and One static literals.
+
+ * cs-parser.jay (integer_literal): use static literals to reduce
+ memory usage for the most used literals (0, 1 and -1). 211kb
+ reduced in memory usage.
+
+ Replace all calls to `new ArrayList' with `new
+ ArrayList(4)' which is a good average number for most allocations,
+ and also requires only 16 bytes of memory for its buffer by
+ default.
+
+ This reduced MCS memory usage in seven megabytes for the RSS after
+ bootstrapping.
+
+2003-07-28 Ravi Pratap <ravi@ximian.com>
+
+ * expression.cs (Invocation.OverloadResolve): Fix the algorithm to
+ handle params methods the correct way by forming only one
+ applicable set with params and normal methods in them. Earlier we
+ were looking at params methods only if we found no normal methods
+ which was not the correct thing to do.
+
+ (Invocation.BetterFunction): Take separate arguments indicating
+ when candidate and the best method are params methods in their
+ expanded form.
+
+ This fixes bugs #43367 and #46199.
+
+ * attribute.cs: Documentation updates.
+
+ (CheckAttribute): Rename to CheckAttributeTarget.
+ (GetValidPlaces): Rename to GetValidTargets.
+
+ * expression.cs (Invocation.IsParamsMethodApplicable): Fix trivial
+ bug - use Convert.ImplicitConversion, not ImplicitUserConversion!
+
+ Fixes bug #44468.
+
+2003-07-28 Miguel de Icaza <miguel@ximian.com>
+
+ * codegen.cs: Compute IsGeneric correctly.
+
+ * cs-parser.jay: Introduce OP_GENERIC_LT for the grammar ambiguity
+ resolution.
+
+ Bring back (temporarily) OP_LEFT_SHIFT, OP_RIGHT_SHIFT,
+ OP_SHIFT_RIGHT_ASSIGN, OP_SHIFT_LEFT_ASSIGN. There were too many
+ regressions, and I was chasing more bugs than I required.
+
+ * interface.cs: Use expressions for base type names (like classes
+ and structs have been doing for a while now), and resolve that.
+ This patch should probably go into head as well.
+
+ This makes it one less user of FindType.
+
+2003-07-24 Miguel de Icaza <miguel@ximian.com>
+
+ This compiler can not self host currently. Need to fix that.
+
+ * Makefile: compile to `gmcs.exe'
+
+ * driver.cs: Turn on v2 by default on gmcs.
+
+ * generic.cs (ConstructedType): Does no longer take a container
+ type argument; That will be taken care of later.
+
+ (ConstructedType.DoResolve, ConstructedType.ResolveAsTypeStep):
+ Use SimpleName to resolve for now, so we can continue the work on
+ the parser, until we get Type.GetType that understands generics.
+
+ (ConstructedType.ToString): Implement
+
+ (TypeArguments.Resolve): Resolve the child expressions as types.
+
+ * cs-parser.jay: Rename interface_constraints to
+ type_parameter_constraints
+
+ (namespace_or_type_name): Only use constructed types for the basic
+ construction, we will deal with identifier<...> later.
+
+ (type/type_name): No longer call DecomposeQI, as
+ namespace_or_type_name is always decoded now.
+
+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 Miguel de Icaza <miguel@ximian.com>
+
+ * cs-parser.jay (namespace_name): do not use
+ namespace_or_type_name, use qualified_identifier, because
+ namespace_or_type_name will soon return a composed expression
+ instead of a string.
+
+ (namespace_or_type_name): Instead of returning a string, now this
+ production returns an expression.
+
+ * codegen.cs (EmitContext): Setup IsGeneric property based on
+ whether our DeclSpace is generic, our the method is generic.
+
+ * modifier.cs (Modifiers.METHOD_GENERIC): New definition, use if
+ the method is generic.
+
+ * cs-parser.jay (type_arguments, opt_type_argument_list,
+ type_parameters, type_parameter_list, opt_type_parameter_list,
+ type_parameter,, opt_type_parameter_constraints_clauses,
+ type_parameter_constraints_clauses,
+ type_parameter_constraint_clause, type_parameter_constraint,
+ interface_constraints): Add new production
+
+ * decl.cs (DeclSpace): IsGeneric, flag to track whether this
+ DeclSpace is generic or not.
+
+ (DeclSpace.SetParameterInfo): New routine, used to set the
+ parameter info for a type.
+
+ (DeclSpace.LookupGeneric): Lookups a name, and if it is a generic,
+ returns a GenericTypeExpr
+
+ * ecore.cs (SimpleName.ResolveAsTypeStep): If our container is
+ generic, lookup the generic argument.
+
+ * attribute.cs: Do not allow TypeParameterExpressions in
+ Attributes.
+
+ * class.cs: Do not allow the Main method to be defined in a
+ Generic container.
+
+ * expression.cs (SizeOf): Do not allow generic types to be used as
+ arguments to sizeof.
+
+ * typemanager.cs (IsGeneric): Wrapper for Reflection when we have
+ it: whether a type is generic or not. Only works for types we are
+ currently building for now.
+
+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>
+
+ * expression.cs (SizeOf.DoResolve): Use ResolveTypeExpr, so we can
+ probe if its a type parameter, and if so, flag an error.
+
+ * decl.cs: Move here the SetParameterInfo code from class.cs.
+ Handle IsGeneric here.
+
+ Handle a variety of errors in the parameter info definition.
+
+ * ecore.cs (SimpleName.DoResolveType): Handle look ups for generic
+ type parameters here.
+
+ * cs-parser.jay (class_declaration): report errors for parameters
+ here as well.
+
+2003-01-21 Miguel de Icaza <miguel@ximian.com>
+
+ * generic.cs: New file, contains support code for generics.
+
+ * cs-parser.jay: Remove OP_SHIFT_LEFT, OP_SHIFT_RIGHT,
+ OP_SHIFT_LEFT_ASSIGN, OP_SHIFT_RIGHT_ASSIGN.
+
+ Update parser for the above removals.
+
+ * cs-tokenizer.cs: Do not handle <<= or >>= specially. This is
+ now taken care of in the parser.
+
+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.
+
--- /dev/null
+//
+// CryptoConvert.cs - Crypto Convertion Routines
+//
+// Author:
+// Sebastien Pouliot <sebastien@ximian.com>
+//
+// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
+// (C) 2004 Novell (http://www.novell.com)
+//
+
+using System;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Mono.Security.Cryptography {
+
+#if INSIDE_CORLIB
+ internal
+#else
+ public
+#endif
+ sealed class CryptoConvert {
+
+ private CryptoConvert ()
+ {
+ }
+
+ static private int ToInt32LE (byte [] bytes, int offset)
+ {
+ return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset];
+ }
+
+ static private uint ToUInt32LE (byte [] bytes, int offset)
+ {
+ return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]);
+ }
+
+ static private byte [] GetBytesLE (int val)
+ {
+ return new byte [] {
+ (byte) (val & 0xff),
+ (byte) ((val >> 8) & 0xff),
+ (byte) ((val >> 16) & 0xff),
+ (byte) ((val >> 24) & 0xff)
+ };
+ }
+
+ static private byte[] Trim (byte[] array)
+ {
+ for (int i=0; i < array.Length; i++) {
+ if (array [i] != 0x00) {
+ byte[] result = new byte [array.Length - i];
+ Buffer.BlockCopy (array, i, result, 0, result.Length);
+ return result;
+ }
+ }
+ return null;
+ }
+
+ // convert the key from PRIVATEKEYBLOB to RSA
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp
+ // e.g. SNK files, PVK files
+ static public RSA FromCapiPrivateKeyBlob (byte[] blob)
+ {
+ return FromCapiPrivateKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ try {
+ if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07)
+ (blob [offset+1] != 0x02) || // Version (0x02)
+ (blob [offset+2] != 0x00) || // Reserved (word)
+ (blob [offset+3] != 0x00) ||
+ (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2
+ throw new CryptographicException ("Invalid blob header");
+
+ // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+ int algId = ToInt32LE (blob, offset+4);
+
+ // DWORD bitlen
+ int bitLen = ToInt32LE (blob, offset+12);
+
+ // DWORD public exponent
+ RSAParameters rsap = new RSAParameters ();
+ byte[] exp = new byte [4];
+ Buffer.BlockCopy (blob, offset+16, exp, 0, 4);
+ Array.Reverse (exp);
+ rsap.Exponent = Trim (exp);
+
+ int pos = offset+20;
+ // BYTE modulus[rsapubkey.bitlen/8];
+ int byteLen = (bitLen >> 3);
+ rsap.Modulus = new byte [byteLen];
+ Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+ Array.Reverse (rsap.Modulus);
+ pos += byteLen;
+
+ // BYTE prime1[rsapubkey.bitlen/16];
+ int byteHalfLen = (byteLen >> 1);
+ rsap.P = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen);
+ Array.Reverse (rsap.P);
+ pos += byteHalfLen;
+
+ // BYTE prime2[rsapubkey.bitlen/16];
+ rsap.Q = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen);
+ Array.Reverse (rsap.Q);
+ pos += byteHalfLen;
+
+ // BYTE exponent1[rsapubkey.bitlen/16];
+ rsap.DP = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen);
+ Array.Reverse (rsap.DP);
+ pos += byteHalfLen;
+
+ // BYTE exponent2[rsapubkey.bitlen/16];
+ rsap.DQ = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen);
+ Array.Reverse (rsap.DQ);
+ pos += byteHalfLen;
+
+ // BYTE coefficient[rsapubkey.bitlen/16];
+ rsap.InverseQ = new byte [byteHalfLen];
+ Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen);
+ Array.Reverse (rsap.InverseQ);
+ pos += byteHalfLen;
+
+ // ok, this is hackish but CryptoAPI support it so...
+ // note: only works because CRT is used by default
+ // http://bugzilla.ximian.com/show_bug.cgi?id=57941
+ rsap.D = new byte [byteLen]; // must be allocated
+ if (pos + byteLen + offset <= blob.Length) {
+ // BYTE privateExponent[rsapubkey.bitlen/8];
+ Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen);
+ Array.Reverse (rsap.D);
+ }
+
+ RSA rsa = (RSA)RSA.Create ();
+ rsa.ImportParameters (rsap);
+ return rsa;
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+ }
+
+ static public byte[] ToCapiPrivateKeyBlob (RSA rsa)
+ {
+ RSAParameters p = rsa.ExportParameters (true);
+ int keyLength = p.Modulus.Length; // in bytes
+ byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)];
+
+ blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+ blob [8] = 0x52; // Magic - RSA2 (ASCII in hex)
+ blob [9] = 0x53;
+ blob [10] = 0x41;
+ blob [11] = 0x32;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0]; // bitlen
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ // public exponent (DWORD)
+ int pos = 16;
+ int n = p.Exponent.Length;
+ while (n > 0)
+ blob [pos++] = p.Exponent [--n];
+ // modulus
+ pos = 20;
+ byte[] part = p.Modulus;
+ int len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+ // private key
+ part = p.P;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.Q;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.DP;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.DQ;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.InverseQ;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+
+ part = p.D;
+ len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+
+ return blob;
+ }
+
+ static public RSA FromCapiPublicKeyBlob (byte[] blob)
+ {
+ return FromCapiPublicKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ try {
+ if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06)
+ (blob [offset+1] != 0x02) || // Version (0x02)
+ (blob [offset+2] != 0x00) || // Reserved (word)
+ (blob [offset+3] != 0x00) ||
+ (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1
+ throw new CryptographicException ("Invalid blob header");
+
+ // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
+ int algId = ToInt32LE (blob, offset+4);
+
+ // DWORD bitlen
+ int bitLen = ToInt32LE (blob, offset+12);
+
+ // DWORD public exponent
+ RSAParameters rsap = new RSAParameters ();
+ rsap.Exponent = new byte [3];
+ rsap.Exponent [0] = blob [offset+18];
+ rsap.Exponent [1] = blob [offset+17];
+ rsap.Exponent [2] = blob [offset+16];
+
+ int pos = offset+20;
+ // BYTE modulus[rsapubkey.bitlen/8];
+ int byteLen = (bitLen >> 3);
+ rsap.Modulus = new byte [byteLen];
+ Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
+ Array.Reverse (rsap.Modulus);
+
+ RSA rsa = (RSA)RSA.Create ();
+ rsa.ImportParameters (rsap);
+ return rsa;
+ }
+ catch (Exception e) {
+ throw new CryptographicException ("Invalid blob.", e);
+ }
+ }
+
+ static public byte[] ToCapiPublicKeyBlob (RSA rsa)
+ {
+ RSAParameters p = rsa.ExportParameters (false);
+ int keyLength = p.Modulus.Length; // in bytes
+ byte[] blob = new byte [20 + keyLength];
+
+ blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
+ blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
+ // [2], [3] // RESERVED - Always 0
+ blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
+ blob [8] = 0x52; // Magic - RSA1 (ASCII in hex)
+ blob [9] = 0x53;
+ blob [10] = 0x41;
+ blob [11] = 0x31;
+
+ byte[] bitlen = GetBytesLE (keyLength << 3);
+ blob [12] = bitlen [0]; // bitlen
+ blob [13] = bitlen [1];
+ blob [14] = bitlen [2];
+ blob [15] = bitlen [3];
+
+ // public exponent (DWORD)
+ int pos = 16;
+ int n = p.Exponent.Length;
+ while (n > 0)
+ blob [pos++] = p.Exponent [--n];
+ // modulus
+ pos = 20;
+ byte[] part = p.Modulus;
+ int len = part.Length;
+ Array.Reverse (part, 0, len);
+ Buffer.BlockCopy (part, 0, blob, pos, len);
+ pos += len;
+ return blob;
+ }
+
+ // PRIVATEKEYBLOB
+ // PUBLICKEYBLOB
+ static public RSA FromCapiKeyBlob (byte[] blob)
+ {
+ return FromCapiKeyBlob (blob, 0);
+ }
+
+ static public RSA FromCapiKeyBlob (byte[] blob, int offset)
+ {
+ if (blob == null)
+ throw new ArgumentNullException ("blob");
+ if (offset >= blob.Length)
+ throw new ArgumentException ("blob is too small.");
+
+ switch (blob [offset]) {
+ case 0x00:
+ // this could be a public key inside an header
+ // like "sn -e" would produce
+ if (blob [offset + 12] == 0x06) {
+ return FromCapiPublicKeyBlob (blob, offset + 12);
+ }
+ break;
+ case 0x06:
+ return FromCapiPublicKeyBlob (blob, offset);
+ case 0x07:
+ return FromCapiPrivateKeyBlob (blob, offset);
+ }
+ throw new CryptographicException ("Unknown blob format.");
+ }
+
+ static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey)
+ {
+ if (keypair == null)
+ throw new ArgumentNullException ("keypair");
+
+ // check between RSA and DSA (and potentially others like DH)
+ if (keypair is RSA)
+ return ToCapiKeyBlob ((RSA)keypair, includePrivateKey);
+ else
+ return null; // TODO
+ }
+
+ static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey)
+ {
+ if (rsa == null)
+ throw new ArgumentNullException ("rsa");
+
+ RSAParameters p = rsa.ExportParameters (includePrivateKey);
+ if (includePrivateKey)
+ return ToCapiPrivateKeyBlob (rsa);
+ else
+ return ToCapiPublicKeyBlob (rsa);
+ }
+
+ static public string ToHex (byte[] input)
+ {
+ if (input == null)
+ return null;
+
+ StringBuilder sb = new StringBuilder (input.Length * 2);
+ foreach (byte b in input) {
+ sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
+ }
+ return sb.ToString ();
+ }
+
+ static private byte FromHexChar (char c)
+ {
+ if ((c >= 'a') && (c <= 'f'))
+ return (byte) (c - 'a' + 10);
+ if ((c >= 'A') && (c <= 'F'))
+ return (byte) (c - 'A' + 10);
+ if ((c >= '0') && (c <= '9'))
+ return (byte) (c - '0');
+ throw new ArgumentException ("invalid hex char");
+ }
+
+ static public byte[] FromHex (string hex)
+ {
+ if (hex == null)
+ return null;
+ if ((hex.Length & 0x1) == 0x1)
+ throw new ArgumentException ("Length must be a multiple of 2");
+
+ byte[] result = new byte [hex.Length >> 1];
+ int n = 0;
+ int i = 0;
+ while (n < result.Length) {
+ result [n] = (byte) (FromHexChar (hex [i++]) << 4);
+ result [n++] += FromHexChar (hex [i++]);
+ }
+ return result;
+ }
+ }
+}
--- /dev/null
+#
+# This makefile needs work, currently we overwrite the value of `bmcs.exe',
+# the reason is that we need this to be compiled with gmcs, so it uses the
+# .NET 2.0 profile.
+#
+thisdir := bmcs
+SUBDIRS :=
+include ../build/rules.make
+
+#uncomment to enable some debug stuff
+#DEBUG_FLAGS=/define:MCS_DEBUG
+
+BOOTSTRAP_MCS = MONO_PATH="$(topdir)/class/lib/net_2_0_bootstrap$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(topdir)/class/lib/net_2_0_bootstrap/mcs.exe $(DEBUG_FLAGS)
+
+BUILT_SOURCES = mb-parser.cs
+
+EXTRA_DISTFILES = mb-parser.jay
+
+PROGRAM_COMPILE = $(BOOT_COMPILE)
+
+CLEAN_FILES = y.output
+
+PROGRAM = bmcs.exe
+
+mb-parser.cs: mb-parser.jay $(topdir)/jay/skeleton.cs
+ $(topdir)/jay/jay -ctv < $(topdir)/jay/skeleton.cs $< > jay-tmp.out && mv jay-tmp.out $@
+
+include ../build/executable.make
+
+bmcs.exe: mb-parser.cs
+ gmcs -d:NET_1_1 -d:ONLY_1_1 -debug /target:exe /out:bmcs.exe mb-parser.cs @bmcs.exe.sources -nowarn:219 -nowarn:162
+
+install-as-mbas: all
+ cp ../class/lib/default/bmcs.exe $(prefix)/lib/mono/1.0/mbas.exe
+
+winstall: all
+ cp ../class/lib/default/bmcs.exe /cygdrive/c/WINDOWS/Microsoft.NET/Framework/v1.1.4322/
+
+winstall-as-mbas: all
+ cp ../class/lib/default/bmcs.exe /cygdrive/c/WINDOWS/Microsoft.NET/Framework/v1.1.4322/
+ cp ../class/lib/default/bmcs.exe /cygdrive/c/WINDOWS/Microsoft.NET/Framework/v1.1.4322/mbas.exe
--- /dev/null
+* This is BMCS
+
+ Last merge to GMCS: 38733
+
+ BMCS is a new fork of the generics compiler from revision
+ 38733 (11th of January 2005).
+
+ This new compiler is based on the changes that Jambunathan did
+ to mcs from November 30th, 2004 to integrate the existing mbas
+ compiler with a more recent mcs.
+
+ We have ported those changes to use `gmcs' so that we get
+ support for generics into our VB compiler eventually.
+
+ Work toward integrating the improvements from mbas will go here.
+
+* LICENSING
+
+ Notice that the compiler might eventually need to go into the
+ class libraries. We request that contributors grant us permission
+ to relicense the code under the MIT X11 license if we have to.
+
--- /dev/null
+//
+// anonymous.cs: Support for anonymous methods
+//
+// Author:
+// Miguel de Icaza (miguel@ximain.com)
+//
+// (C) 2003, 2004 Novell, Inc.
+//
+// TODO: Ideally, we should have the helper classes emited as a hierarchy to map
+// their nesting, and have the visibility set to private, instead of NestedAssembly
+//
+//
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+ public class AnonymousMethod : Expression {
+ // Used to generate unique method names.
+ static int anonymous_method_count;
+
+ // An array list of AnonymousMethodParameter or null
+ public Parameters Parameters;
+
+ //
+ // The block that makes up the body for the anonymous mehtod
+ //
+ public ToplevelBlock Block;
+
+ //
+ // The container block for this anonymous method.
+ //
+ public Block ContainingBlock;
+
+ //
+ // The implicit method we create
+ //
+ public Method method;
+
+ MethodInfo invoke_mb;
+
+ // The emit context for the anonymous method
+ public EmitContext aec;
+ public InternalParameters amp;
+ bool unreachable;
+
+ //
+ // The modifiers applied to the method, we aggregate them
+ //
+ int method_modifiers = Modifiers.INTERNAL;
+
+ //
+ // During the resolve stage of the anonymous method body,
+ // we discover the actual scope where we are hosted, or
+ // null to host the method in the same class
+ //
+ public ScopeInfo Scope;
+
+ //
+ // Points to our container anonymous method if its present
+ //
+ public AnonymousMethod ContainerAnonymousMethod;
+
+ public AnonymousMethod (Parameters parameters, ToplevelBlock container, ToplevelBlock block, Location l)
+ {
+ Parameters = parameters;
+ Block = block;
+ loc = l;
+
+ //
+ // The order is important: this setups the CaptureContext tree hierarchy.
+ //
+ container.SetHaveAnonymousMethods (l, this);
+ block.SetHaveAnonymousMethods (l, this);
+ }
+
+ 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 = TypeManager.anonymous_method_type;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ // nothing, as we only exist to not do anything.
+ }
+
+ //
+ // Creates the host for the anonymous method
+ //
+ bool CreateMethodHost (EmitContext ec, Type return_type)
+ {
+ //
+ // Crude hack follows: we replace the TypeBuilder during the
+ // definition to get the method hosted in the right class
+ //
+
+ TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
+ TypeBuilder type_host = Scope == null ? current_type : Scope.ScopeTypeBuilder;
+
+ if (current_type == null)
+ throw new Exception ("The current_type is null");
+
+ if (type_host == null)
+ throw new Exception ("Type host is null");
+
+ if (current_type == type_host && ec.IsStatic){
+ if (ec.IsStatic)
+ method_modifiers |= Modifiers.STATIC;
+ current_type = null;
+ }
+
+ method = new Method (
+ (TypeContainer) ec.TypeContainer, null,
+ new TypeExpression (return_type, loc),
+ method_modifiers, false, new MemberName ("<#AnonymousMethod>" + anonymous_method_count++),
+ Parameters, null, loc);
+ method.Block = Block;
+
+
+ //
+ // Swap the TypeBuilder while we define the method, then restore
+ //
+ if (current_type != null)
+ ec.TypeContainer.TypeBuilder = type_host;
+ bool res = method.Define ();
+ if (current_type != null)
+ ec.TypeContainer.TypeBuilder = current_type;
+ return res;
+ }
+
+ void Error_ParameterMismatch (Type t)
+ {
+ Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
+ "{0}' since there is a parameter mismatch", t);
+ }
+
+ //
+ // Returns true if this anonymous method can be implicitly
+ // converted to the delegate type `delegate_type'
+ //
+ public Expression Compatible (EmitContext ec, Type delegate_type, bool probe)
+ {
+ //
+ // At this point its the first time we know the return type that is
+ // needed for the anonymous method. We create the method here.
+ //
+
+ MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec, delegate_type, loc);
+ invoke_mb = (MethodInfo) invoke_mg.Methods [0];
+ ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+ //
+ // If implicit parameters are set, then we must check for out in the parameters
+ // and flag it accordingly.
+ //
+ bool out_invalid_check = false;
+
+ if (Parameters == null){
+ int i, j;
+ out_invalid_check = true;
+
+ //
+ // We provide a set of inaccessible parameters
+ //
+ int params_idx = -1;
+ for (i = 0; i < invoke_pd.Count; i++){
+ if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+ params_idx = i;
+ }
+ int n = invoke_pd.Count - (params_idx != -1 ? 1 : 0);
+ Parameter [] fixedpars = new Parameter [n];
+
+ for (i = j = 0; i < invoke_pd.Count; i++){
+ if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)
+ continue;
+ fixedpars [j] = new Parameter (
+ new TypeExpression (invoke_pd.ParameterType (i), loc),
+ "+" + j, invoke_pd.ParameterModifier (i), null);
+ j++;
+ }
+
+ Parameter variable = null;
+ if (params_idx != -1){
+ variable = new Parameter (
+ new TypeExpression (invoke_pd.ParameterType (params_idx), loc),
+ "+" + params_idx, invoke_pd.ParameterModifier (params_idx), null);
+ }
+
+ Parameters = new Parameters (fixedpars, variable, loc);
+ }
+
+ //
+ // First, parameter types of `delegate_type' must be compatible
+ // with the anonymous method.
+ //
+ amp = new InternalParameters (Parameters.GetParameterInfo (ec), Parameters);
+
+ if (amp.Count != invoke_pd.Count){
+ if (!probe){
+ Report.Error (1593, loc,
+ "Anonymous method has {0} parameters, while delegate requires {1}",
+ amp.Count, invoke_pd.Count);
+ Error_ParameterMismatch (delegate_type);
+ }
+ return null;
+ }
+
+ for (int i = 0; i < amp.Count; i++){
+ Parameter.Modifier amp_mod = amp.ParameterModifier (i);
+ if (amp_mod != invoke_pd.ParameterModifier (i)){
+ if (!probe){
+ Report.Error (1676, loc,
+ "Signature mismatch in parameter modifier for parameter #0", i + 1);
+ Error_ParameterMismatch (delegate_type);
+ }
+ return null;
+ }
+
+ if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){
+ if (!probe){
+ Report.Error (1678, loc,
+ "Signature mismatch in parameter {0}: need `{1}' got `{2}'", i + 1,
+ TypeManager.CSharpName (invoke_pd.ParameterType (i)),
+ TypeManager.CSharpName (amp.ParameterType (i)));
+ Error_ParameterMismatch (delegate_type);
+ }
+ return null;
+ }
+
+ if (out_invalid_check && (invoke_pd.ParameterModifier (i) & Parameter.Modifier.OUT) != 0){
+ if (!probe){
+ Report.Error (1676, loc,"Parameter {0} must include the `out' modifier ", i+1);
+ Error_ParameterMismatch (delegate_type);
+ }
+ return null;
+ }
+ }
+
+ //
+ // If we are only probing, return ourselves
+ //
+ if (probe)
+ return this;
+
+ //
+ // Second: the return type of the delegate must be compatible with
+ // the anonymous type. Instead of doing a pass to examine the block
+ // we satisfy the rule by setting the return type on the EmitContext
+ // to be the delegate type return type.
+ //
+
+ //MethodBuilder builder = method_data.MethodBuilder;
+ //ILGenerator ig = builder.GetILGenerator ();
+
+
+ aec = new EmitContext (
+ ec.TypeContainer, ec.DeclSpace, loc, null,
+ invoke_mb.ReturnType,
+ /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
+ (ec.InUnsafe ? Modifiers.UNSAFE : 0),
+ /* No constructor */ false);
+
+ aec.CurrentAnonymousMethod = this;
+ ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
+ ContainingBlock = ec.CurrentBlock;
+
+ if (aec.ResolveTopBlock (ec, Block, amp, loc, out unreachable))
+ return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);
+
+ return null;
+ }
+
+ public MethodBuilder GetMethodBuilder ()
+ {
+ return method.MethodData.MethodBuilder;
+ }
+
+ public void EmitMethod (EmitContext ec)
+ {
+ if (!CreateMethodHost (ec, invoke_mb.ReturnType))
+ return;
+
+ MethodBuilder builder = GetMethodBuilder ();
+ ILGenerator ig = builder.GetILGenerator ();
+ aec.ig = ig;
+
+ Parameters.LabelParameters (aec, builder, loc);
+
+ //
+ // Adjust based on the computed state of the
+ // method from CreateMethodHost
+
+ if ((method_modifiers & Modifiers.STATIC) != 0)
+ aec.IsStatic = true;
+
+ aec.EmitMeta (Block, amp);
+ aec.EmitResolvedTopBlock (Block, unreachable);
+ }
+
+ public static void Error_AddressOfCapturedVar (string name, Location loc)
+ {
+ Report.Error (1686, loc,
+ "Variable {0} is captured in an anonymous method and its address is also being taken: they are exclusive", name);
+ }
+ }
+
+ //
+ // This will emit the code for the delegate, as well delegate creation on the host
+ //
+ public class AnonymousDelegate : DelegateCreation {
+ AnonymousMethod am;
+
+ public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
+ {
+ type = target_type;
+ loc = l;
+ this.am = am;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ am.EmitMethod (ec);
+
+ //
+ // Now emit the delegate creation.
+ //
+ if ((am.method.ModFlags & Modifiers.STATIC) == 0)
+ delegate_instance_expression = new AnonymousInstance (am);
+
+ Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);
+ constructor_method = ((MethodGroupExpr) ml).Methods [0];
+ delegate_method = am.GetMethodBuilder ();
+ base.Emit (ec);
+ }
+
+ class AnonymousInstance : Expression {
+ AnonymousMethod am;
+
+ public AnonymousInstance (AnonymousMethod am)
+ {
+ this.am = am;
+ eclass = ExprClass.Value;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ am.aec.EmitMethodHostInstance (ec, am);
+ }
+ }
+ }
+
+ class CapturedParameter {
+ public Type Type;
+ public FieldBuilder FieldBuilder;
+ public int Idx;
+
+ public CapturedParameter (Type type, int idx)
+ {
+ Type = type;
+ Idx = idx;
+ }
+ }
+
+ //
+ // Here we cluster all the variables captured on a given scope, we also
+ // keep some extra information that might be required on each scope.
+ //
+ public class ScopeInfo {
+ public CaptureContext CaptureContext;
+ public ScopeInfo ParentScope;
+ public Block ScopeBlock;
+ public bool NeedThis = false;
+ public bool HostsParameters = false;
+
+ // For tracking the number of scopes created.
+ public int id;
+ static int count;
+ bool inited = false;
+
+ ArrayList locals = new ArrayList ();
+ ArrayList children = new ArrayList ();
+
+ //
+ // The types and fields generated
+ //
+ public TypeBuilder ScopeTypeBuilder;
+ public ConstructorBuilder ScopeConstructor;
+ public FieldBuilder THIS;
+ public FieldBuilder ParentLink;
+
+ //
+ // Points to the object of type `ScopeTypeBuilder' that
+ // holds the data for the scope
+ //
+ public LocalBuilder ScopeInstance;
+
+
+ public ScopeInfo (CaptureContext cc, Block b)
+ {
+ CaptureContext = cc;
+ ScopeBlock = b;
+ id = count++;
+
+ cc.AddScope (this);
+ }
+
+ public void AddLocal (LocalInfo li)
+ {
+ if (locals.Contains (li))
+ return;
+
+ locals.Add (li);
+}
+
+ public bool IsCaptured (LocalInfo li)
+ {
+ return locals.Contains (li);
+ }
+
+ public void AddChild (ScopeInfo si)
+ {
+ if (children.Contains (si))
+ return;
+ children.Add (si);
+ }
+
+ static int indent = 0;
+
+ void Pad ()
+ {
+ for (int i = 0; i < indent; i++)
+ Console.Write (" ");
+ }
+
+ void EmitDebug ()
+ {
+ //Console.WriteLine (Environment.StackTrace);
+ Pad ();
+ Console.WriteLine ("START");
+ indent++;
+ Pad ();
+ Console.WriteLine ("NeedThis=" + NeedThis);
+ foreach (LocalInfo li in locals){
+ Pad ();
+ Console.WriteLine ("var {0}", li.Name);
+ }
+
+ foreach (ScopeInfo si in children)
+ si.EmitDebug ();
+ indent--;
+ Pad ();
+ Console.WriteLine ("END");
+ }
+
+ public string MakeHelperName ()
+ {
+ return String.Format ("<>AnonHelp<{0}>", id);
+ }
+
+ public void EmitScopeConstructor ()
+ {
+ Type [] constructor_types = TypeManager.NoTypes;
+ Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;
+ ScopeConstructor = ScopeTypeBuilder.DefineConstructor (
+ MethodAttributes.Public | MethodAttributes.HideBySig |
+ MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+ CallingConventions.HasThis, constructor_types);
+ InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+ TypeManager.RegisterMethod (ScopeConstructor, parameter_info, constructor_types);
+
+ ILGenerator cig = ScopeConstructor.GetILGenerator ();
+ cig.Emit (OpCodes.Ldarg_0);
+ cig.Emit (OpCodes.Call, TypeManager.object_ctor);
+ cig.Emit (OpCodes.Ret);
+ }
+
+ public void EmitScopeType (EmitContext ec)
+ {
+ //EmitDebug ();
+
+ if (ScopeTypeBuilder != null)
+ return;
+
+ ILGenerator ig = ec.ig;
+ TypeBuilder container = ec.TypeContainer.TypeBuilder;
+
+ ScopeTypeBuilder = container.DefineNestedType (
+ MakeHelperName (), TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.NestedAssembly,
+ TypeManager.object_type, null);
+
+ if (NeedThis)
+ THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly);
+
+ if (ParentScope != null){
+ if (ParentScope.ScopeTypeBuilder == null){
+ throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this));
+ }
+
+ ParentLink = ScopeTypeBuilder.DefineField ("<>parent", ParentScope.ScopeTypeBuilder,
+ FieldAttributes.Assembly);
+ }
+
+ if (NeedThis && ParentScope != null)
+ throw new Exception ("I was not expecting THIS && having a parent");
+
+ foreach (LocalInfo info in locals){
+ info.FieldBuilder = ScopeTypeBuilder.DefineField (
+ info.Name, info.VariableType, FieldAttributes.Assembly);
+ }
+
+ if (HostsParameters){
+ Hashtable captured_parameters = CaptureContext.captured_parameters;
+
+ foreach (DictionaryEntry de in captured_parameters){
+ string name = (string) de.Key;
+ CapturedParameter cp = (CapturedParameter) de.Value;
+ FieldBuilder fb;
+
+ fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
+ cp.FieldBuilder = fb;
+ }
+ }
+
+ EmitScopeConstructor ();
+ foreach (ScopeInfo si in children){
+ si.EmitScopeType (ec);
+ }
+ }
+
+ public void CloseTypes ()
+ {
+ RootContext.RegisterHelperClass (ScopeTypeBuilder);
+ foreach (ScopeInfo si in children)
+ si.CloseTypes ();
+ }
+
+ //
+ // Emits the initialization code for the scope
+ //
+ public void EmitInitScope (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (inited)
+ return;
+
+ ig.Emit (OpCodes.Newobj, (ConstructorInfo) ScopeConstructor);
+ ScopeInstance = ig.DeclareLocal (ScopeTypeBuilder);
+ ig.Emit (OpCodes.Stloc, ScopeInstance);
+
+ if (THIS != null){
+ ig.Emit (OpCodes.Ldloc, ScopeInstance);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Stfld, THIS);
+ }
+
+ //
+ // Copy the parameter values, if any
+ //
+ int extra = ec.IsStatic ? 0 : 1;
+ if (HostsParameters){
+ Hashtable captured_parameters = CaptureContext.captured_parameters;
+
+ foreach (DictionaryEntry de in captured_parameters){
+ string name = (string) de.Key;
+ CapturedParameter cp = (CapturedParameter) de.Value;
+
+ ig.Emit (OpCodes.Ldloc, ScopeInstance);
+ ParameterReference.EmitLdArg (ig, cp.Idx + extra);
+ ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
+ }
+ }
+
+ if (ParentScope != null){
+ //
+ // Only emit initialization in our capturecontext world
+ //
+ if (ParentScope.CaptureContext == CaptureContext){
+ ig.Emit (OpCodes.Ldloc, ScopeInstance);
+ ig.Emit (OpCodes.Ldloc, ParentScope.ScopeInstance);
+ ig.Emit (OpCodes.Stfld, ParentLink);
+ } else {
+ ig.Emit (OpCodes.Ldloc, ScopeInstance);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Stfld, ParentLink);
+ }
+ }
+ inited = true;
+ }
+
+ static void DoPath (StringBuilder sb, ScopeInfo start)
+ {
+ if (start.ParentScope != null){
+ DoPath (sb, start.ParentScope);
+ sb.Append (", ");
+ }
+ sb.Append ((start.id).ToString ());
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+
+ sb.Append ("{");
+ if (CaptureContext != null){
+ sb.Append (CaptureContext.ToString ());
+ sb.Append (":");
+ }
+
+ DoPath (sb, this);
+ sb.Append ("}");
+
+ return sb.ToString ();
+ }
+ }
+
+ //
+ // CaptureContext objects are created on demand if a method has
+ // anonymous methods and kept on the ToplevelBlock.
+ //
+ // If they exist, all ToplevelBlocks in the containing block are
+ // linked together (children pointing to their parents).
+ //
+ public class CaptureContext {
+ public static int count;
+ public int cc_id;
+ Location loc;
+
+ //
+ // Points to the toplevel block that owns this CaptureContext
+ //
+ ToplevelBlock toplevel_owner;
+ Hashtable scopes = new Hashtable ();
+ bool have_captured_vars = false;
+ ScopeInfo topmost = null;
+
+ //
+ // Captured fields
+ //
+ Hashtable captured_fields = new Hashtable ();
+ Hashtable captured_variables = new Hashtable ();
+ public Hashtable captured_parameters = new Hashtable ();
+ public AnonymousMethod Host;
+
+ public CaptureContext (ToplevelBlock toplevel_owner, Location loc, AnonymousMethod host)
+ {
+ cc_id = count++;
+ this.toplevel_owner = toplevel_owner;
+ this.loc = loc;
+
+ if (host != null)
+ Host = host;
+ }
+
+ void DoPath (StringBuilder sb, CaptureContext cc)
+ {
+ if (cc.ParentCaptureContext != null){
+ DoPath (sb, cc.ParentCaptureContext);
+ sb.Append (".");
+ }
+ sb.Append (cc_id.ToString ());
+ }
+
+ public override string ToString ()
+ {
+ ToplevelBlock parent = ParentToplevel;
+ StringBuilder sb = new StringBuilder ();
+
+ sb.Append ("[");
+ DoPath (sb, this);
+ sb.Append ("]");
+ return sb.ToString ();
+ }
+
+ public ToplevelBlock ParentToplevel {
+ get {
+ return toplevel_owner.Container;
+ }
+ }
+
+ public CaptureContext ParentCaptureContext {
+ get {
+ ToplevelBlock parent = ParentToplevel;
+
+ return (parent == null) ? null : parent.CaptureContext;
+ }
+ }
+
+ // Returns the deepest of two scopes
+ public ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
+ {
+ ScopeInfo p;
+
+ if (a == null)
+ return b;
+ if (b == null)
+ return a;
+ if (a == b)
+ return a;
+
+ //
+ // If they Scopes are on the same CaptureContext, we do the double
+ // checks just so if there is an invariant change in the future,
+ // we get the exception at the end
+ //
+ for (p = a; p != null; p = p.ParentScope)
+ if (p == b)
+ return a;
+
+ for (p = b; p != null; p = p.ParentScope)
+ if (p == a)
+ return b;
+
+ CaptureContext ca = a.CaptureContext;
+ CaptureContext cb = b.CaptureContext;
+
+ for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
+ if (c == cb)
+ return a;
+
+ for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
+ if (c == ca)
+ return b;
+ throw new Exception ("Should never be reached");
+ }
+
+ void AdjustMethodScope (AnonymousMethod am, ScopeInfo scope)
+ {
+ am.Scope = Deepest (am.Scope, scope);
+ }
+
+ void LinkScope (ScopeInfo scope, int id)
+ {
+ ScopeInfo parent = (ScopeInfo) scopes [id];
+ scope.ParentScope = parent;
+ parent.AddChild (scope);
+
+ if (scope == topmost)
+ topmost = parent;
+ }
+
+ public void AddLocal (AnonymousMethod am, LocalInfo li)
+ {
+ if (li.Block.Toplevel != toplevel_owner){
+ ParentCaptureContext.AddLocal (am, li);
+ return;
+ }
+ int block_id = li.Block.ID;
+ ScopeInfo scope;
+ if (scopes [block_id] == null){
+ scope = new ScopeInfo (this, li.Block);
+ scopes [block_id] = scope;
+ } else
+ scope = (ScopeInfo) scopes [block_id];
+
+ if (topmost == null){
+ topmost = scope;
+ } else {
+ // Link to parent
+ for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
+ if (scopes [b.ID] != null){
+ LinkScope (scope, b.ID);
+ break;
+ }
+ }
+
+ if (scope.ParentScope == null && ParentCaptureContext != null){
+ CaptureContext pcc = ParentCaptureContext;
+
+ for (Block b = am.ContainingBlock; b != null; b = b.Parent){
+ if (pcc.scopes [b.ID] != null){
+ pcc.LinkScope (scope, b.ID);
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // Adjust the owner
+ //
+ if (Host != null)
+ AdjustMethodScope (Host, topmost);
+
+ //
+ // Adjust the user
+ //
+ AdjustMethodScope (am, scope);
+
+ if (captured_variables [li] != null)
+ return;
+
+ have_captured_vars = true;
+ captured_variables [li] = li;
+ scope.AddLocal (li);
+ }
+
+ //
+ // Retursn the CaptureContext for the block that defines the parameter `name'
+ //
+ static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
+ {
+ ToplevelBlock container = current.Container;
+ if (container != null){
+ CaptureContext cc = _ContextForParameter (container, name);
+ if (cc != null)
+ return cc;
+ }
+ if (current.IsParameterReference (name))
+ return current.ToplevelBlockCaptureContext;
+ return null;
+ }
+
+ static CaptureContext ContextForParameter (ToplevelBlock current, string name)
+ {
+ CaptureContext cc = _ContextForParameter (current, name);
+ if (cc == null)
+ throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
+ return cc;
+ }
+
+ //
+ // Records the captured parameter at the appropriate CaptureContext
+ //
+ public void AddParameter (EmitContext ec, AnonymousMethod am, string name, Type t, int idx)
+ {
+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+
+ cc.AddParameterToContext (am, name, t, idx);
+ }
+
+ //
+ // Records the parameters in the context
+ //
+ void AddParameterToContext (AnonymousMethod am, string name, Type t, int idx)
+ {
+ if (captured_parameters == null)
+ captured_parameters = new Hashtable ();
+ if (captured_parameters [name] != null)
+ return;
+ captured_parameters [name] = new CapturedParameter (t, idx);
+
+ if (topmost == null){
+ //
+ // Create one ScopeInfo, if there are none.
+ //
+ topmost = new ScopeInfo (this, toplevel_owner);
+ scopes [toplevel_owner.ID] = topmost;
+ } else {
+ //
+ // If the topmost ScopeInfo is not at the topblock level, insert
+ // a new ScopeInfo there.
+ //
+ if (topmost.ScopeBlock != toplevel_owner){
+ ScopeInfo par_si = new ScopeInfo (this, toplevel_owner);
+ scopes [toplevel_owner.ID] = topmost;
+ topmost.ParentScope = par_si;
+ topmost = par_si;
+ }
+ }
+
+ topmost.HostsParameters = true;
+ AdjustMethodScope (am, topmost);
+ }
+
+ //
+ // Captured fields are only recorded on the topmost CaptureContext, because that
+ // one is the one linked to the owner of instance fields
+ //
+ public void AddField (FieldExpr fe)
+ {
+ if (fe.FieldInfo.IsStatic)
+ throw new Exception ("Attempt to register a static field as a captured field");
+
+ CaptureContext parent = ParentCaptureContext;
+ if (parent != null)
+ parent.AddField (fe);
+ else
+ captured_fields [fe] = fe;
+ }
+
+
+ public bool HaveCapturedVariables {
+ get {
+ return have_captured_vars;
+ }
+ }
+
+ public bool HaveCapturedFields {
+ get {
+ CaptureContext parent = ParentCaptureContext;
+ if (parent != null)
+ return parent.HaveCapturedFields;
+ return captured_fields.Count > 0;
+ }
+ }
+
+ public bool IsCaptured (LocalInfo local)
+ {
+ foreach (ScopeInfo si in scopes.Values){
+ if (si.IsCaptured (local))
+ return true;
+ }
+ return false;
+ }
+
+ //
+ // Returns whether the parameter is captured
+ //
+ public bool IsParameterCaptured (string name)
+ {
+ if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
+ return true;
+
+ if (captured_parameters != null)
+ return captured_parameters [name] != null;
+ return false;
+ }
+
+ public void EmitHelperClasses (EmitContext ec)
+ {
+ if (topmost != null){
+ topmost.NeedThis = HaveCapturedFields;
+ topmost.EmitScopeType (ec);
+ }
+ }
+
+ public void CloseHelperClasses ()
+ {
+ if (topmost != null)
+ topmost.CloseTypes ();
+ }
+
+ ScopeInfo GetScopeFromBlock (EmitContext ec, Block b)
+ {
+ ScopeInfo si;
+
+ si = (ScopeInfo) scopes [b.ID];
+ if (si == null)
+ throw new Exception ("Si is null for block " + b.ID);
+ si.EmitInitScope (ec);
+
+ return si;
+ }
+
+ //
+ // Emits the opcodes necessary to load the instance of the captured
+ // variable in `li'
+ //
+ public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li, AnonymousMethod am)
+ {
+ ILGenerator ig = ec.ig;
+ ScopeInfo si;
+
+ if (li.Block.Toplevel == toplevel_owner){
+ si = GetScopeFromBlock (ec, li.Block);
+ ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+ return;
+ }
+
+ si = am.Scope;
+ ig.Emit (OpCodes.Ldarg_0);
+ if (si != null){
+ while (si.ScopeBlock.ID != li.Block.ID){
+ if (si.ParentLink != null)
+ ig.Emit (OpCodes.Ldfld, si.ParentLink);
+ si = si.ParentScope;
+ if (si == null)
+ throw new Exception (
+ String.Format ("Never found block {0} starting at {1} while looking up {2}",
+ li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
+ }
+ }
+ }
+
+ //
+ // Internal routine that loads the instance to reach parameter `name'
+ //
+ void EmitParameterInstance (EmitContext ec, string name)
+ {
+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+ if (cc != this){
+ cc.EmitParameterInstance (ec, name);
+ return;
+ }
+ Block invocation_block = ec.CurrentBlock;
+ CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+ ILGenerator ig = ec.ig;
+
+ ScopeInfo si;
+ if (ec.CurrentBlock == toplevel_owner){
+ si = GetScopeFromBlock (ec, toplevel_owner);
+ ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+ return;
+ }
+
+ si = ec.CurrentAnonymousMethod.Scope;
+ ig.Emit (OpCodes.Ldarg_0);
+ if (si != null){
+ while (si.ParentLink != null) {
+ ig.Emit (OpCodes.Ldfld, si.ParentLink);
+ si = si.ParentScope;
+ }
+ }
+ }
+
+ //
+ // Emits the code necessary to load the parameter named `name' within
+ // an anonymous method.
+ //
+ public void EmitParameter (EmitContext ec, string name)
+ {
+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+ if (cc != this){
+ cc.EmitParameter (ec, name);
+ return;
+ }
+ EmitParameterInstance (ec, name);
+ CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+ ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+ }
+
+ //
+ // Implements the assignment of `source' to the paramenter named `name' within
+ // an anonymous method.
+ //
+ public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+ if (cc != this){
+ cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load);
+ return;
+ }
+ ILGenerator ig = ec.ig;
+ CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+
+ EmitParameterInstance (ec, name);
+ source.Emit (ec);
+ if (leave_copy)
+ ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
+ }
+
+ //
+ // Emits the address for the parameter named `name' within
+ // an anonymous method.
+ //
+ public void EmitAddressOfParameter (EmitContext ec, string name)
+ {
+ CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+ if (cc != this){
+ cc.EmitAddressOfParameter (ec, name);
+ return;
+ }
+ EmitParameterInstance (ec, name);
+ CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+ ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
+ }
+
+ //
+ // The following methods are only invoked on the host for the
+ // anonymous method.
+ //
+ public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
+ {
+ ILGenerator ig = target.ig;
+ ScopeInfo si = am.Scope;
+
+ if (si == null){
+ ig.Emit (OpCodes.Ldarg_0);
+ return;
+ }
+
+ si.EmitInitScope (target);
+ ig.Emit (OpCodes.Ldloc, si.ScopeInstance);
+ }
+
+ ArrayList all_scopes = new ArrayList ();
+
+ public void AddScope (ScopeInfo si)
+ {
+ all_scopes.Add (si);
+ toplevel_owner.RegisterCaptureContext (this);
+ }
+
+ //
+ // Links any scopes that were not linked previously
+ //
+ public void AdjustScopes ()
+ {
+ foreach (ScopeInfo scope in all_scopes){
+ if (scope.ParentScope != null)
+ continue;
+
+ for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
+ if (scopes [b.ID] != null){
+ LinkScope (scope, b.ID);
+ break;
+ }
+ }
+
+ if (scope.ParentScope == null && ParentCaptureContext != null){
+ CaptureContext pcc = ParentCaptureContext;
+
+ for (Block b = Host.ContainingBlock; b != null; b = b.Parent){
+ if (pcc.scopes [b.ID] != null){
+ pcc.LinkScope (scope, b.ID);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//
+// assign.cs: Assignments.
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+// Martin Baulig (martin@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2004 Novell, 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 is an extra version of Emit. If leave_copy is `true'
+ // A copy of the expression will be left on the stack at the
+ // end of the code generated for EmitAssign
+ //
+ void Emit (EmitContext ec, bool leave_copy);
+
+ //
+ // This method does the assignment
+ // `source' will be stored into the location specified by `this'
+ // if `leave_copy' is true, a copy of `source' will be left on the stack
+ // if `prepare_for_load' is true, when `source' is emitted, there will
+ // be data on the stack that it can use to compuatate its value. This is
+ // for expressions like a [f ()] ++, where you can't call `f ()' twice.
+ //
+ void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
+
+ /*
+ For simple assignments, this interface is very simple, EmitAssign is called with source
+ as the source expression and leave_copy and prepare_for_load false.
+
+ For compound assignments it gets complicated.
+
+ EmitAssign will be called as before, however, prepare_for_load will be
+ true. The @source expression will contain an expression
+ which calls Emit. So, the calls look like:
+
+ this.EmitAssign (ec, source, false, true) ->
+ source.Emit (ec); ->
+ [...] ->
+ this.Emit (ec, false); ->
+ end this.Emit (ec, false); ->
+ end [...]
+ end source.Emit (ec);
+ end this.EmitAssign (ec, source, false, true)
+
+
+ When prepare_for_load is true, EmitAssign emits a `token' on the stack that
+ Emit will use for its state.
+
+ Let's take FieldExpr as an example. assume we are emitting f ().y += 1;
+
+ Here is the call tree again. This time, each call is annotated with the IL
+ it produces:
+
+ this.EmitAssign (ec, source, false, true)
+ call f
+ dup
+
+ Binary.Emit ()
+ this.Emit (ec, false);
+ ldfld y
+ end this.Emit (ec, false);
+
+ IntConstant.Emit ()
+ ldc.i4.1
+ end IntConstant.Emit
+
+ add
+ end Binary.Emit ()
+
+ stfld
+ end this.EmitAssign (ec, source, false, true)
+
+ Observe two things:
+ 1) EmitAssign left a token on the stack. It was the result of f ().
+ 2) This token was used by Emit
+
+ leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy
+ of the expression at that point in evaluation. This is used for pre/post inc/dec
+ and for a = x += y. Let's do the above example with leave_copy true in EmitAssign
+
+ this.EmitAssign (ec, source, true, true)
+ call f
+ dup
+
+ Binary.Emit ()
+ this.Emit (ec, false);
+ ldfld y
+ end this.Emit (ec, false);
+
+ IntConstant.Emit ()
+ ldc.i4.1
+ end IntConstant.Emit
+
+ add
+ end Binary.Emit ()
+
+ dup
+ stloc temp
+ stfld
+ ldloc temp
+ end this.EmitAssign (ec, source, true, true)
+
+ And with it true in Emit
+
+ this.EmitAssign (ec, source, false, true)
+ call f
+ dup
+
+ Binary.Emit ()
+ this.Emit (ec, true);
+ ldfld y
+ dup
+ stloc temp
+ end this.Emit (ec, true);
+
+ IntConstant.Emit ()
+ ldc.i4.1
+ end IntConstant.Emit
+
+ add
+ end Binary.Emit ()
+
+ stfld
+ ldloc temp
+ end this.EmitAssign (ec, source, false, true)
+
+ Note that these two examples are what happens for ++x and x++, respectively.
+ */
+ }
+
+ /// <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.
+ ///
+ /// If `is_address' is true, then the value that we store is the address to the
+ /// real value, and not the value itself.
+ ///
+ /// This is needed for a value type, because otherwise you just end up making a
+ /// copy of the value on the stack and modifying it. You really need a pointer
+ /// to the origional value so that you can modify it in that location. This
+ /// Does not happen with a class because a class is a pointer -- so you always
+ /// get the indirection.
+ ///
+ /// The `is_address' stuff is really just a hack. We need to come up with a better
+ /// way to handle it.
+ /// </remarks>
+ public class LocalTemporary : Expression, IMemoryLocation {
+ LocalBuilder builder;
+ bool is_address;
+
+ public LocalTemporary (EmitContext ec, Type t) : this (ec, t, false) {}
+
+ public LocalTemporary (EmitContext ec, Type t, bool is_address)
+ {
+ type = t;
+ eclass = ExprClass.Value;
+ loc = Location.Null;
+ builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (t): t);
+ this.is_address = is_address;
+ }
+
+ public LocalTemporary (LocalBuilder b, Type t)
+ {
+ type = t;
+ eclass = ExprClass.Value;
+ loc = Location.Null;
+ builder = b;
+ }
+
+ public void Release (EmitContext ec)
+ {
+ ec.FreeTemporaryLocal (builder, type);
+ builder = null;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ ig.Emit (OpCodes.Ldloc, builder);
+ // we need to copy from the pointer
+ if (is_address)
+ LoadFromPtr (ig, type);
+ }
+
+ // NB: if you have `is_address' on the stack there must
+ // be a managed pointer. Otherwise, it is the type from
+ // the ctor.
+ public void Store (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ ig.Emit (OpCodes.Stloc, builder);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ // if is_address, than this is just the address anyways,
+ // so we just return this.
+ ILGenerator ig = ec.ig;
+
+ if (is_address)
+ ig.Emit (OpCodes.Ldloc, builder);
+ else
+ ig.Emit (OpCodes.Ldloca, builder);
+ }
+
+ public bool PointsToAddress {
+ get {
+ return is_address;
+ }
+ }
+ }
+
+ /// <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 (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 BinaryDelegate)) {
+ error70 (ei, loc);
+ return null;
+ }
+ }
+ }
+
+ FieldExpr field_exp = target as FieldExpr;
+ if (field_exp != null && !ec.IsConstructor && !ec.IsFieldInitializer) {
+ field_exp = field_exp.InstanceExpression as FieldExpr;
+ if (field_exp != null && field_exp.FieldInfo.IsInitOnly) {
+ if (field_exp.IsStatic) {
+ Report.Error (1650, loc, "Members of static readonly field '{0}' cannot be assigned to " +
+ "(except in a static constructor or a variable initializer)", TypeManager.GetFullNameSignature (field_exp.FieldInfo));
+ } else {
+ Report.Error (1648, loc, "Members of readonly field '{0}' cannot be assigned to " +
+ "(except in a constructor or a variable initializer)", TypeManager.GetFullNameSignature (field_exp.FieldInfo));
+ }
+ return null;
+ }
+ }
+
+ if (!(target is IAssignMethod) && (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", loc);
+ return null;
+ } else if ((RootContext.Version == LanguageVersion.ISO_1) &&
+ (source is MethodGroupExpr)){
+ ((MethodGroupExpr) source).ReportUsageError ();
+ return null;
+
+ }
+
+ if (target_type == source_type){
+ if (source is New && target_type.IsValueType &&
+ (target.eclass != ExprClass.IndexerAccess) && (target.eclass != ExprClass.PropertyAccess)){
+ New n = (New) source;
+
+ if (n.SetValueTypeVariable (target))
+ return n;
+ else
+ return null;
+ }
+
+ 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){
+ //
+ // 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
+ //
+ if (Convert.ImplicitStandardConversionExists (ec, a.original_source, target_type))
+ return this;
+
+ //
+ // In the spec 2.4 they added: or if type of the target is int
+ // and the operator is a shift operator...
+ //
+ if (source_type == TypeManager.int32_type &&
+ (b.Oper == Binary.Operator.LeftShift || b.Oper == Binary.Operator.RightShift))
+ 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, false, false);
+ 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;
+ }
+
+ IAssignMethod am = (IAssignMethod) target;
+
+ 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;
+
+ am.EmitAssign (ec, temp_source, !is_statement, this is CompoundAssign);
+
+ 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);
+ }
+ }
+}
+
+
+
+
--- /dev/null
+//
+// attribute.cs: Attribute Handler
+//
+// Author: Ravi Pratap (ravi@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Text;
+
+namespace Mono.CSharp {
+
+ /// <summary>
+ /// Base class for objects that can have Attributes applied to them.
+ /// </summary>
+ public abstract class Attributable {
+ /// <summary>
+ /// Attributes for this type
+ /// </summary>
+ protected Attributes attributes;
+
+ public Attributable (Attributes attrs)
+ {
+ attributes = attrs;
+ }
+
+ public Attributes OptAttributes
+ {
+ get {
+ return attributes;
+ }
+ set {
+ attributes = value;
+ }
+ }
+
+ /// <summary>
+ /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
+ /// </summary>
+ public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
+
+ /// <summary>
+ /// Returns one AttributeTarget for this element.
+ /// </summary>
+ public abstract AttributeTargets AttributeTargets { get; }
+
+ public abstract bool IsClsCompliaceRequired (DeclSpace ds);
+
+ /// <summary>
+ /// Gets list of valid attribute targets for explicit target declaration.
+ /// The first array item is default target. Don't break this rule.
+ /// </summary>
+ public abstract string[] ValidAttributeTargets { get; }
+ };
+
+ public class Attribute {
+ public readonly string ExplicitTarget;
+ public AttributeTargets Target;
+
+ public readonly string Name;
+ public readonly ArrayList Arguments;
+
+ public readonly Location Location;
+
+ public Type Type;
+
+ // Is non-null if type is AttributeUsageAttribute
+ AttributeUsageAttribute usage_attribute;
+
+ public AttributeUsageAttribute UsageAttribute {
+ get {
+ return usage_attribute;
+ }
+ }
+
+ MethodImplOptions ImplOptions;
+ UnmanagedType UnmanagedType;
+ CustomAttributeBuilder cb;
+
+ // non-null if named args present after Resolve () is called
+ PropertyInfo [] prop_info_arr;
+ FieldInfo [] field_info_arr;
+ object [] field_values_arr;
+ object [] prop_values_arr;
+ object [] pos_values;
+
+ static PtrHashtable usage_attr_cache = new PtrHashtable ();
+
+ public Attribute (string target, string name, ArrayList args, Location loc)
+ {
+ Name = name;
+ Arguments = args;
+ Location = loc;
+ ExplicitTarget = target;
+ }
+
+ void Error_InvalidNamedArgument (string name)
+ {
+ Report.Error (617, Location, "Invalid attribute argument: '{0}'. Argument must be fields " +
+ "fields which are not readonly, static or const; or read-write instance properties.",
+ Name);
+ }
+
+ static void Error_AttributeArgumentNotValid (Location loc)
+ {
+ Report.Error (182, loc,
+ "An attribute argument must be a constant expression, typeof " +
+ "expression or array creation expression");
+ }
+
+ static void Error_TypeParameterInAttribute (Location loc)
+ {
+ Report.Error (
+ -202, loc, "Can not use a type parameter in an attribute");
+ }
+
+ /// <summary>
+ /// This is rather hack. We report many emit attribute error with same error to be compatible with
+ /// csc. But because csc has to report them this way because error came from ilasm we needn't.
+ /// </summary>
+ public void Error_AttributeEmitError (string inner)
+ {
+ Report.Error (647, Location, "Error emitting '{0}' attribute because '{1}'", Name, inner);
+ }
+
+ public void Error_InvalidSecurityParent ()
+ {
+ Error_AttributeEmitError ("it is attached to invalid parent");
+ }
+
+ void Error_AttributeConstructorMismatch ()
+ {
+ Report.Error (-6, Location,
+ "Could not find a constructor for this argument list.");
+ }
+
+ /// <summary>
+ /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
+ /// </summary>
+ protected virtual Type CheckAttributeType (EmitContext ec)
+ {
+ string NameAttribute = Name + "Attribute";
+ Type t1 = ec.ResolvingTypeTree
+ ? ec.DeclSpace.FindType (Location, Name)
+ : RootContext.LookupType (ec.DeclSpace, Name, true, Location);
+
+ // FIXME: Shouldn't do this for quoted attributes: [@A]
+ Type t2 = ec.ResolvingTypeTree
+ ? ec.DeclSpace.FindType (Location, NameAttribute)
+ : RootContext.LookupType (ec.DeclSpace, NameAttribute, true, Location);
+
+ String err0616 = null;
+ if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
+ t1 = null;
+ err0616 = "'" + Name + "': is not an attribute class";
+ }
+ if (t2 != null && ! t2.IsSubclassOf (TypeManager.attribute_type)) {
+ t2 = null;
+ err0616 = (err0616 != null)
+ ? "Neither '" + Name + "' nor '" + NameAttribute +"' is an attribute class"
+ : "'" + Name + "Attribute': is not an attribute class";
+ }
+
+ if (t1 != null && t2 != null) {
+ Report.Error(1614, Location, "'" + Name + "': is ambiguous; "
+ + " use either '@" + Name + "' or '" + NameAttribute + "'");
+ return null;
+ }
+ if (t1 != null)
+ return t1;
+ if (t2 != null)
+ return t2;
+ if (err0616 != null) {
+ Report.Error (616, Location, err0616);
+ return null;
+ }
+
+ Report.Error (246, Location,
+ "Could not find attribute '" + Name
+ + "' (are you missing a using directive or an assembly reference ?)");
+
+ return null;
+ }
+
+ public Type ResolveType (EmitContext ec)
+ {
+ if (Type == null)
+ Type = CheckAttributeType (ec);
+ return Type;
+ }
+
+ /// <summary>
+ /// Validates the guid string
+ /// </summary>
+ bool ValidateGuid (string guid)
+ {
+ try {
+ new Guid (guid);
+ return true;
+ } catch {
+ Report.Error (647, Location, "Format of GUID is invalid: " + guid);
+ return false;
+ }
+ }
+
+ string GetFullMemberName (string member)
+ {
+ return Type.FullName + '.' + member;
+ }
+
+ //
+ // Given an expression, if the expression is a valid attribute-argument-expression
+ // returns an object that can be used to encode it, or null on failure.
+ //
+ public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)
+ {
+ if (e is EnumConstant) {
+ if (RootContext.StdLib)
+ result = ((EnumConstant)e).GetValueAsEnumType ();
+ else
+ result = ((EnumConstant)e).GetValue ();
+
+ return true;
+ }
+
+ Constant constant = e as Constant;
+ if (constant != null) {
+ if (e.Type != arg_type) {
+ constant = Const.ChangeType (loc, constant, arg_type);
+ if (constant == null) {
+ result = null;
+ Error_AttributeArgumentNotValid (loc);
+ return false;
+ }
+ }
+ result = constant.GetValue ();
+ return true;
+ } else if (e is TypeOf) {
+ result = ((TypeOf) e).TypeArg;
+ return true;
+ } else if (e is ArrayCreation){
+ result = ((ArrayCreation) e).EncodeAsAttribute ();
+ if (result != null)
+ return true;
+ } else if (e is EmptyCast) {
+ Expression child = ((EmptyCast)e).Child;
+ return GetAttributeArgumentExpression (child, loc, child.Type, out result);
+ }
+
+ result = null;
+ Error_AttributeArgumentNotValid (loc);
+ return false;
+ }
+
+ public CustomAttributeBuilder Resolve (EmitContext ec)
+ {
+ Type oldType = Type;
+
+ // Sanity check.
+ Type = CheckAttributeType (ec);
+
+ if (oldType == null && Type == null)
+ return null;
+ if (oldType != null && oldType != Type){
+ Report.Error (-27, Location,
+ "Attribute {0} resolved to different types at different times: {1} vs. {2}",
+ Name, oldType, Type);
+ return null;
+ }
+
+ if (Type.IsAbstract) {
+ Report.Error (653, Location, "Cannot apply attribute class '{0}' because it is abstract", Name);
+ return null;
+ }
+
+ bool MethodImplAttr = false;
+ bool MarshalAsAttr = false;
+ bool GuidAttr = false;
+ bool usage_attr = false;
+
+ bool DoCompares = true;
+
+ //
+ // If we are a certain special attribute, we
+ // set the information accordingly
+ //
+
+ if (Type == TypeManager.attribute_usage_type)
+ usage_attr = true;
+ else if (Type == TypeManager.methodimpl_attr_type)
+ MethodImplAttr = true;
+ else if (Type == TypeManager.marshal_as_attr_type)
+ MarshalAsAttr = true;
+ else if (Type == TypeManager.guid_attr_type)
+ GuidAttr = true;
+ else
+ DoCompares = false;
+
+ // Now we extract the positional and named arguments
+
+ ArrayList pos_args = new ArrayList ();
+ ArrayList named_args = new ArrayList ();
+ int pos_arg_count = 0;
+
+ if (Arguments != null) {
+ pos_args = (ArrayList) Arguments [0];
+ if (pos_args != null)
+ pos_arg_count = pos_args.Count;
+ if (Arguments.Count > 1)
+ named_args = (ArrayList) Arguments [1];
+ }
+
+ pos_values = new object [pos_arg_count];
+
+ //
+ // First process positional arguments
+ //
+
+ int i;
+ for (i = 0; i < pos_arg_count; i++) {
+ Argument a = (Argument) pos_args [i];
+ Expression e;
+
+ if (!a.Resolve (ec, Location))
+ return null;
+
+ e = a.Expr;
+
+ object val;
+ if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))
+ return null;
+
+ pos_values [i] = val;
+
+ if (DoCompares){
+ if (usage_attr) {
+ usage_attribute = new AttributeUsageAttribute ((AttributeTargets)val);
+ } else if (MethodImplAttr) {
+ this.ImplOptions = (MethodImplOptions) val;
+ } else if (GuidAttr){
+ //
+ // we will later check the validity of the type
+ //
+ if (val is string){
+ if (!ValidateGuid ((string) val))
+ return null;
+ }
+
+ } else if (MarshalAsAttr)
+ this.UnmanagedType =
+ (System.Runtime.InteropServices.UnmanagedType) val;
+ }
+ }
+
+ //
+ // Now process named arguments
+ //
+
+ ArrayList field_infos = null;
+ ArrayList prop_infos = null;
+ ArrayList field_values = null;
+ ArrayList prop_values = null;
+
+ if (named_args.Count > 0) {
+ field_infos = new ArrayList ();
+ prop_infos = new ArrayList ();
+ field_values = new ArrayList ();
+ prop_values = new ArrayList ();
+ }
+
+ Hashtable seen_names = new Hashtable();
+
+ for (i = 0; i < named_args.Count; i++) {
+ DictionaryEntry de = (DictionaryEntry) named_args [i];
+ string member_name = (string) de.Key;
+ Argument a = (Argument) de.Value;
+ Expression e;
+
+ if (seen_names.Contains(member_name)) {
+ Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument");
+ return null;
+ }
+ seen_names.Add(member_name, 1);
+
+ if (!a.Resolve (ec, Location))
+ return null;
+
+ Expression member = Expression.MemberLookup (
+ ec, Type, member_name,
+ MemberTypes.Field | MemberTypes.Property,
+ BindingFlags.Public | BindingFlags.Instance,
+ Location);
+
+ if (member == null) {
+ member = Expression.MemberLookup (ec, Type, member_name,
+ MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,
+ Location);
+
+ if (member != null) {
+ Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", GetFullMemberName (member_name));
+ return null;
+ }
+ }
+
+ if (member == null){
+ Report.Error (117, Location, "Attribute `{0}' does not contain a definition for `{1}'",
+ Type, member_name);
+ return null;
+ }
+
+ if (!(member is PropertyExpr || member is FieldExpr)) {
+ Error_InvalidNamedArgument (member_name);
+ return null;
+ }
+
+ e = a.Expr;
+ if (e is TypeParameterExpr){
+ Error_TypeParameterInAttribute (Location);
+ return null;
+ }
+
+ if (member is PropertyExpr) {
+ PropertyExpr pe = (PropertyExpr) member;
+ PropertyInfo pi = pe.PropertyInfo;
+
+ if (!pi.CanWrite || !pi.CanRead) {
+ Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedArgument (member_name);
+ return null;
+ }
+
+ object value;
+ if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value))
+ return null;
+
+ if (usage_attribute != null) {
+ if (member_name == "AllowMultiple")
+ usage_attribute.AllowMultiple = (bool) value;
+ if (member_name == "Inherited")
+ usage_attribute.Inherited = (bool) value;
+ }
+
+ prop_values.Add (value);
+ prop_infos.Add (pi);
+
+ } else if (member is FieldExpr) {
+ FieldExpr fe = (FieldExpr) member;
+ FieldInfo fi = fe.FieldInfo;
+
+ if (fi.IsInitOnly) {
+ Error_InvalidNamedArgument (member_name);
+ return null;
+ }
+
+ object value;
+ if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value))
+ return null;
+
+ field_values.Add (value);
+
+ field_infos.Add (fi);
+ }
+ }
+
+ Expression mg = Expression.MemberLookup (
+ ec, Type, ".ctor", MemberTypes.Constructor,
+ BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+ Location);
+
+ if (mg == null) {
+ Error_AttributeConstructorMismatch ();
+ return null;
+ }
+
+ MethodBase constructor = Invocation.OverloadResolve (
+ ec, (MethodGroupExpr) mg, pos_args, false, Location);
+
+ if (constructor == null) {
+ return null;
+ }
+
+ //
+ // Now we perform some checks on the positional args as they
+ // cannot be null for a constructor which expects a parameter
+ // of type object
+ //
+
+ ParameterData pd = Invocation.GetParameterData (constructor);
+
+ int last_real_param = pd.Count;
+ if (pd.HasParams) {
+ // When the params is not filled we need to put one
+ if (last_real_param > pos_arg_count) {
+ object [] new_pos_values = new object [pos_arg_count + 1];
+ pos_values.CopyTo (new_pos_values, 0);
+ new_pos_values [pos_arg_count] = new object [] {} ;
+ pos_values = new_pos_values;
+ }
+ last_real_param--;
+ }
+
+ for (int j = 0; j < pos_arg_count; ++j) {
+ Argument a = (Argument) pos_args [j];
+
+ if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
+ Error_AttributeArgumentNotValid (Location);
+ return null;
+ }
+
+ if (j < last_real_param)
+ continue;
+
+ if (j == last_real_param) {
+ object [] array = new object [pos_arg_count - last_real_param];
+ array [0] = pos_values [j];
+ pos_values [j] = array;
+ continue;
+ }
+
+ object [] params_array = (object []) pos_values [last_real_param];
+ params_array [j - last_real_param] = pos_values [j];
+ }
+
+ // Adjust the size of the pos_values if it had params
+ if (last_real_param != pos_arg_count) {
+ object [] new_pos_values = new object [last_real_param + 1];
+ Array.Copy (pos_values, new_pos_values, last_real_param + 1);
+ pos_values = new_pos_values;
+ }
+
+ try {
+ if (named_args.Count > 0) {
+ prop_info_arr = new PropertyInfo [prop_infos.Count];
+ field_info_arr = new FieldInfo [field_infos.Count];
+ field_values_arr = new object [field_values.Count];
+ prop_values_arr = new object [prop_values.Count];
+
+ field_infos.CopyTo (field_info_arr, 0);
+ field_values.CopyTo (field_values_arr, 0);
+
+ prop_values.CopyTo (prop_values_arr, 0);
+ prop_infos.CopyTo (prop_info_arr, 0);
+
+ cb = new CustomAttributeBuilder (
+ (ConstructorInfo) constructor, pos_values,
+ prop_info_arr, prop_values_arr,
+ field_info_arr, field_values_arr);
+ }
+ else
+ cb = new CustomAttributeBuilder (
+ (ConstructorInfo) constructor, pos_values);
+ } catch (NullReferenceException) {
+ //
+ // Don't know what to do here
+ //
+ Report.Warning (
+ -101, Location, "NullReferenceException while trying to create attribute." +
+ "Something's wrong!");
+ } catch (Exception e) {
+ //
+ // Sample:
+ // using System.ComponentModel;
+ // [DefaultValue (CollectionChangeAction.Add)]
+ // class X { static void Main () {} }
+ //
+ Report.Warning (
+ -23, Location, "The compiler can not encode this attribute in .NET due to a bug in the .NET runtime. Try the Mono runtime. The exception was: " + e.Message);
+ }
+
+ return cb;
+ }
+
+ /// <summary>
+ /// Get a string containing a list of valid targets for the attribute 'attr'
+ /// </summary>
+ public string GetValidTargets ()
+ {
+ StringBuilder sb = new StringBuilder ();
+ AttributeTargets targets = GetAttributeUsage ().ValidOn;
+
+ if ((targets & AttributeTargets.Assembly) != 0)
+ sb.Append ("'assembly' ");
+
+ if ((targets & AttributeTargets.Class) != 0)
+ sb.Append ("'class' ");
+
+ if ((targets & AttributeTargets.Constructor) != 0)
+ sb.Append ("'constructor' ");
+
+ if ((targets & AttributeTargets.Delegate) != 0)
+ sb.Append ("'delegate' ");
+
+ if ((targets & AttributeTargets.Enum) != 0)
+ sb.Append ("'enum' ");
+
+ if ((targets & AttributeTargets.Event) != 0)
+ sb.Append ("'event' ");
+
+ if ((targets & AttributeTargets.Field) != 0)
+ sb.Append ("'field' ");
+
+ if ((targets & AttributeTargets.Interface) != 0)
+ sb.Append ("'interface' ");
+
+ if ((targets & AttributeTargets.Method) != 0)
+ sb.Append ("'method' ");
+
+ if ((targets & AttributeTargets.Module) != 0)
+ sb.Append ("'module' ");
+
+ if ((targets & AttributeTargets.Parameter) != 0)
+ sb.Append ("'parameter' ");
+
+ if ((targets & AttributeTargets.Property) != 0)
+ sb.Append ("'property' ");
+
+ if ((targets & AttributeTargets.ReturnValue) != 0)
+ sb.Append ("'return' ");
+
+ if ((targets & AttributeTargets.Struct) != 0)
+ sb.Append ("'struct' ");
+
+ return sb.ToString ();
+
+ }
+
+ /// <summary>
+ /// Returns AttributeUsage attribute for this type
+ /// </summary>
+ public AttributeUsageAttribute GetAttributeUsage ()
+ {
+ AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute;
+ if (ua != null)
+ return ua;
+
+ Class attr_class = TypeManager.LookupClass (Type);
+
+ if (attr_class == null) {
+ object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
+ ua = (AttributeUsageAttribute)usage_attr [0];
+ usage_attr_cache.Add (Type, ua);
+ return ua;
+ }
+
+ return attr_class.AttributeUsage;
+ }
+
+ /// <summary>
+ /// Returns custom name of indexer
+ /// </summary>
+ public string GetIndexerAttributeValue (EmitContext ec)
+ {
+ if (pos_values == null) {
+ // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
+ // But because a lot of attribute class code must be rewritten will be better to wait...
+ Resolve (ec);
+ }
+
+ return pos_values [0] as string;
+ }
+
+ /// <summary>
+ /// Returns condition of ConditionalAttribute
+ /// </summary>
+ public string GetConditionalAttributeValue (DeclSpace ds)
+ {
+ if (pos_values == null) {
+ EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+ // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
+ // But because a lot of attribute class code must be rewritten will be better to wait...
+ Resolve (ec);
+ }
+
+ // Some error occurred
+ if (pos_values [0] == null)
+ return null;
+
+ return (string)pos_values [0];
+ }
+
+ /// <summary>
+ /// Creates the instance of ObsoleteAttribute from this attribute instance
+ /// </summary>
+ public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+ {
+ if (pos_values == null) {
+ EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+ // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
+ // But because a lot of attribute class code must be rewritten will be better to wait...
+ Resolve (ec);
+ }
+
+ // Some error occurred
+ if (pos_values == null)
+ return null;
+
+ if (pos_values.Length == 0)
+ return new ObsoleteAttribute ();
+
+ if (pos_values.Length == 1)
+ return new ObsoleteAttribute ((string)pos_values [0]);
+
+ return new ObsoleteAttribute ((string)pos_values [0], (bool)pos_values [1]);
+ }
+
+ /// <summary>
+ /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
+ /// before ApplyAttribute. We need to resolve the arguments.
+ /// This situation occurs when class deps is differs from Emit order.
+ /// </summary>
+ public bool GetClsCompliantAttributeValue (DeclSpace ds)
+ {
+ if (pos_values == null) {
+ EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+ // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
+ // But because a lot of attribute class code must be rewritten will be better to wait...
+ Resolve (ec);
+ }
+
+ // Some error occurred
+ if (pos_values [0] == null)
+ return false;
+
+ return (bool)pos_values [0];
+ }
+
+ /// <summary>
+ /// Tests permitted SecurityAction for assembly or other types
+ /// </summary>
+ public bool CheckSecurityActionValidity (bool for_assembly)
+ {
+ SecurityAction action = GetSecurityActionValue ();
+
+ if ((action == SecurityAction.RequestMinimum || action == SecurityAction.RequestOptional || action == SecurityAction.RequestRefuse) && for_assembly)
+ return true;
+
+ if (!for_assembly) {
+ if (action < SecurityAction.Demand || action > SecurityAction.InheritanceDemand) {
+ Error_AttributeEmitError ("SecurityAction is out of range");
+ return false;
+ }
+
+ if ((action != SecurityAction.RequestMinimum && action != SecurityAction.RequestOptional && action != SecurityAction.RequestRefuse) && !for_assembly)
+ return true;
+ }
+
+ Error_AttributeEmitError (String.Concat ("SecurityAction '", action, "' is not valid for this declaration"));
+ return false;
+ }
+
+ System.Security.Permissions.SecurityAction GetSecurityActionValue ()
+ {
+ return (SecurityAction)pos_values [0];
+ }
+
+ /// <summary>
+ /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
+ /// </summary>
+ /// <returns></returns>
+ public void ExtractSecurityPermissionSet (ListDictionary permissions)
+ {
+ if (TypeManager.LookupDeclSpace (Type) != null && RootContext.StdLib) {
+ Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
+ return;
+ }
+
+ SecurityAttribute sa;
+ // For all assemblies except corlib we can avoid all hacks
+ if (RootContext.StdLib) {
+ sa = (SecurityAttribute) Activator.CreateInstance (Type, pos_values);
+
+ if (prop_info_arr != null) {
+ for (int i = 0; i < prop_info_arr.Length; ++i) {
+ PropertyInfo pi = prop_info_arr [i];
+ pi.SetValue (sa, prop_values_arr [i], null);
+ }
+ }
+ } else {
+ Type temp_type = Type.GetType (Type.FullName);
+ // HACK: All mscorlib attributes have same ctor syntax
+ sa = (SecurityAttribute) Activator.CreateInstance (temp_type, new object[] { GetSecurityActionValue () } );
+
+ // All types are from newly created corlib but for invocation with old we need to convert them
+ if (prop_info_arr != null) {
+ for (int i = 0; i < prop_info_arr.Length; ++i) {
+ PropertyInfo emited_pi = prop_info_arr [i];
+ PropertyInfo pi = temp_type.GetProperty (emited_pi.Name, emited_pi.PropertyType);
+
+ object old_instance = pi.PropertyType.IsEnum ?
+ System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
+ prop_values_arr [i];
+
+ pi.SetValue (sa, old_instance, null);
+ }
+ }
+ }
+
+ IPermission perm = sa.CreatePermission ();
+ SecurityAction action;
+
+ // IS is correct because for corlib we are using an instance from old corlib
+ if (perm is System.Security.CodeAccessPermission) {
+ action = GetSecurityActionValue ();
+ } else {
+ switch (GetSecurityActionValue ()) {
+ case SecurityAction.Demand:
+ action = (SecurityAction)13;
+ break;
+ case SecurityAction.LinkDemand:
+ action = (SecurityAction)14;
+ break;
+ case SecurityAction.InheritanceDemand:
+ action = (SecurityAction)15;
+ break;
+ default:
+ Error_AttributeEmitError ("Invalid SecurityAction for non-Code Access Security permission");
+ return;
+ }
+ }
+
+ PermissionSet ps = (PermissionSet)permissions [action];
+ if (ps == null) {
+ ps = new PermissionSet (PermissionState.None);
+ permissions.Add (action, ps);
+ }
+ ps.AddPermission (sa.CreatePermission ());
+ }
+
+ object GetValue (object value)
+ {
+ if (value is EnumConstant)
+ return ((EnumConstant) value).GetValue ();
+ else
+ return value;
+ }
+
+ public object GetPositionalValue (int i)
+ {
+ return (pos_values == null) ? null : pos_values[i];
+ }
+
+ object GetFieldValue (string name)
+ {
+ int i;
+ if (field_info_arr == null)
+ return null;
+ i = 0;
+ foreach (FieldInfo fi in field_info_arr) {
+ if (fi.Name == name)
+ return GetValue (field_values_arr [i]);
+ i++;
+ }
+ return null;
+ }
+
+ public UnmanagedMarshal GetMarshal (Attributable attr)
+ {
+ object value = GetFieldValue ("SizeParamIndex");
+ if (value != null && UnmanagedType != UnmanagedType.LPArray) {
+ Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
+ return null;
+ }
+
+ object o = GetFieldValue ("ArraySubType");
+ UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
+
+ switch (UnmanagedType) {
+ case UnmanagedType.CustomMarshaler:
+ MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
+ BindingFlags.Static | BindingFlags.Public);
+ if (define_custom == null) {
+ Report.RuntimeMissingSupport (Location, "set marshal info");
+ return null;
+ }
+
+ object [] args = new object [4];
+ args [0] = GetFieldValue ("MarshalTypeRef");
+ args [1] = GetFieldValue ("MarshalCookie");
+ args [2] = GetFieldValue ("MarshalType");
+ args [3] = Guid.Empty;
+ return (UnmanagedMarshal) define_custom.Invoke (null, args);
+
+ case UnmanagedType.LPArray:
+ return UnmanagedMarshal.DefineLPArray (array_sub_type);
+
+ case UnmanagedType.SafeArray:
+ return UnmanagedMarshal.DefineSafeArray (array_sub_type);
+
+ case UnmanagedType.ByValArray:
+ FieldMember fm = attr as FieldMember;
+ if (fm == null) {
+ Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
+ return null;
+ }
+ return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
+
+ case UnmanagedType.ByValTStr:
+ return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
+
+ default:
+ return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
+ }
+ }
+
+ public bool IsInternalCall
+ {
+ get { return ImplOptions == MethodImplOptions.InternalCall; }
+ }
+
+ /// <summary>
+ /// Emit attribute for Attributable symbol
+ /// </summary>
+ public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
+ {
+ CustomAttributeBuilder cb = Resolve (ec);
+ if (cb == null)
+ return;
+
+ AttributeUsageAttribute usage_attr = GetAttributeUsage ();
+ if ((usage_attr.ValidOn & Target) == 0) {
+ Report.Error (592, Location, "Attribute '{0}' is not valid on this declaration type. It is valid on {1} declarations only.", Name, GetValidTargets ());
+ return;
+ }
+
+ ias.ApplyAttributeBuilder (this, cb);
+
+ if (!usage_attr.AllowMultiple) {
+ ArrayList emitted_targets = (ArrayList)emitted_attr [Type];
+ if (emitted_targets == null) {
+ emitted_targets = new ArrayList ();
+ emitted_attr.Add (Type, emitted_targets);
+ } else if (emitted_targets.Contains (Target)) {
+ Report.Error (579, Location, "Duplicate '" + Name + "' attribute");
+ return;
+ }
+ emitted_targets.Add (Target);
+ }
+
+ if (!RootContext.VerifyClsCompliance)
+ return;
+
+ // Here we are testing attribute arguments for array usage (error 3016)
+ if (ias.IsClsCompliaceRequired (ec.DeclSpace)) {
+ if (Arguments == null)
+ return;
+
+ ArrayList pos_args = (ArrayList) Arguments [0];
+ if (pos_args != null) {
+ foreach (Argument arg in pos_args) {
+ // Type is undefined (was error 246)
+ if (arg.Type == null)
+ return;
+
+ if (arg.Type.IsArray) {
+ Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
+ return;
+ }
+ }
+ }
+
+ if (Arguments.Count < 2)
+ return;
+
+ ArrayList named_args = (ArrayList) Arguments [1];
+ foreach (DictionaryEntry de in named_args) {
+ Argument arg = (Argument) de.Value;
+
+ // Type is undefined (was error 246)
+ if (arg.Type == null)
+ return;
+
+ if (arg.Type.IsArray) {
+ Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant");
+ return;
+ }
+ }
+ }
+ }
+
+ public object GetValue (EmitContext ec, Constant c, Type target)
+ {
+ if (Convert.ImplicitConversionExists (ec, c, target))
+ return c.GetValue ();
+
+ Convert.Error_CannotImplicitConversion (Location, c.Type, target);
+ return null;
+ }
+
+ public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
+ MethodAttributes flags, Type ret_type, Type [] param_types)
+ {
+ //
+ // We extract from the attribute the information we need
+ //
+
+ if (Arguments == null) {
+ Console.WriteLine ("Internal error : this is not supposed to happen !");
+ return null;
+ }
+
+ ResolveType (ec);
+ if (Type == null)
+ return null;
+
+ ArrayList named_args = new ArrayList ();
+
+ ArrayList pos_args = (ArrayList) Arguments [0];
+ if (Arguments.Count > 1)
+ named_args = (ArrayList) Arguments [1];
+
+
+ string dll_name = null;
+
+ Argument tmp = (Argument) pos_args [0];
+
+ if (!tmp.Resolve (ec, Location))
+ return null;
+
+ if (tmp.Expr is Constant)
+ dll_name = (string) ((Constant) tmp.Expr).GetValue ();
+ else {
+ Error_AttributeArgumentNotValid (Location);
+ return null;
+ }
+
+ // Now we process the named arguments
+ CallingConvention cc = CallingConvention.Winapi;
+ CharSet charset = CharSet.Ansi;
+ bool preserve_sig = true;
+#if FIXME
+ bool exact_spelling = false;
+#endif
+ bool set_last_err = false;
+ string entry_point = null;
+
+ for (int i = 0; i < named_args.Count; i++) {
+
+ DictionaryEntry de = (DictionaryEntry) named_args [i];
+
+ string member_name = (string) de.Key;
+ Argument a = (Argument) de.Value;
+
+ if (!a.Resolve (ec, Location))
+ return null;
+
+ Expression member = Expression.MemberLookup (
+ ec, Type, member_name,
+ MemberTypes.Field | MemberTypes.Property,
+ BindingFlags.Public | BindingFlags.Instance,
+ Location);
+
+ if (member == null || !(member is FieldExpr)) {
+ Error_InvalidNamedArgument (member_name);
+ return null;
+ }
+
+ if (member is FieldExpr) {
+ FieldExpr fe = (FieldExpr) member;
+ FieldInfo fi = fe.FieldInfo;
+
+ if (fi.IsInitOnly) {
+ Error_InvalidNamedArgument (member_name);
+ return null;
+ }
+
+ if (a.Expr is Constant) {
+ Constant c = (Constant) a.Expr;
+
+ try {
+ if (member_name == "CallingConvention"){
+ object val = GetValue (ec, c, typeof (CallingConvention));
+ if (val == null)
+ return null;
+ cc = (CallingConvention) val;
+ } else if (member_name == "CharSet"){
+ charset = (CharSet) c.GetValue ();
+ } else if (member_name == "EntryPoint")
+ entry_point = (string) c.GetValue ();
+ else if (member_name == "SetLastError")
+ set_last_err = (bool) c.GetValue ();
+#if FIXME
+ else if (member_name == "ExactSpelling")
+ exact_spelling = (bool) c.GetValue ();
+#endif
+ else if (member_name == "PreserveSig")
+ preserve_sig = (bool) c.GetValue ();
+ } catch (InvalidCastException){
+ Error_InvalidNamedArgument (member_name);
+ Error_AttributeArgumentNotValid (Location);
+ }
+ } else {
+ Error_AttributeArgumentNotValid (Location);
+ return null;
+ }
+
+ }
+ }
+
+ if (entry_point == null)
+ entry_point = name;
+ if (set_last_err)
+ charset = (CharSet)((int)charset | 0x40);
+
+ MethodBuilder mb = builder.DefinePInvokeMethod (
+ name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
+ CallingConventions.Standard,
+ ret_type,
+ param_types,
+ cc,
+ charset);
+
+ if (preserve_sig)
+ mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
+
+ return mb;
+ }
+
+ private Expression GetValue ()
+ {
+ if ((Arguments == null) || (Arguments.Count < 1))
+ return null;
+ ArrayList al = (ArrayList) Arguments [0];
+ if ((al == null) || (al.Count < 1))
+ return null;
+ Argument arg = (Argument) al [0];
+ if ((arg == null) || (arg.Expr == null))
+ return null;
+ return arg.Expr;
+ }
+
+ public string GetString ()
+ {
+ Expression e = GetValue ();
+ if (e is StringLiteral)
+ return (e as StringLiteral).Value;
+ return null;
+ }
+
+ public bool GetBoolean ()
+ {
+ Expression e = GetValue ();
+ if (e is BoolLiteral)
+ return (e as BoolLiteral).Value;
+ return false;
+ }
+
+ public bool IsAssemblyAttribute {
+ get {
+ return ExplicitTarget == "assembly";
+ }
+ }
+
+ public bool IsModuleAttribute {
+ get {
+ return ExplicitTarget == "module";
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// For global attributes (assembly, module) we need special handling.
+ /// Attributes can be located in the several files
+ /// </summary>
+ public class GlobalAttribute: Attribute
+ {
+ public readonly NamespaceEntry ns;
+
+ public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):
+ base (target, name, args, loc)
+ {
+ ns = container.NamespaceEntry;
+ }
+
+ protected override Type CheckAttributeType (EmitContext ec)
+ {
+ // RootContext.Tree.Types has a single NamespaceEntry which gets overwritten
+ // each time a new file is parsed. However, we need to use the NamespaceEntry
+ // in effect where the attribute was used. Since code elsewhere cannot assume
+ // that the NamespaceEntry is right, just overwrite it.
+ //
+ // FIXME: Check every place the NamespaceEntry of RootContext.Tree.Types is used
+ // to ensure the right one is used.
+ if (ec.DeclSpace == RootContext.Tree.Types)
+ ec.DeclSpace.NamespaceEntry = ns;
+
+ return base.CheckAttributeType (ec);
+ }
+ }
+
+ public class Attributes {
+ public ArrayList Attrs;
+
+ public Attributes (Attribute a)
+ {
+ Attrs = new ArrayList ();
+ Attrs.Add (a);
+ }
+
+ public Attributes (ArrayList attrs)
+ {
+ Attrs = attrs;
+ }
+
+ public void AddAttributes (ArrayList attrs)
+ {
+ Attrs.AddRange (attrs);
+ }
+
+ public void AddAttribute (Attribute attr)
+ {
+ Attrs.Add (attr);
+ }
+
+ /// <summary>
+ /// Checks whether attribute target is valid for the current element
+ /// </summary>
+ public bool CheckTargets (Attributable member)
+ {
+ string[] valid_targets = member.ValidAttributeTargets;
+ foreach (Attribute a in Attrs) {
+ if (a.ExplicitTarget == null || a.ExplicitTarget == valid_targets [0]) {
+ a.Target = member.AttributeTargets;
+ continue;
+ }
+
+ // TODO: we can skip the first item
+ if (((IList) valid_targets).Contains (a.ExplicitTarget)) {
+ switch (a.ExplicitTarget) {
+ case "return": a.Target = AttributeTargets.ReturnValue; continue;
+ case "param": a.Target = AttributeTargets.Parameter; continue;
+ case "field": a.Target = AttributeTargets.Field; continue;
+ case "method": a.Target = AttributeTargets.Method; continue;
+ case "property": a.Target = AttributeTargets.Property; continue;
+ }
+ throw new InternalErrorException ("Unknown explicit target: " + a.ExplicitTarget);
+ }
+
+ StringBuilder sb = new StringBuilder ();
+ foreach (string s in valid_targets) {
+ sb.Append (s);
+ sb.Append (", ");
+ }
+ sb.Remove (sb.Length - 2, 2);
+ Report.Error (657, a.Location, "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'", a.ExplicitTarget, sb.ToString ());
+ return false;
+ }
+ return true;
+ }
+
+ public Attribute Search (Type t, EmitContext ec)
+ {
+ foreach (Attribute a in Attrs) {
+ if (a.ResolveType (ec) == t)
+ return a;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
+ /// </summary>
+ public Attribute[] SearchMulti (Type t, EmitContext ec)
+ {
+ ArrayList ar = null;
+
+ foreach (Attribute a in Attrs) {
+ if (a.ResolveType (ec) == t) {
+ if (ar == null)
+ ar = new ArrayList ();
+ ar.Add (a);
+ }
+ }
+
+ return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[];
+ }
+
+ public void Emit (EmitContext ec, Attributable ias)
+ {
+ if (!CheckTargets (ias))
+ return;
+
+ ListDictionary ld = new ListDictionary ();
+
+ foreach (Attribute a in Attrs)
+ a.Emit (ec, ias, ld);
+ }
+
+ public bool Contains (Type t, EmitContext ec)
+ {
+ return Search (t, ec) != null;
+ }
+ }
+
+ /// <summary>
+ /// Helper class for attribute verification routine.
+ /// </summary>
+ sealed class AttributeTester
+ {
+ static PtrHashtable analyzed_types = new PtrHashtable ();
+ static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
+ static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
+ static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+
+ private AttributeTester ()
+ {
+ }
+
+ /// <summary>
+ /// Returns true if parameters of two compared methods are CLS-Compliant.
+ /// It tests differing only in ref or out, or in array rank.
+ /// </summary>
+ public static bool AreOverloadedMethodParamsClsCompliant (Type[] types_a, Type[] types_b)
+ {
+ if (types_a == null || types_b == null)
+ return true;
+
+ if (types_a.Length != types_b.Length)
+ return true;
+
+ for (int i = 0; i < types_b.Length; ++i) {
+ Type aType = types_a [i];
+ Type bType = types_b [i];
+
+ if (aType.IsArray && bType.IsArray && aType.GetArrayRank () != bType.GetArrayRank () && aType.GetElementType () == bType.GetElementType ()) {
+ return false;
+ }
+
+ Type aBaseType = aType;
+ bool is_either_ref_or_out = false;
+
+ if (aType.IsByRef || aType.IsPointer) {
+ aBaseType = aType.GetElementType ();
+ is_either_ref_or_out = true;
+ }
+
+ Type bBaseType = bType;
+ if (bType.IsByRef || bType.IsPointer)
+ {
+ bBaseType = bType.GetElementType ();
+ is_either_ref_or_out = !is_either_ref_or_out;
+ }
+
+ if (aBaseType != bBaseType)
+ continue;
+
+ if (is_either_ref_or_out)
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Goes through all parameters and test if they are CLS-Compliant.
+ /// </summary>
+ public static bool AreParametersCompliant (Parameter[] fixedParameters, Location loc)
+ {
+ if (fixedParameters == null)
+ return true;
+
+ foreach (Parameter arg in fixedParameters) {
+ if (!AttributeTester.IsClsCompliant (arg.ParameterType)) {
+ Report.Error (3001, loc, "Argument type '{0}' is not CLS-compliant", arg.GetSignatureForError ());
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /// <summary>
+ /// This method tests the CLS compliance of external types. It doesn't test type visibility.
+ /// </summary>
+ public static bool IsClsCompliant (Type type)
+ {
+ if (type == null)
+ return true;
+
+ object type_compliance = analyzed_types[type];
+ if (type_compliance != null)
+ return type_compliance == TRUE;
+
+ if (type.IsPointer) {
+ analyzed_types.Add (type, null);
+ return false;
+ }
+
+ bool result;
+ if (type.IsArray || type.IsByRef) {
+ result = IsClsCompliant (TypeManager.GetElementType (type));
+ } else {
+ result = AnalyzeTypeCompliance (type);
+ }
+ analyzed_types.Add (type, result ? TRUE : FALSE);
+ return result;
+ }
+
+ static object TRUE = new object ();
+ static object FALSE = new object ();
+
+ public static void VerifyModulesClsCompliance ()
+ {
+ Module[] modules = TypeManager.Modules;
+ if (modules == null)
+ return;
+
+ // The first module is generated assembly
+ for (int i = 1; i < modules.Length; ++i) {
+ Module module = modules [i];
+ if (!IsClsCompliant (module)) {
+ Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute to match the assembly", module.Name);
+ return;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Tests container name for CLS-Compliant name (differing only in case)
+ /// </summary>
+ public static void VerifyTopLevelNameClsCompliance ()
+ {
+ Hashtable locase_table = new Hashtable ();
+
+ // Convert imported type names to lower case and ignore not cls compliant
+ foreach (DictionaryEntry de in TypeManager.all_imported_types) {
+ Type t = (Type)de.Value;
+ if (!AttributeTester.IsClsCompliant (t))
+ continue;
+
+ locase_table.Add (((string)de.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture), t);
+ }
+
+ foreach (DictionaryEntry de in RootContext.Tree.Decls) {
+ DeclSpace decl = (DeclSpace)de.Value;
+ if (!decl.IsClsCompliaceRequired (decl))
+ continue;
+
+ string lcase = decl.Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+ if (!locase_table.Contains (lcase)) {
+ locase_table.Add (lcase, decl);
+ continue;
+ }
+
+ object conflict = locase_table [lcase];
+ if (conflict is Type)
+ Report.SymbolRelatedToPreviousError ((Type)conflict);
+ else
+ Report.SymbolRelatedToPreviousError ((MemberCore)conflict);
+
+ Report.Error (3005, decl.Location, "Identifier '{0}' differing only in case is not CLS-compliant", decl.GetSignatureForError ());
+ }
+ }
+
+ static bool IsClsCompliant (ICustomAttributeProvider attribute_provider)
+ {
+ object[] CompliantAttribute = attribute_provider.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
+ if (CompliantAttribute.Length == 0)
+ return false;
+
+ return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant;
+ }
+
+ static bool AnalyzeTypeCompliance (Type type)
+ {
+ DeclSpace ds = TypeManager.LookupDeclSpace (type);
+ if (ds != null) {
+ return ds.IsClsCompliaceRequired (ds.Parent);
+ }
+
+ if (type.IsGenericParameter || type.IsGenericInstance)
+ return false;
+
+ object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
+ if (CompliantAttribute.Length == 0)
+ return IsClsCompliant (type.Assembly);
+
+ return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant;
+ }
+
+ /// <summary>
+ /// Returns instance of ObsoleteAttribute when type is obsolete
+ /// </summary>
+ public static ObsoleteAttribute GetObsoleteAttribute (Type type)
+ {
+ object type_obsolete = analyzed_types_obsolete [type];
+ if (type_obsolete == FALSE)
+ return null;
+
+ if (type_obsolete != null)
+ return (ObsoleteAttribute)type_obsolete;
+
+ ObsoleteAttribute result = null;
+ if (type.IsByRef || type.IsArray || type.IsPointer) {
+ result = GetObsoleteAttribute (TypeManager.GetElementType (type));
+ } else if (type.IsGenericParameter || type.IsGenericInstance)
+ return null;
+ else {
+ DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
+
+ // Type is external, we can get attribute directly
+ if (type_ds == null) {
+ object[] attribute = type.GetCustomAttributes (TypeManager.obsolete_attribute_type, false);
+ if (attribute.Length == 1)
+ result = (ObsoleteAttribute)attribute [0];
+ } else {
+ result = type_ds.GetObsoleteAttribute (type_ds);
+ }
+ }
+
+ analyzed_types_obsolete.Add (type, result == null ? FALSE : result);
+ return result;
+ }
+
+ /// <summary>
+ /// Returns instance of ObsoleteAttribute when method is obsolete
+ /// </summary>
+ public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
+ {
+ IMethodData mc = TypeManager.GetMethod (mb);
+ if (mc != null)
+ return mc.GetObsoleteAttribute ();
+
+ // compiler generated methods are not registered by AddMethod
+ if (mb.DeclaringType is TypeBuilder)
+ return null;
+
+ return GetMemberObsoleteAttribute (mb);
+ }
+
+ /// <summary>
+ /// Returns instance of ObsoleteAttribute when member is obsolete
+ /// </summary>
+ public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
+ {
+ object type_obsolete = analyzed_member_obsolete [mi];
+ if (type_obsolete == FALSE)
+ return null;
+
+ if (type_obsolete != null)
+ return (ObsoleteAttribute)type_obsolete;
+
+ if ((mi.DeclaringType is TypeBuilder) || mi.DeclaringType.IsGenericInstance)
+ return null;
+
+ ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false) as ObsoleteAttribute;
+ analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
+ return oa;
+ }
+
+ /// <summary>
+ /// Common method for Obsolete error/warning reporting.
+ /// </summary>
+ public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc)
+ {
+ if (oa.IsError) {
+ Report.Error (619, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
+ return;
+ }
+
+ if (oa.Message == null) {
+ Report.Warning (612, loc, "'{0}' is obsolete", member);
+ return;
+ }
+ if (RootContext.WarningLevel >= 2)
+ Report.Warning (618, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
+ }
+
+ public static bool IsConditionalMethodExcluded (MethodBase mb)
+ {
+ object excluded = analyzed_method_excluded [mb];
+ if (excluded != null)
+ return excluded == TRUE ? true : false;
+
+ if (mb.Mono_IsInflatedMethod)
+ return false;
+
+ ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[];
+ if (attrs.Length == 0) {
+ analyzed_method_excluded.Add (mb, FALSE);
+ return false;
+ }
+
+ foreach (ConditionalAttribute a in attrs) {
+ if (RootContext.AllDefines.Contains (a.ConditionString)) {
+ analyzed_method_excluded.Add (mb, FALSE);
+ return false;
+ }
+ }
+ analyzed_method_excluded.Add (mb, TRUE);
+ return true;
+ }
+ }
+}
--- /dev/null
+<configuration>\r
+ <startup>\r
+ <supportedRuntime version="v2.0.40607"/>\r
+ </startup>\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
--- /dev/null
+AssemblyInfo.cs
+anonymous.cs
+assign.cs
+attribute.cs
+driver.cs
+mb-tokenizer.cs
+cfold.cs
+class.cs
+codegen.cs
+const.cs
+constant.cs
+convert.cs
+decl.cs
+delegate.cs
+doc.cs
+enum.cs
+ecore.cs
+expression.cs
+flowanalysis.cs
+generic.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
+module.cs
+../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs
--- /dev/null
+//
+// 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
+ //
+#if WRONG
+ Constant match, other;
+#endif
+
+ if (left is ULongConstant){
+#if WRONG
+ other = right;
+ match = left;
+#endif
+ if (!(right is ULongConstant))
+ right = right.ToULong (loc);
+ } else {
+#if WRONG
+ other = left;
+ match = right;
+#endif
+ 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 other;
+ if (left is UIntConstant)
+ other = right;
+ else
+ other = left;
+
+ // Nothing to do.
+ if (other is UIntConstant)
+ return;
+
+ IntConstant ic = other as IntConstant;
+ if (ic != null){
+ if (ic.Value >= 0){
+ if (left == other)
+ left = new UIntConstant ((uint) ic.Value);
+ else
+ right = new UIntConstant ((uint) ic.Value);
+ return;
+ }
+ }
+
+ if (other is SByteConstant || other is ShortConstant || ic != null){
+ left = left.ToLong (loc);
+ right = right.ToLong (loc);
+ } else {
+ left = left.ToUInt (loc);
+ right = left.ToUInt (loc);
+ }
+
+ return;
+ } else if (left is DecimalConstant || right is DecimalConstant) {
+ if (!(left is DecimalConstant))
+ left = left.ToDecimal (loc);
+ else if (!(right is DecimalConstant))
+ right = right.ToDecimal (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;
+
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ 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 if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+
+ result = new DecimalConstant (res);
+ } else {
+ throw new Exception ( "Unexepected addition 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 if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
+ } else {
+ throw new Exception ( "Unexepected subtraction 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 if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
+ } else {
+ throw new Exception ( "Unexepected multiply 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 if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res);
+ } else {
+ throw new Exception ( "Unexepected division 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 modulus 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 NullLiteral){
+ if (right is NullLiteral)
+ return new BoolConstant (true);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value == null);
+ } else if (right is NullLiteral){
+ if (left is NullLiteral)
+ return new BoolConstant (true);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value == null);
+ }
+ 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 NullLiteral){
+ if (right is NullLiteral)
+ return new BoolConstant (false);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value != null);
+ } else if (right is NullLiteral){
+ if (left is NullLiteral)
+ return new BoolConstant (false);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value != null);
+ }
+ 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;
+ }
+ }
+}
--- /dev/null
+//
+// class.cs: Class and Struct handlers
+//
+// Authors: Miguel de Icaza (miguel@gnu.org)
+// Martin Baulig (martin@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+//
+// 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.Text;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Xml;
+
+using Mono.CompilerServices.SymbolWriter;
+
+namespace Mono.CSharp {
+
+ public enum Kind {
+ Root,
+ Struct,
+ Class,
+ Interface
+ }
+
+ /// <summary>
+ /// This is the base class for structs and classes.
+ /// </summary>
+ public abstract class TypeContainer : DeclSpace, IMemberContainer {
+
+ public class MemberCoreArrayList: ArrayList
+ {
+ /// <summary>
+ /// Defines the MemberCore objects that are in this array
+ /// </summary>
+ public virtual void DefineContainerMembers ()
+ {
+ foreach (MemberCore mc in this) {
+ mc.Define ();
+ }
+ }
+
+ public virtual void Emit ()
+ {
+ foreach (MemberCore mc in this)
+ mc.Emit ();
+ }
+ }
+
+ public class MethodArrayList: MemberCoreArrayList
+ {
+ [Flags]
+ enum CachedMethods {
+ Equals = 1,
+ GetHashCode = 1 << 1
+ }
+
+ CachedMethods cached_method;
+ TypeContainer container;
+
+ public MethodArrayList (TypeContainer container)
+ {
+ this.container = container;
+ }
+
+ /// <summary>
+ /// Method container contains Equals method
+ /// </summary>
+ public bool HasEquals {
+ set {
+ cached_method |= CachedMethods.Equals;
+ }
+
+ get {
+ return (cached_method & CachedMethods.Equals) != 0;
+ }
+ }
+
+ /// <summary>
+ /// Method container contains GetHashCode method
+ /// </summary>
+ public bool HasGetHashCode {
+ set {
+ cached_method |= CachedMethods.GetHashCode;
+ }
+
+ get {
+ return (cached_method & CachedMethods.GetHashCode) != 0;
+ }
+ }
+
+ public override void DefineContainerMembers ()
+ {
+ base.DefineContainerMembers ();
+
+ if ((RootContext.WarningLevel >= 3) && HasEquals && !HasGetHashCode) {
+ Report.Warning (659, container.Location, "'{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
+ }
+ }
+
+ }
+
+ public sealed class IndexerArrayList: MemberCoreArrayList
+ {
+ /// <summary>
+ /// The indexer name for this container
+ /// </summary>
+ public string IndexerName = DefaultIndexerName;
+
+ bool seen_normal_indexers = false;
+
+ TypeContainer container;
+
+ public IndexerArrayList (TypeContainer container)
+ {
+ this.container = container;
+ }
+
+ /// <summary>
+ /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
+ /// class 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 DefaultMember attribute is attached
+ /// to the class.
+ /// </summary>
+ public override void DefineContainerMembers()
+ {
+ base.DefineContainerMembers ();
+
+ 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.
+ //
+
+ // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
+ foreach (Indexer i in this) {
+ if (i.InterfaceType != null) {
+ if (seen_normal_indexers)
+ throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
+ continue;
+ }
+
+ seen_normal_indexers = true;
+
+ if (class_indexer_name == null) {
+ class_indexer_name = i.ShortName;
+ continue;
+ }
+
+ if (i.ShortName != class_indexer_name)
+ Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
+ }
+
+ if (class_indexer_name != null)
+ IndexerName = class_indexer_name;
+ }
+
+ public override void Emit ()
+ {
+ base.Emit ();
+
+ if (!seen_normal_indexers)
+ return;
+
+ CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
+ container.TypeBuilder.SetCustomAttribute (cb);
+ }
+ }
+
+ public class OperatorArrayList: MemberCoreArrayList
+ {
+ TypeContainer container;
+
+ public OperatorArrayList (TypeContainer container)
+ {
+ this.container = container;
+ }
+
+ //
+ // 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.ReturnType;
+ 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 this){
+ 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)) {
+ if (container.Methods == null || !container.Methods.HasEquals)
+ Report.Warning (660, container.Location, "'{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
+
+ if (container.Methods == null || !container.Methods.HasGetHashCode)
+ Report.Warning (661, container.Location, "'{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
+ }
+ }
+
+ public override void DefineContainerMembers ()
+ {
+ base.DefineContainerMembers ();
+ CheckPairedOperators ();
+ }
+ }
+
+
+ // Whether this is a struct, class or interface
+ public readonly Kind Kind;
+
+ // Holds a list of classes and structures
+ ArrayList types;
+
+ // Holds the list of properties
+ MemberCoreArrayList properties;
+
+ // Holds the list of enumerations
+ MemberCoreArrayList enums;
+
+ // Holds the list of delegates
+ MemberCoreArrayList delegates;
+
+ // Holds the list of constructors
+ protected MemberCoreArrayList instance_constructors;
+
+ // Holds the list of fields
+ MemberCoreArrayList fields;
+
+ // Holds a list of fields that have initializers
+ protected ArrayList initialized_fields;
+
+ // Holds a list of static fields that have initializers
+ protected ArrayList initialized_static_fields;
+
+ // Holds the list of constants
+ MemberCoreArrayList constants;
+
+ // Holds the list of
+ MemberCoreArrayList interfaces;
+
+ // Holds the methods.
+ MethodArrayList methods;
+
+ // Holds the events
+ protected MemberCoreArrayList events;
+
+ // Holds the indexers
+ IndexerArrayList indexers;
+
+ // Holds the operators
+ MemberCoreArrayList operators;
+
+ // Holds the iterators
+ ArrayList iterators;
+
+ // Holds the parts of a partial class;
+ ArrayList parts;
+
+ //
+ // Pointers to the default constructor and the default static constructor
+ //
+ protected Constructor default_constructor;
+ protected Constructor default_static_constructor;
+
+ //
+ // 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;
+ TypeExpr parent_type;
+
+ ArrayList type_bases;
+
+ bool members_defined;
+ bool members_defined_ok;
+
+ // The interfaces we implement.
+ protected Type[] ifaces;
+ protected Type ptype;
+
+ // The parent member cache and our member cache
+ MemberCache parent_cache;
+ MemberCache member_cache;
+
+ public const string DefaultIndexerName = "Item";
+
+ Type GenericType;
+
+ public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
+ Attributes attrs, Kind kind, Location l)
+ : base (ns, parent, name, attrs, l)
+ {
+ this.Kind = kind;
+
+ types = new ArrayList ();
+
+ base_class_name = null;
+ }
+
+ public bool AddToMemberContainer (MemberCore symbol, bool is_method)
+ {
+ return AddToContainer (symbol, is_method, String.Concat (Name, '.', symbol.Name), symbol.Name);
+ }
+
+ bool AddToTypeContainer (DeclSpace ds)
+ {
+ return AddToContainer (ds, false, ds.Name, ds.Basename);
+ }
+
+ public void AddConstant (Const constant)
+ {
+ if (!AddToMemberContainer (constant, false))
+ return;
+
+ if (constants == null)
+ constants = new MemberCoreArrayList ();
+
+ constants.Add (constant);
+ }
+
+ public void AddEnum (Mono.CSharp.Enum e)
+ {
+ if (!AddToTypeContainer (e))
+ return;
+
+ if (enums == null)
+ enums = new MemberCoreArrayList ();
+
+ enums.Add (e);
+ }
+
+ public void AddClassOrStruct (TypeContainer c)
+ {
+ if (!AddToTypeContainer (c))
+ return;
+
+ types.Add (c);
+ }
+
+ public void AddDelegate (Delegate d)
+ {
+ if (!AddToTypeContainer (d))
+ return;
+
+ if (delegates == null)
+ delegates = new MemberCoreArrayList ();
+
+ delegates.Add (d);
+ }
+
+ public void AddMethod (Method method)
+ {
+ if (!AddToMemberContainer (method, true))
+ return;
+
+ if (methods == null)
+ methods = new MethodArrayList (this);
+
+ if (method.Name.IndexOf ('.') != -1)
+ methods.Insert (0, method);
+ else
+ methods.Add (method);
+ }
+
+ public void AddConstructor (Constructor c)
+ {
+ if (c.Name != Basename) {
+ Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
+ }
+
+ bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
+
+ if (is_static){
+ if (default_static_constructor != null) {
+ Report.SymbolRelatedToPreviousError (default_static_constructor);
+ Report.Error (111, c.Location, "Type '{0}' already defines a member " +
+ "called '{1}' with the same parameter types", Name, c.Name);
+ return;
+ }
+
+ default_static_constructor = c;
+ } else {
+ if (c.IsDefault ()){
+ if (default_constructor != null) {
+ Report.SymbolRelatedToPreviousError (default_constructor);
+ Report.Error (111, c.Location, "Type '{0}' already defines a member " +
+ "called '{1}' with the same parameter types", Name, c.Name);
+ return;
+ }
+ default_constructor = c;
+ }
+
+ if (instance_constructors == null)
+ instance_constructors = new MemberCoreArrayList ();
+
+ instance_constructors.Add (c);
+ }
+ }
+
+ public void AddInterface (TypeContainer iface)
+ {
+ if (!AddToTypeContainer (iface))
+ return;
+
+ if (interfaces == null) {
+ interfaces = new MemberCoreArrayList ();
+ }
+
+ interfaces.Add (iface);
+ }
+
+ public void AddField (Field field)
+ {
+ if (!AddToMemberContainer (field, false))
+ return;
+
+ if (fields == null)
+ fields = new MemberCoreArrayList ();
+
+ 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);
+
+ } else {
+ if (initialized_fields == null)
+ initialized_fields = new ArrayList ();
+
+ initialized_fields.Add (field);
+ }
+ }
+
+ if ((field.ModFlags & Modifiers.STATIC) == 0)
+ have_nonstatic_fields = true;
+ }
+
+ public void AddProperty (Property prop)
+ {
+ if (!AddToMemberContainer (prop, false) ||
+ !AddToMemberContainer (prop.Get, true) || !AddToMemberContainer (prop.Set, true))
+ return;
+
+ if (properties == null)
+ properties = new MemberCoreArrayList ();
+
+ if (prop.Name.IndexOf ('.') != -1)
+ properties.Insert (0, prop);
+ else
+ properties.Add (prop);
+ }
+
+ public void AddEvent (Event e)
+ {
+ if (!AddToMemberContainer (e, false))
+ return;
+
+ if (e is EventProperty) {
+ if (!AddToMemberContainer (e.Add, true))
+ return;
+
+ if (!AddToMemberContainer (e.Remove, true))
+ return;
+ }
+
+ if (events == null)
+ events = new MemberCoreArrayList ();
+
+ events.Add (e);
+ }
+
+ /// <summary>
+ /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
+ /// </summary>
+ public void AddIndexer (Indexer i)
+ {
+ if (indexers == null)
+ indexers = new IndexerArrayList (this);
+
+ if (i.IsExplicitImpl)
+ indexers.Insert (0, i);
+ else
+ indexers.Add (i);
+ }
+
+ public void AddOperator (Operator op)
+ {
+ if (!AddToMemberContainer (op, true))
+ return;
+
+ if (operators == null)
+ operators = new OperatorArrayList (this);
+
+ operators.Add (op);
+ }
+
+ public void AddIterator (Iterator i)
+ {
+ if (iterators == null)
+ iterators = new ArrayList ();
+
+ iterators.Add (i);
+ }
+
+ public void AddType (TypeContainer tc)
+ {
+ types.Add (tc);
+ }
+
+ public void AddPart (ClassPart part)
+ {
+ if (parts == null)
+ parts = new ArrayList ();
+
+ parts.Add (part);
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.default_member_type) {
+ if (Indexers != null) {
+ Report.Error (646, a.Location,
+ "Cannot specify the DefaultMember attribute on" +
+ " a type containing an indexer");
+ return;
+ }
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ throw new NotSupportedException ();
+ }
+ }
+
+ public ArrayList Types {
+ get {
+ return types;
+ }
+ }
+
+ public MethodArrayList Methods {
+ get {
+ return methods;
+ }
+ }
+
+ public ArrayList Constants {
+ get {
+ return constants;
+ }
+ }
+
+ public ArrayList Interfaces {
+ get {
+ return interfaces;
+ }
+ }
+
+ public ArrayList Iterators {
+ get {
+ return iterators;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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 ArrayList Parts {
+ get {
+ return parts;
+ }
+ }
+
+ public virtual TypeAttributes TypeAttr {
+ get {
+ return Modifiers.TypeAttr (ModFlags, this);
+ }
+ }
+
+ public string IndexerName {
+ get {
+ return indexers == null ? DefaultIndexerName : indexers.IndexerName;
+ }
+ }
+
+ //
+ // Emits the instance field initializers
+ //
+ public bool EmitFieldInitializers (EmitContext ec)
+ {
+ ArrayList fields;
+ 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;
+ fe.IsFieldInitializer = true;
+
+ 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
+ //
+ protected void DefineDefaultConstructor (bool is_static)
+ {
+ Constructor c;
+
+ // The default constructor is public
+ // If the class is abstract, the default constructor is protected
+ // The default static constructor is private
+
+ int mods = Modifiers.PUBLIC;
+ if (is_static)
+ mods = Modifiers.STATIC | Modifiers.PRIVATE;
+ else if ((ModFlags & Modifiers.ABSTRACT) != 0)
+ mods = Modifiers.PROTECTED;
+
+ c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
+ new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters,
+ Location),
+ Location);
+
+ AddConstructor (c);
+
+ c.Block = new ToplevelBlock (null, Location);
+
+ }
+
+ /// <remarks>
+ /// The pending methods that need to be implemented
+ // (interfaces or abstract methods)
+ /// </remarks>
+ public PendingImplementation Pending;
+
+ public abstract void Register ();
+
+ public abstract PendingImplementation GetPendingImplementations ();
+
+ TypeExpr[] GetPartialBases (out TypeExpr parent, out bool error)
+ {
+ ArrayList ifaces = new ArrayList ();
+
+ parent = null;
+ Location parent_loc = Location.Null;
+
+ foreach (ClassPart part in parts) {
+ TypeExpr new_parent;
+ TypeExpr[] new_ifaces;
+
+ new_ifaces = part.GetClassBases (out new_parent, out error);
+ if (error)
+ return null;
+
+ if ((parent != null) && (new_parent != null) &&
+ !parent.Equals (new_parent)) {
+ Report.Error (263, part.Location,
+ "Partial declarations of `{0}' must " +
+ "not specify different base classes",
+ Name);
+
+ if (!Location.IsNull (parent_loc))
+ Report.LocationOfPreviousError (parent_loc);
+
+ error = true;
+ return null;
+ }
+
+ if ((parent == null) && (new_parent != null)) {
+ parent = new_parent;
+ parent_loc = part.Location;
+ }
+
+ if (new_ifaces == null)
+ continue;
+
+ foreach (TypeExpr iface in new_ifaces) {
+ bool found = false;
+ foreach (TypeExpr old_iface in ifaces) {
+ if (old_iface.Equals (iface)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ ifaces.Add (iface);
+ }
+ }
+
+ error = false;
+
+ TypeExpr[] retval = new TypeExpr [ifaces.Count];
+ ifaces.CopyTo (retval, 0);
+ return retval;
+ }
+
+ TypeExpr[] GetNormalBases (out TypeExpr parent, out bool error)
+ {
+ parent = null;
+
+ int count = Bases.Count;
+ int start, i, j;
+
+ if (Kind == Kind.Class){
+ TypeExpr name = ResolveTypeExpr ((Expression) Bases [0], Location);
+
+ if (name == null){
+ error = true;
+ return null;
+ }
+
+ if (name.IsClass){
+ parent = name;
+ start = 1;
+ } else {
+ start = 0;
+ }
+ } else {
+ start = 0;
+ }
+
+ TypeExpr [] ifaces = new TypeExpr [count-start];
+
+ for (i = start, j = 0; i < count; i++, j++){
+ Expression name = (Expression) Bases [i];
+ TypeExpr resolved = ResolveTypeExpr (name, Location);
+ if (resolved == null) {
+ error = true;
+ return null;
+ }
+
+ ifaces [j] = resolved;
+ }
+
+ error = false;
+ return ifaces;
+ }
+
+ /// <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>
+ TypeExpr [] GetClassBases (out TypeExpr parent, out bool error)
+ {
+ int i;
+
+ error = false;
+
+ TypeExpr[] ifaces;
+
+ if (parts != null)
+ ifaces = GetPartialBases (out parent, out error);
+ else if (Bases == null){
+ parent = null;
+ return null;
+ } else
+ ifaces = GetNormalBases (out parent, out error);
+
+ if (error)
+ return null;
+
+ if ((parent != null) && (Kind == Kind.Class)){
+ if (parent is TypeParameterExpr){
+ Report.Error (
+ 689, parent.Location,
+ "Type parameter `{0}' can not be used as a " +
+ "base class or interface", parent.Name);
+ error = true;
+ return null;
+ }
+
+ if (IsGeneric && parent.IsAttribute){
+ Report.Error (
+ 698, parent.Location,
+ "A generic type cannot derive from `{0}' " +
+ "because it is an attribute class",
+ parent.Name);
+ error = true;
+ return null;
+ }
+
+ if (parent.IsSealed){
+ error = true;
+ Report.SymbolRelatedToPreviousError (parent.Type);
+ if (parent.Type.IsAbstract) {
+ Report.Error (709, Location, "'{0}': Cannot derive from static class", GetSignatureForError ());
+ } else {
+ Report.Error (509, Location, "'{0}': Cannot derive from sealed class", GetSignatureForError ());
+ }
+ return null;
+ }
+
+ if (!parent.CanInheritFrom ()){
+ Report.Error (644, Location,
+ "`{0}' cannot inherit from special class `{1}'",
+ Name, parent_type.Name);
+ error = true;
+ return null;
+ }
+
+ if (!parent.AsAccessible (this, ModFlags)) {
+ Report.SymbolRelatedToPreviousError (parent.Type);
+ Report.Error (60, Location, "Inconsistent accessibility: base class '{0}' is less accessible than class '{1}'",
+ TypeManager.CSharpName (parent.Type), GetSignatureForError ());
+ }
+ }
+
+ if (parent != null)
+ base_class_name = parent.Name;
+
+ if (ifaces == null)
+ return null;
+
+ int count = ifaces != null ? ifaces.Length : 0;
+
+ for (i = 0; i < count; i++) {
+ TypeExpr iface = (TypeExpr) ifaces [i];
+
+ if ((Kind != Kind.Class) && !iface.IsInterface){
+ string what = Kind == Kind.Struct ?
+ "Struct" : "Interface";
+
+ Report.Error (527, Location,
+ "In {0} `{1}', type `{2}' is not "+
+ "an interface", what, Name, iface.Name);
+ error = true;
+ return null;
+ }
+
+ if (iface.IsClass) {
+ if (parent != null)
+ Report.Error (1721, Location,
+ "In Class `{0}', `{1}' is not an interface, and a base class has already been defined",
+ Name, iface.Name);
+ else {
+ Report.Error (1722, Location,
+ "In Class `{0}', `{1}' is not " +
+ "an interface, a base class must be listed first", Name, iface.Name);
+ }
+ error = true;
+ return null;
+ }
+
+ for (int x = 0; x < i; x++) {
+ if (iface.Equals (ifaces [x])) {
+ Report.Error (528, Location,
+ "`{0}' is already listed in " +
+ "interface list", iface.Name);
+ error = true;
+ return null;
+ }
+ }
+
+ if ((Kind == Kind.Interface) &&
+ !iface.AsAccessible (Parent, ModFlags))
+ Report.Error (61, Location,
+ "Inconsistent accessibility: base " +
+ "interface `{0}' is less accessible " +
+ "than interface `{1}'", iface.Name,
+ Name);
+ }
+
+ return ifaces;
+ }
+
+ bool CheckGenericInterfaces (Type[] ifaces)
+ {
+ ArrayList already_checked = new ArrayList ();
+
+ for (int i = 0; i < ifaces.Length; i++) {
+ Type iface = ifaces [i];
+ foreach (Type t in already_checked) {
+ if (iface == t)
+ continue;
+
+ Type[] infered = new Type [CountTypeParameters];
+ if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, infered, null))
+ continue;
+
+ Report.Error (
+ 695, Location,
+ "`{0}' cannot implement both `{1}' and `{2}' " +
+ "because they may unify for some type " +
+ "parameter substitutions",
+ TypeManager.GetFullName (TypeBuilder),
+ iface, t);
+ return false;
+ }
+
+ already_checked.Add (iface);
+ }
+
+ return true;
+ }
+
+ bool error = false;
+
+ //
+ // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
+ //
+ public override TypeBuilder DefineType ()
+ {
+ TypeExpr parent;
+
+ if (error)
+ return null;
+
+ if (TypeBuilder != null)
+ return TypeBuilder;
+
+ ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+
+ TypeAttributes type_attributes = TypeAttr;
+
+ try {
+ if (IsTopLevel){
+ if (TypeManager.NamespaceClash (Name, Location)) {
+ error = true;
+ return null;
+ }
+
+ ModuleBuilder builder = CodeGen.Module.Builder;
+ TypeBuilder = builder.DefineType (
+ Name, type_attributes, null, null);
+ } else {
+ TypeBuilder builder;
+ if (Parent.TypeBuilder != null)
+ builder = Parent.TypeBuilder;
+ else
+ builder = Parent.DefineType ();
+
+ if (builder == null) {
+ error = true;
+ return null;
+ }
+
+ TypeBuilder = builder.DefineNestedType (
+ MemberName.Basename, type_attributes,
+ null, null);
+ }
+ }
+ catch (ArgumentException) {
+ Report.RuntimeMissingSupport (Location, "static classes");
+ return null;
+ }
+
+ TypeManager.AddUserType (Name, TypeBuilder, this);
+
+ TypeExpr current_type = null;
+
+ if (IsGeneric) {
+ string[] param_names = new string [TypeParameters.Length];
+ for (int i = 0; i < TypeParameters.Length; i++)
+ param_names [i] = TypeParameters [i].Name;
+
+ GenericTypeParameterBuilder[] gen_params;
+ gen_params = TypeBuilder.DefineGenericParameters (param_names);
+
+ int offset = CountTypeParameters - CurrentTypeParameters.Length;
+ for (int i = offset; i < gen_params.Length; i++)
+ CurrentTypeParameters [i - offset].Define (gen_params [i]);
+
+ foreach (TypeParameter type_param in CurrentTypeParameters) {
+ if (!type_param.Resolve (this)) {
+ error = true;
+ return null;
+ }
+ }
+
+ for (int i = offset; i < gen_params.Length; i++)
+ CurrentTypeParameters [i - offset].DefineConstraints ();
+
+ current_type = new ConstructedType (Name, TypeParameters, Location);
+ }
+
+ if (IsGeneric) {
+ foreach (TypeParameter type_param in TypeParameters)
+ if (!type_param.DefineType (ec)) {
+ error = true;
+ return null;
+ }
+ }
+
+ if ((Kind == Kind.Struct) && TypeManager.value_type == null)
+ throw new Exception ();
+
+ TypeExpr[] iface_exprs = GetClassBases (out parent_type, out error);
+ if (error)
+ return null;
+
+ if (parent_type == null) {
+ if (Kind == Kind.Class){
+ if (RootContext.StdLib)
+ parent_type = TypeManager.system_object_expr;
+ else if (Name != "System.Object")
+ parent_type = TypeManager.system_object_expr;
+ } else if (Kind == Kind.Struct){
+ //
+ // If we are compiling our runtime,
+ // and we are defining ValueType, then our
+ // parent is `System.Object'.
+ //
+ if (!RootContext.StdLib && Name == "System.ValueType")
+ parent_type = TypeManager.system_object_expr;
+ else if (Kind == Kind.Struct)
+ parent_type = TypeManager.system_valuetype_expr;
+ }
+ }
+
+ if (parent_type != null) {
+ parent_type = parent_type.ResolveAsTypeTerminal (ec);
+ if (parent_type == null) {
+ error = true;
+ return null;
+ }
+
+ ptype = parent_type.Type;
+ }
+
+ if (!CheckRecursiveDefinition ()) {
+ error = true;
+ return null;
+ }
+
+ if (ptype != null)
+ TypeBuilder.SetParent (ptype);
+
+ //
+ // 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 ((Kind == Kind.Struct) && !have_nonstatic_fields){
+ TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
+ FieldAttributes.Private);
+ }
+
+ // add interfaces that were not added at type creation
+ if (iface_exprs != null) {
+ ifaces = TypeManager.ExpandInterfaces (ec, iface_exprs);
+ if (ifaces == null) {
+ error = true;
+ return null;
+ }
+
+ foreach (Type itype in ifaces)
+ TypeBuilder.AddInterfaceImplementation (itype);
+
+ if (!CheckGenericInterfaces (ifaces)) {
+ error = true;
+ return null;
+ }
+
+ TypeManager.RegisterBuilder (TypeBuilder, ifaces);
+ }
+
+ if (IsGeneric) {
+ foreach (TypeParameter type_param in TypeParameters)
+ if (!type_param.CheckDependencies (ec)) {
+ error = true;
+ return null;
+ }
+ }
+
+ if (current_type != null) {
+ current_type = current_type.ResolveAsTypeTerminal (ec);
+ if (current_type == null) {
+ error = true;
+ return null;
+ }
+
+ CurrentType = current_type.Type;
+ }
+
+ //
+ // Finish the setup for the EmitContext
+ //
+ ec.ContainerType = TypeBuilder;
+
+ if ((parent_type != null) && parent_type.IsAttribute) {
+ RootContext.RegisterAttribute (this);
+ } else if (!(this is Iterator))
+ RootContext.RegisterOrder (this);
+
+ if (!DefineNestedTypes ()) {
+ error = true;
+ return null;
+ }
+
+ return TypeBuilder;
+ }
+
+ protected virtual bool DefineNestedTypes ()
+ {
+ if (Interfaces != null) {
+ foreach (TypeContainer iface in Interfaces)
+ if (iface.DefineType () == null)
+ return false;
+ }
+
+ if (Types != null) {
+ foreach (TypeContainer tc in Types)
+ if (tc.DefineType () == null)
+ return false;
+ }
+
+ if (Delegates != null) {
+ foreach (Delegate d in Delegates)
+ if (d.DefineType () == null)
+ return false;
+ }
+
+ if (Enums != null) {
+ foreach (Enum en in Enums)
+ if (en.DefineType () == null)
+ return false;
+ }
+
+ if (Parts != null) {
+ foreach (ClassPart part in Parts) {
+ part.TypeBuilder = TypeBuilder;
+ part.parent_type = parent_type;
+ part.ec = new EmitContext (part, Mono.CSharp.Location.Null, null, null, ModFlags);
+ }
+ }
+
+ return true;
+ }
+
+ protected bool CheckRecursiveDefinition ()
+ {
+ if (InTransit) {
+ Report.Error (146, Location,
+ "Class definition is circular: `{0}'",
+ GetSignatureForError ());
+ error = true;
+ return false;
+ }
+
+ InTransit = true;
+
+ Type parent = ptype;
+ if (parent != null) {
+ if (parent.IsGenericInstance)
+ parent = parent.GetGenericTypeDefinition ();
+
+ TypeContainer ptc = TypeManager.LookupTypeContainer (parent);
+ if ((ptc != null) && !ptc.CheckRecursiveDefinition ())
+ return false;
+ }
+
+ InTransit = false;
+ return true;
+ }
+
+ 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)
+ {
+ if (members_defined)
+ return members_defined_ok;
+
+ members_defined_ok = DoDefineMembers ();
+ members_defined = true;
+
+ return members_defined_ok;
+ }
+
+ protected virtual bool DoDefineMembers ()
+ {
+ //
+ // We need to be able to use the member cache while we are checking/defining
+ //
+ if (TypeBuilder.BaseType != null)
+ parent_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
+
+ if (TypeBuilder.IsInterface)
+ parent_cache = TypeManager.LookupParentInterfacesCache (TypeBuilder);
+
+ if (IsTopLevel) {
+ if ((ModFlags & Modifiers.NEW) != 0)
+ Error_KeywordNotAllowed (Location);
+ } else {
+ // HACK: missing implemenation
+ // This is not fully functional. Better way how to handle this is to have recursive definition of containers
+ // instead of flat as we have now.
+ // Now we are not able to check inner attribute class because its parent had not been defined.
+
+ // TODO: remove this if
+ if (Parent.MemberCache != null) {
+ MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
+ if (conflict_symbol == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
+ } else {
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError ());
+ }
+ }
+ }
+ }
+
+ DefineContainerMembers (constants);
+ DefineContainerMembers (fields);
+
+ if ((Kind == Kind.Class) && !(this is ClassPart) && !(this is StaticClass)){
+ if ((instance_constructors == null) &&
+ !(this is StaticClass)) {
+ if (default_constructor == null)
+ DefineDefaultConstructor (false);
+ }
+
+ if (initialized_static_fields != null &&
+ default_static_constructor == null)
+ DefineDefaultConstructor (true);
+ }
+
+ if (Kind == Kind.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 = GetPendingImplementations ();
+
+ if (parts != null) {
+ foreach (ClassPart part in parts) {
+ if (!part.DefineMembers (this))
+ return false;
+ }
+ }
+
+ //
+ // Constructors are not in the defined_names array
+ //
+ DefineContainerMembers (instance_constructors);
+
+ if (default_static_constructor != null)
+ default_static_constructor.Define ();
+
+ DefineContainerMembers (properties);
+ DefineContainerMembers (events);
+ DefineContainerMembers (indexers);
+ DefineContainerMembers (methods);
+ DefineContainerMembers (operators);
+ DefineContainerMembers (enums);
+ DefineContainerMembers (delegates);
+
+ if (CurrentType != null) {
+ GenericType = CurrentType;
+
+ ec.ContainerType = GenericType;
+ }
+
+
+#if CACHE
+ if (!(this is ClassPart))
+ member_cache = new MemberCache (this);
+#endif
+
+ if (parts != null) {
+ foreach (ClassPart part in parts)
+ part.member_cache = member_cache;
+ }
+
+ if (iterators != null) {
+ foreach (Iterator iterator in iterators) {
+ if (iterator.DefineType () == null)
+ return false;
+ }
+
+ foreach (Iterator iterator in iterators) {
+ if (!iterator.DefineMembers (this))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ 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");
+ }
+ }
+
+ protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
+ {
+ if (mcal != null)
+ mcal.DefineContainerMembers ();
+ }
+
+ public override bool Define ()
+ {
+ if (parts != null) {
+ foreach (ClassPart part in parts) {
+ if (!part.Define ())
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public MemberInfo FindMemberWithSameName (string name, bool ignore_methods)
+ {
+ return ParentCache.FindMemberWithSameName (name, ignore_methods, null);
+ }
+
+ /// <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;
+
+
+ static TypeContainer ()
+ {
+ accepting_filter = new MemberFilter (AlwaysAccept);
+ }
+
+ public MethodInfo[] GetMethods ()
+ {
+ ArrayList members = new ArrayList ();
+
+ DefineMembers (null);
+
+ if (methods != null) {
+ int len = methods.Count;
+ for (int i = 0; i < len; i++) {
+ Method m = (Method) methods [i];
+
+ members.Add (m.MethodBuilder);
+ }
+ }
+
+ if (operators != null) {
+ int len = operators.Count;
+ for (int i = 0; i < len; i++) {
+ Operator o = (Operator) operators [i];
+
+ members.Add (o.OperatorMethodBuilder);
+ }
+ }
+
+ if (properties != null) {
+ int len = properties.Count;
+ for (int i = 0; i < len; i++) {
+ Property p = (Property) properties [i];
+
+ if (p.GetBuilder != null)
+ members.Add (p.GetBuilder);
+ if (p.SetBuilder != null)
+ members.Add (p.SetBuilder);
+ }
+ }
+
+ if (indexers != null) {
+ int len = indexers.Count;
+ for (int i = 0; i < len; i++) {
+ Indexer ix = (Indexer) indexers [i];
+
+ if (ix.GetBuilder != null)
+ members.Add (ix.GetBuilder);
+ if (ix.SetBuilder != null)
+ members.Add (ix.SetBuilder);
+ }
+ }
+
+ if (events != null) {
+ int len = events.Count;
+ for (int i = 0; i < len; i++) {
+ Event e = (Event) events [i];
+
+ if (e.AddBuilder != null)
+ members.Add (e.AddBuilder);
+ if (e.RemoveBuilder != null)
+ members.Add (e.RemoveBuilder);
+ }
+ }
+
+ MethodInfo[] retMethods = new MethodInfo [members.Count];
+ members.CopyTo (retMethods, 0);
+ return retMethods;
+ }
+
+ // Indicated whether container has StructLayout attribute set Explicit
+ public virtual bool HasExplicitLayout {
+ get {
+ return false;
+ }
+ }
+
+ /// <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 = null;
+
+ 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) {
+ int len = fields.Count;
+ for (int i = 0; i < len; i++) {
+ Field f = (Field) fields [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (fb);
+ }
+ }
+ }
+
+ if (constants != null) {
+ int len = constants.Count;
+ for (int i = 0; i < len; i++) {
+ Const con = (Const) constants [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (fb);
+ }
+ }
+ }
+ }
+
+ if ((mt & MemberTypes.Method) != 0) {
+ if (methods != null) {
+ int len = methods.Count;
+ for (int i = 0; i < len; i++) {
+ Method m = (Method) methods [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (mb);
+ }
+ }
+ }
+
+ if (operators != null) {
+ int len = operators.Count;
+ for (int i = 0; i < len; i++) {
+ Operator o = (Operator) operators [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (ob);
+ }
+ }
+ }
+
+ if (properties != null) {
+ int len = properties.Count;
+ for (int i = 0; i < len; i++) {
+ Property p = (Property) properties [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (b);
+ }
+
+ b = p.SetBuilder;
+ if (b != null && filter (b, criteria) == true) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (b);
+ }
+ }
+ }
+
+ if (indexers != null) {
+ int len = indexers.Count;
+ for (int i = 0; i < len; i++) {
+ Indexer ix = (Indexer) indexers [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (b);
+ }
+
+ b = ix.SetBuilder;
+ if (b != null && filter (b, criteria) == true) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (b);
+ }
+ }
+ }
+ }
+
+ if ((mt & MemberTypes.Event) != 0) {
+ if (events != null) {
+ int len = events.Count;
+ for (int i = 0; i < len; i++) {
+ Event e = (Event) events [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (e.EventBuilder);
+ }
+ }
+ }
+ }
+
+ if ((mt & MemberTypes.Property) != 0){
+ if (properties != null) {
+ int len = properties.Count;
+ for (int i = 0; i < len; i++) {
+ Property p = (Property) properties [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (p.PropertyBuilder);
+ }
+ }
+ }
+
+ if (indexers != null) {
+ int len = indexers.Count;
+ for (int i = 0; i < len; i++) {
+ Indexer ix = (Indexer) indexers [i];
+
+ 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) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (ix.PropertyBuilder);
+ }
+ }
+ }
+ }
+
+ if ((mt & MemberTypes.NestedType) != 0) {
+ if (types != null) {
+ int len = types.Count;
+ for (int i = 0; i < len; i++) {
+ TypeContainer t = (TypeContainer) types [i];
+
+ if ((t.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = t.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true)) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (tb);
+ }
+ }
+ }
+
+ if (enums != null) {
+ int len = enums.Count;
+ for (int i = 0; i < len; i++) {
+ Enum en = (Enum) enums [i];
+
+ if ((en.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = en.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true)) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (tb);
+ }
+ }
+ }
+
+ if (delegates != null) {
+ int len = delegates.Count;
+ for (int i = 0; i < len; i++) {
+ Delegate d = (Delegate) delegates [i];
+
+ if ((d.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = d.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true)) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (tb);
+ }
+ }
+ }
+
+ if (interfaces != null) {
+ int len = interfaces.Count;
+ for (int i = 0; i < len; i++) {
+ TypeContainer iface = (TypeContainer) interfaces [i];
+
+ if ((iface.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = iface.TypeBuilder;
+ if (tb != null && (filter (tb, criteria) == true)) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (tb);
+ }
+ }
+ }
+ }
+
+ if ((mt & MemberTypes.Constructor) != 0){
+ if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
+ int len = instance_constructors.Count;
+ for (int i = 0; i < len; i++) {
+ Constructor c = (Constructor) instance_constructors [i];
+
+ ConstructorBuilder cb = c.ConstructorBuilder;
+ if (cb != null && filter (cb, criteria) == true) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (cb);
+ }
+ }
+ }
+
+ if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
+ ConstructorBuilder cb =
+ default_static_constructor.ConstructorBuilder;
+
+ if (cb != null && filter (cb, criteria) == true) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.Add (cb);
+ }
+ }
+ }
+
+ //
+ // Lookup members in parent if requested.
+ //
+ if ((bf & BindingFlags.DeclaredOnly) == 0) {
+ if (TypeBuilder.BaseType != null) {
+ MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
+ if (list.Count > 0) {
+ if (members == null)
+ members = new ArrayList ();
+
+ members.AddRange (list);
+ }
+ }
+
+ }
+
+ Timer.StopTimer (TimerType.TcFindMembers);
+
+ if (members == null)
+ return MemberList.Empty;
+ else
+ 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.Emit ();
+ return;
+ }
+
+ protected virtual void VerifyMembers (EmitContext ec)
+ {
+ //
+ // 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.Accessibility) != Modifiers.PRIVATE)
+ continue;
+
+ if ((f.status & Field.Status.USED) == 0){
+ Report.Warning (169, f.Location, "The private field '{0}' is never used", f.GetSignatureForError ());
+ 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 '{0}' is never assigned to, and will always have its default value '{1}'", f.GetSignatureForError (), "");
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Emits the code, this step is performed after all
+ /// the types, enumerations, constructors
+ /// </summary>
+ public void EmitType ()
+ {
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ Emit ();
+
+ if (instance_constructors != null) {
+ if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsCompliaceRequired (this)) {
+ bool has_compliant_args = false;
+
+ foreach (Constructor c in instance_constructors) {
+ c.Emit ();
+
+ if (has_compliant_args)
+ continue;
+
+ has_compliant_args = c.HasCompliantArgs;
+ }
+ if (!has_compliant_args)
+ Report.Error (3015, Location, "'{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
+ } else {
+ foreach (Constructor c in instance_constructors)
+ c.Emit ();
+ }
+ }
+
+ EmitConstants ();
+
+ if (default_static_constructor != null)
+ default_static_constructor.Emit ();
+
+ if (methods != null)
+ foreach (Method m in methods)
+ m.Emit ();
+
+ if (operators != null)
+ foreach (Operator o in operators)
+ o.Emit ();
+
+ if (properties != null)
+ foreach (Property p in properties)
+ p.Emit ();
+
+ if (indexers != null){
+ indexers.Emit ();
+ }
+
+ if (fields != null)
+ foreach (Field f in fields)
+ f.Emit ();
+
+ if (events != null){
+ foreach (Event e in Events)
+ e.Emit ();
+ }
+
+ if (delegates != null) {
+ foreach (Delegate d in Delegates) {
+ d.Emit ();
+ }
+ }
+
+ if (enums != null) {
+ foreach (Enum e in enums) {
+ e.Emit ();
+ }
+ }
+
+ if (parts != null) {
+ foreach (ClassPart part in parts)
+ part.EmitType ();
+ }
+
+ if ((Pending != null) && !(this is ClassPart))
+ if (Pending.VerifyPendingMethods ())
+ return;
+
+ VerifyMembers (ec);
+
+ if (iterators != null)
+ foreach (Iterator iterator in iterators)
+ iterator.EmitType ();
+
+// if (types != null)
+// foreach (TypeContainer tc in types)
+// tc.Emit ();
+ }
+
+ public override void CloseType ()
+ {
+ if ((caching_flags & Flags.CloseTypeCreated) != 0)
+ return;
+
+ try {
+ caching_flags |= Flags.CloseTypeCreated;
+ 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 (Types != null){
+ foreach (TypeContainer tc in Types)
+ if (tc.Kind == Kind.Struct)
+ tc.CloseType ();
+
+ foreach (TypeContainer tc in Types)
+ if (tc.Kind != Kind.Struct)
+ tc.CloseType ();
+ }
+
+ if (Delegates != null)
+ foreach (Delegate d in Delegates)
+ d.CloseType ();
+
+ if (Iterators != null)
+ foreach (Iterator i in Iterators)
+ i.CloseType ();
+
+ types = null;
+ properties = null;
+ enums = null;
+ delegates = null;
+ fields = null;
+ initialized_fields = null;
+ initialized_static_fields = null;
+ constants = null;
+ interfaces = null;
+ methods = null;
+ events = null;
+ indexers = null;
+ operators = null;
+ iterators = null;
+ ec = null;
+ default_constructor = null;
+ default_static_constructor = null;
+ type_bases = null;
+ OptAttributes = null;
+ ifaces = null;
+ parent_cache = null;
+ member_cache = null;
+ }
+
+ // TODO: make it obsolete and use GetSignatureForError
+ public string MakeName (string n)
+ {
+ return "`" + Name + "." + n + "'";
+ }
+
+ //
+ // 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 (Kind == Kind.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;
+ }
+
+ public bool UserDefinedStaticConstructor {
+ get {
+ return default_static_constructor != null;
+ }
+ }
+
+ public Constructor DefaultStaticConstructor {
+ get { return default_static_constructor; }
+ }
+
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds))
+ return false;
+
+ VerifyClsName ();
+
+ if (IsGeneric) {
+ Report.Error (3024, Location, "'{0}': type parameters are not CLS-compliant",
+ GetSignatureForError ());
+ return false;
+ }
+
+ Type base_type = TypeBuilder.BaseType;
+ if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
+ Report.Error (3009, Location, "'{0}': base type '{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
+ }
+ return true;
+ }
+
+
+ /// <summary>
+ /// Checks whether container name is CLS Compliant
+ /// </summary>
+ void VerifyClsName ()
+ {
+ Hashtable parent_members = parent_cache == null ?
+ new Hashtable () :
+ parent_cache.GetPublicMembers ();
+ Hashtable this_members = new Hashtable ();
+
+ foreach (DictionaryEntry entry in defined_names) {
+ MemberCore mc = (MemberCore)entry.Value;
+ if (!mc.IsClsCompliaceRequired (this))
+ continue;
+
+ string name = (string)entry.Key;
+ string basename = name.Substring (name.LastIndexOf ('.') + 1);
+
+ string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+ object found = parent_members [lcase];
+ if (found == null) {
+ found = this_members [lcase];
+ if (found == null) {
+ this_members.Add (lcase, mc);
+ continue;
+ }
+ }
+
+ if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
+ continue;
+
+ if (found is MemberInfo) {
+ if (basename == ((MemberInfo)found).Name)
+ continue;
+ Report.SymbolRelatedToPreviousError ((MemberInfo)found);
+ } else {
+ Report.SymbolRelatedToPreviousError ((MemberCore) found);
+ }
+ Report.Error (3005, mc.Location, "Identifier '{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
+ }
+ }
+
+
+ /// <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 virtual 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;
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ CheckUsageOfObsoleteAttribute (TypeBuilder.BaseType);
+
+ if (ifaces == null)
+ return;
+
+ foreach (Type iface in ifaces) {
+ CheckUsageOfObsoleteAttribute (iface);
+ }
+ }
+
+ //
+ // IMemberContainer
+ //
+
+ string IMemberContainer.Name {
+ get {
+ return Name;
+ }
+ }
+
+ Type IMemberContainer.Type {
+ get {
+ return TypeBuilder;
+ }
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get {
+ return member_cache;
+ }
+ }
+
+ bool IMemberContainer.IsInterface {
+ get {
+ return Kind == Kind.Interface;
+ }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
+
+ if (GenericType != null)
+ return TypeManager.FindMembers (GenericType, mt, new_bf,
+ null, null);
+ else
+ return FindMembers (mt, new_bf, null, null);
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal override void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateTypeDocComment (this, ds);
+ }
+
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
+
+ public virtual MemberCache ParentCache {
+ get {
+ return parent_cache;
+ }
+ }
+
+ }
+
+ public class PartialContainer : TypeContainer {
+
+ public readonly Namespace Namespace;
+ public readonly int OriginalModFlags;
+ public readonly int AllowedModifiers;
+ public readonly TypeAttributes DefaultTypeAttributes;
+
+ static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
+ MemberName member_name, int mod_flags, Kind kind,
+ Location loc)
+ {
+ PartialContainer pc;
+ string full_name = member_name.GetName (true);
+ DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
+ if (ds != null) {
+ pc = ds as PartialContainer;
+
+ if (pc == null) {
+ Report.Error (
+ 260, ds.Location, "Missing partial modifier " +
+ "on declaration of type `{0}'; another " +
+ "partial implementation of this type exists",
+ member_name.GetTypeName());
+
+ Report.LocationOfPreviousError (loc);
+ return null;
+ }
+
+ if (pc.Kind != kind) {
+ Report.Error (
+ 261, loc, "Partial declarations of `{0}' " +
+ "must be all classes, all structs or " +
+ "all interfaces", member_name.GetTypeName ());
+ return null;
+ }
+
+ if (pc.OriginalModFlags != mod_flags) {
+ Report.Error (
+ 262, loc, "Partial declarations of `{0}' " +
+ "have conflicting accessibility modifiers",
+ member_name.GetTypeName ());
+ return null;
+ }
+
+ return pc;
+ }
+
+ pc = new PartialContainer (ns, parent, member_name, mod_flags, kind, loc);
+ RootContext.Tree.RecordDecl (full_name, pc);
+ parent.AddType (pc);
+ pc.Register ();
+ return pc;
+ }
+
+ public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
+ MemberName name, int mod, Attributes attrs,
+ Kind kind, Location loc)
+ {
+ PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
+ if (pc == null) {
+ // An error occured; create a dummy container, but don't
+ // register it.
+ pc = new PartialContainer (ns, parent, name, mod, kind, loc);
+ }
+
+ ClassPart part = new ClassPart (ns, pc, mod, attrs, kind, loc);
+ pc.AddPart (part);
+ return part;
+ }
+
+ protected PartialContainer (NamespaceEntry ns, TypeContainer parent,
+ MemberName name, int mod, Kind kind, Location l)
+ : base (ns, parent, name, null, kind, l)
+ {
+ this.Namespace = ns.NS;
+
+ switch (kind) {
+ case Kind.Class:
+ AllowedModifiers = Class.AllowedModifiers;
+ DefaultTypeAttributes = Class.DefaultTypeAttributes;
+ break;
+
+ case Kind.Struct:
+ AllowedModifiers = Struct.AllowedModifiers;
+ DefaultTypeAttributes = Struct.DefaultTypeAttributes;
+ break;
+
+ case Kind.Interface:
+ AllowedModifiers = Interface.AllowedModifiers;
+ DefaultTypeAttributes = Interface.DefaultTypeAttributes;
+ break;
+
+ default:
+ throw new InvalidOperationException ();
+ }
+
+ int accmods;
+ if (parent.Parent == null)
+ accmods = Modifiers.INTERNAL;
+ else
+ accmods = Modifiers.PRIVATE;
+
+ this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
+ this.OriginalModFlags = mod;
+ }
+
+ public override void Register ()
+ {
+ if (Kind == Kind.Interface)
+ Parent.AddInterface (this);
+ else if (Kind == Kind.Class || Kind == Kind.Struct)
+ Parent.AddClassOrStruct (this);
+ else
+ throw new InvalidOperationException ();
+ }
+
+ public override PendingImplementation GetPendingImplementations ()
+ {
+ return PendingImplementation.GetPendingImplementations (this);
+ }
+
+ public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
+ Location l)
+ {
+ ClassPart part = new ClassPart (ns, this, mod, attrs, Kind, l);
+ AddPart (part);
+ return part;
+ }
+
+ public override TypeAttributes TypeAttr {
+ get {
+ return base.TypeAttr | DefaultTypeAttributes;
+ }
+ }
+ }
+
+ public class ClassPart : TypeContainer, IMemberContainer {
+ public readonly PartialContainer PartialContainer;
+ public readonly bool IsPartial;
+
+ public ClassPart (NamespaceEntry ns, PartialContainer parent,
+ int mod, Attributes attrs, Kind kind, Location l)
+ : base (ns, parent.Parent, parent.MemberName, attrs, kind, l)
+ {
+ this.PartialContainer = parent;
+ this.IsPartial = true;
+
+ int accmods;
+ if (parent.Parent == null)
+ accmods = Modifiers.INTERNAL;
+ else
+ accmods = Modifiers.PRIVATE;
+
+ this.ModFlags = Modifiers.Check (
+ parent.AllowedModifiers, mod, accmods, l);
+ }
+
+ public override void Register ()
+ {
+ }
+
+ public override PendingImplementation GetPendingImplementations ()
+ {
+ return PartialContainer.Pending;
+ }
+
+ public override bool VerifyImplements (Type interface_type, string full,
+ string name, Location loc)
+ {
+ return PartialContainer.VerifyImplements (
+ interface_type, full, name, loc);
+ }
+
+ public override MemberCache ParentCache {
+ get {
+ return PartialContainer.ParentCache;
+ }
+ }
+ }
+
+ public abstract class ClassOrStruct : TypeContainer {
+ bool hasExplicitLayout = false;
+ ListDictionary declarative_security;
+
+ public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
+ MemberName name, Attributes attrs, Kind kind,
+ Location l)
+ : base (ns, parent, name, attrs, kind, l)
+ {
+ }
+
+ public override PendingImplementation GetPendingImplementations ()
+ {
+ return PendingImplementation.GetPendingImplementations (this);
+ }
+
+ public override bool HasExplicitLayout {
+ get {
+ return hasExplicitLayout;
+ }
+ }
+
+ protected override void VerifyMembers (EmitContext ec)
+ {
+ base.VerifyMembers (ec);
+
+ if ((events != null) && (RootContext.WarningLevel >= 3)) {
+ foreach (Event e in events){
+ if (e.status == 0)
+ Report.Warning (67, e.Location, "The event '{0}' is never used", e.GetSignatureForError ());
+ }
+ }
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
+ if (declarative_security == null)
+ declarative_security = new ListDictionary ();
+
+ a.ExtractSecurityPermissionSet (declarative_security);
+ return;
+ }
+
+ if (a.Type == TypeManager.struct_layout_attribute_type
+ && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
+ hasExplicitLayout = true;
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override void Emit()
+ {
+ base.Emit ();
+
+ if (declarative_security != null) {
+ foreach (DictionaryEntry de in declarative_security) {
+ TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
+ }
+ }
+ }
+
+ public override void Register ()
+ {
+ Parent.AddClassOrStruct (this);
+ }
+ }
+
+ /// <summary>
+ /// Class handles static classes declaration
+ /// </summary>
+ public sealed class StaticClass: Class {
+ public StaticClass (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
+ Attributes attrs, Location l)
+ : base (ns, parent, name, mod & ~Modifiers.STATIC, attrs, l)
+ {
+ if (RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (l, "static classes");
+ Environment.Exit (1);
+ }
+ }
+
+ protected override void DefineContainerMembers (MemberCoreArrayList list)
+ {
+ if (list == null)
+ return;
+
+ foreach (MemberCore m in list) {
+ if (m is Operator) {
+ Report.Error (715, m.Location, "'{0}': static classes cannot contain user-defined operators", m.GetSignatureForError (this));
+ continue;
+ }
+
+ if ((m.ModFlags & Modifiers.STATIC) != 0)
+ continue;
+
+ if (m is Constructor) {
+ Report.Error (710, m.Location, "'{0}': Static classes cannot have instance constructors", GetSignatureForError ());
+ continue;
+ }
+
+ if (m is Destructor) {
+ Report.Error (711, m.Location, "'{0}': Static class cannot contain destructor", GetSignatureForError ());
+ continue;
+ }
+ Report.Error (708, m.Location, "'{0}': cannot declare instance members in a static class", m.GetSignatureForError (this));
+ }
+
+ base.DefineContainerMembers (list);
+ }
+
+ public override TypeBuilder DefineType()
+ {
+ TypeBuilder tb = base.DefineType ();
+ if (tb == null)
+ return null;
+
+ if ((ptype != null) && (ptype != TypeManager.object_type)) {
+ Report.Error (
+ 713, Location,
+ "Static class '{0}' cannot derive from type '{1}'. " +
+ "Static classes must derive from object",
+ GetSignatureForError (), ptype);
+ return null;
+ }
+
+ if (ifaces != null) {
+ foreach (Type t in ifaces)
+ Report.SymbolRelatedToPreviousError (t);
+ Report.Error (
+ 714, Location,
+ "'{0}': static classes cannot implement interfaces",
+ GetSignatureForError ());
+ }
+ return tb;
+ }
+
+ public override TypeAttributes TypeAttr {
+ get {
+ return base.TypeAttr | TypeAttributes.Abstract | TypeAttributes.Sealed;
+ }
+ }
+ }
+
+ public class Class : ClassOrStruct {
+ // <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;
+
+ // Information in the case we are an attribute type
+ AttributeUsageAttribute attribute_usage;
+
+ public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
+ Attributes attrs, Location l)
+ : base (ns, parent, name, attrs, Kind.Class, l)
+ {
+ int accmods;
+
+ if (parent.Parent == null)
+ accmods = Modifiers.INTERNAL;
+ else
+ accmods = Modifiers.PRIVATE;
+
+ this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
+ if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.SEALED)) == (Modifiers.ABSTRACT | Modifiers.SEALED)) {
+ Report.Error (502, Location, "'{0}' cannot be both abstract and sealed", GetSignatureForError ());
+ }
+
+ attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Class;
+ }
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.UsageAttribute != null) {
+ if (ptype != TypeManager.attribute_type &&
+ !ptype.IsSubclassOf (TypeManager.attribute_type) &&
+ TypeBuilder.FullName != "System.Attribute") {
+ Report.Error (641, a.Location, "Attribute '{0}' is only valid on classes derived from System.Attribute", a.Name);
+ }
+ attribute_usage = a.UsageAttribute;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public AttributeUsageAttribute AttributeUsage {
+ get {
+ return attribute_usage;
+ }
+ }
+
+ public const TypeAttributes DefaultTypeAttributes =
+ TypeAttributes.AutoLayout | TypeAttributes.Class;
+
+ //
+ // FIXME: How do we deal with the user specifying a different
+ // layout?
+ //
+ public override TypeAttributes TypeAttr {
+ get {
+ return base.TypeAttr | DefaultTypeAttributes;
+ }
+ }
+ }
+
+ public class Struct : ClassOrStruct {
+ // <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 (NamespaceEntry ns, TypeContainer parent, MemberName name,
+ int mod, Attributes attrs, Location l)
+ : base (ns, parent, name, attrs, Kind.Struct, 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;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Struct;
+ }
+ }
+
+ public const TypeAttributes DefaultTypeAttributes =
+ TypeAttributes.SequentialLayout |
+ TypeAttributes.Sealed |
+ TypeAttributes.BeforeFieldInit;
+
+ //
+ // 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 | DefaultTypeAttributes;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Interfaces
+ /// </summary>
+ public class Interface : TypeContainer, IMemberContainer {
+ /// <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 (NamespaceEntry ns, TypeContainer parent, MemberName name,
+ int mod, Attributes attrs, Location l)
+ : base (ns, parent, name, attrs, Kind.Interface, l)
+ {
+ int accmods;
+
+ if (parent.Parent == null)
+ accmods = Modifiers.INTERNAL;
+ else
+ accmods = Modifiers.PRIVATE;
+
+ this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
+ }
+
+ public override void Register ()
+ {
+ Parent.AddInterface (this);
+ }
+
+ public override PendingImplementation GetPendingImplementations ()
+ {
+ return null;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Interface;
+ }
+ }
+
+ public const TypeAttributes DefaultTypeAttributes =
+ TypeAttributes.AutoLayout |
+ TypeAttributes.Abstract |
+ TypeAttributes.Interface;
+
+ public override TypeAttributes TypeAttr {
+ get {
+ return base.TypeAttr | DefaultTypeAttributes;
+ }
+ }
+ }
+
+ public abstract class MethodCore : MemberBase {
+ public readonly Parameters Parameters;
+ public readonly GenericMethod GenericMethod;
+ public readonly DeclSpace ds;
+ protected ToplevelBlock block;
+
+ //
+ // Parameters, cached for semantic analysis.
+ //
+ protected InternalParameters parameter_info;
+ protected Type [] parameter_types;
+
+ // Whether this is an operator method.
+ public bool IsOperator;
+
+ //
+ // The method we're overriding if this is an override method.
+ //
+ protected MethodInfo parent_method = null;
+
+ static string[] attribute_targets = new string [] { "method", "return" };
+
+ public MethodCore (TypeContainer parent, GenericMethod generic,
+ Expression type, int mod, int allowed_mod, bool is_iface,
+ MemberName name, Attributes attrs, Parameters parameters,
+ Location loc)
+ : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
+ attrs, loc)
+ {
+ Parameters = parameters;
+ IsInterface = is_iface;
+ this.GenericMethod = generic;
+
+ if (generic != null)
+ ds = generic;
+ else
+ ds = parent;
+ }
+
+ //
+ // 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 ToplevelBlock Block {
+ get {
+ return block;
+ }
+
+ set {
+ block = value;
+ }
+ }
+
+ protected override bool CheckBase ()
+ {
+ if (!base.CheckBase ())
+ return false;
+
+ // Check whether arguments were correct.
+ if (!DoDefineParameters ())
+ return false;
+
+ if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
+ return false;
+
+ if (IsExplicitImpl)
+ return true;
+
+ // Is null for System.Object while compiling corlib and base interfaces
+ if (Parent.ParentCache == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
+ }
+ return true;
+ }
+
+ Type parent_ret_type = null;
+ parent_method = FindOutParentMethod (Parent, ref parent_ret_type);
+
+ // method is override
+ if (parent_method != null) {
+
+ if (!CheckMethodAgainstBase ())
+ return false;
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ if (!MemberType.Equals (TypeManager.TypeToCoreType (parent_ret_type))) {
+ Report.SymbolRelatedToPreviousError (parent_method);
+ Report.Error (508, Location, GetSignatureForError (Parent) + ": cannot " +
+ "change return type when overriding inherited member");
+ return false;
+ }
+ } else {
+ if (parent_method.IsAbstract && !IsInterface) {
+ Report.SymbolRelatedToPreviousError (parent_method);
+ Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
+ return false;
+ }
+ }
+
+ if (parent_method.IsSpecialName && !(this is PropertyBase)) {
+ Report.Error (561, Location, "'{0}': cannot override '{1}' because it is a special compiler-generated method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (parent_method));
+ return false;
+ }
+
+ if (RootContext.WarningLevel > 2) {
+ if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
+ Parent.Methods.HasEquals = true;
+ else if (Name == "GetHashCode" && parameter_types.Length == 0)
+ Parent.Methods.HasGetHashCode = true;
+ }
+
+ ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
+ if (oa != null) {
+ EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
+ if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
+ Report.SymbolRelatedToPreviousError (parent_method);
+ Report.Warning (672, 1, Location, "Member '{0}' overrides obsolete member. Add the Obsolete attribute to '{0}'", GetSignatureForError (Parent));
+ }
+ }
+ return true;
+ }
+
+ MemberInfo conflict_symbol = Parent.FindMemberWithSameName (Name, !(this is Property));
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+ if (conflict_symbol != null) {
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ if (this is PropertyBase)
+ Report.Error (544, Location, "'{0}': cannot override because '{1}' is not a property", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
+ else
+ Report.Error (505, Location, "'{0}': cannot override because '{1}' is not a method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
+ } else
+ Report.Error (115, Location, "'{0}': no suitable methods found to override", GetSignatureForError (Parent));
+ return false;
+ }
+
+ if (conflict_symbol == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
+ }
+ return true;
+ }
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ if (this is Method && conflict_symbol is MethodBase)
+ return true;
+
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
+
+ return true;
+ }
+
+
+ //
+ // 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)
+ //
+ bool CheckMethodAgainstBase ()
+ {
+ bool ok = true;
+
+ // TODO: replace with GetSignatureForError
+ string name = parent_method.DeclaringType.Name + "." + parent_method.Name;
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0){
+ if (!(parent_method.IsAbstract || parent_method.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 (parent_method.IsFinal) {
+ // This happens when implementing interface methods.
+ if (parent_method.IsHideBySig && parent_method.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 = flags & MethodAttributes.MemberAccessMask;
+ MethodAttributes parentp = parent_method.Attributes & MethodAttributes.MemberAccessMask;
+
+ if (!CheckAccessModifiers (thisp, parentp, parent_method)) {
+ Error_CannotChangeAccessModifiers (Parent, parent_method, name);
+ ok = false;
+ }
+ }
+
+ if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
+ ModFlags |= Modifiers.NEW;
+ Report.SymbolRelatedToPreviousError (parent_method);
+ if (!IsInterface && (parent_method.IsVirtual || parent_method.IsAbstract)) {
+ if (RootContext.WarningLevel >= 2)
+ Report.Warning (114, Location, "'{0}' hides inherited member '{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", GetSignatureForError (Parent), TypeManager.CSharpSignature (parent_method));
+ } else
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
+
+ return ok;
+ }
+
+ protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes parentp, MethodInfo base_method)
+ {
+ 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 != base_method.DeclaringType.Assembly){
+ //
+ // assemblies differ - report an error
+ //
+
+ return false;
+ } else if (thisp != parentp) {
+ //
+ // same assembly, but other attributes differ - report an error
+ //
+
+ return false;
+ };
+ } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
+ //
+ // if it's not "protected internal", it must be "protected"
+ //
+
+ return false;
+ } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
+ //
+ // protected within the same assembly - an error
+ //
+ return false;
+ } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
+ (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
+ //
+ // protected ok, but other attributes differ - report an error
+ //
+ return false;
+ }
+ return true;
+ } else {
+ return (thisp == parentp);
+ }
+ }
+
+ 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 + "'");
+ }
+
+ protected static string Error722 {
+ get {
+ return "'{0}': static types cannot be used as return types";
+ }
+ }
+
+ /// <summary>
+ /// For custom member duplication search in a container
+ /// </summary>
+ protected abstract bool CheckForDuplications ();
+
+ /// <summary>
+ /// Gets parent method and its return type
+ /// </summary>
+ protected abstract MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type);
+
+ protected virtual bool DoDefineParameters ()
+ {
+ EmitContext ec = ds.EmitContext;
+ if (ec == null)
+ throw new InternalErrorException ("DoDefineParameters invoked too early");
+
+ bool old_unsafe = ec.InUnsafe;
+ ec.InUnsafe = InUnsafe;
+ // Check if arguments were correct
+ parameter_types = Parameters.GetParameterInfo (ec);
+ ec.InUnsafe = old_unsafe;
+
+ if ((parameter_types == null) ||
+ !CheckParameters (ds, parameter_types))
+ return false;
+
+ TypeParameter[] tparam = ds.IsGeneric ? ds.TypeParameters : null;
+ parameter_info = new InternalParameters (parameter_types, Parameters, tparam);
+
+ 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;
+ }
+
+ void error_425 (Type old, Type t, string name)
+ {
+ Report.Error (425, Location,
+ "The constraints of type parameter `{0}' " +
+ "of method `{1}' must match the constraints for " +
+ "type parameter `{2}' of method `{3}'",
+ TypeManager.CSharpName (old), Name,
+ TypeManager.CSharpName (t), name);
+ }
+
+ protected override bool CheckGenericOverride (MethodInfo method, string name)
+ {
+ ParameterData pd = Invocation.GetParameterData (method);
+
+ for (int i = 0; i < ParameterTypes.Length; i++) {
+ GenericConstraints ogc = pd.GenericConstraints (i);
+ GenericConstraints gc = ParameterInfo.GenericConstraints (i);
+
+ if ((gc == null) && (ogc == null))
+ continue;
+
+ Type ot = pd.ParameterType (i);
+ Type t = ParameterTypes [i];
+
+ if (!((gc != null) && (ogc != null))) {
+ error_425 (ot, t, name);
+ return false;
+ }
+
+ if ((gc.Attributes != ogc.Attributes) ||
+ (gc.HasClassConstraint != ogc.HasClassConstraint)) {
+ error_425 (ot, t, name);
+ return false;
+ }
+
+ if (ogc.HasClassConstraint &&
+ !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
+ error_425 (ot, t, name);
+ return false;
+ }
+
+ Type[] oct = ogc.InterfaceConstraints;
+ Type[] ct = gc.InterfaceConstraints;
+
+ if (oct.Length != ct.Length) {
+ error_425 (ot, t, name);
+ return false;
+ }
+
+ for (int j = 0; j < oct.Length; j++)
+ if (!oct [j].Equals (ct [j])) {
+ error_425 (ot, t, name);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds)) {
+ if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
+ Report.Error (3011, Location, "'{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
+ }
+ return false;
+ }
+
+ if (Parameters.HasArglist) {
+ Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
+ }
+
+ if (!AttributeTester.IsClsCompliant (MemberType)) {
+ if ((this is Property) || (this is Indexer))
+ Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
+ GetSignatureForError ());
+ else
+ Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant",
+ GetSignatureForError ());
+ }
+
+ AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
+
+ return true;
+ }
+
+ bool MayUnify (MethodCore first, MethodCore second)
+ {
+ int a_type_params = 0;
+ if (first.GenericMethod != null)
+ a_type_params = first.GenericMethod.CountTypeParameters;
+
+ int b_type_params = 0;
+ if (second.GenericMethod != null)
+ b_type_params = second.GenericMethod.CountTypeParameters;
+
+ if (a_type_params != b_type_params)
+ return false;
+
+ Type[] class_infered, method_infered;
+ if (Parent.CountTypeParameters > 0)
+ class_infered = new Type [Parent.CountTypeParameters];
+ else
+ class_infered = null;
+
+ if (a_type_params > 0)
+ method_infered = new Type [a_type_params];
+ else
+ method_infered = null;
+
+ return TypeManager.MayBecomeEqualGenericInstances (
+ first.ParameterTypes, second.ParameterTypes, class_infered, method_infered);
+ }
+
+ protected bool IsDuplicateImplementation (MethodCore method)
+ {
+ if ((method == this) ||
+ (method.MemberName.GetTypeName () != MemberName.GetTypeName ()))
+ return false;
+
+ Type[] param_types = method.ParameterTypes;
+ if (param_types == null)
+ return false;
+
+ if (param_types.Length != ParameterTypes.Length)
+ return false;
+
+ bool equal = true;
+ bool may_unify = MayUnify (this, method);
+
+ for (int i = 0; i < param_types.Length; i++) {
+ if (param_types [i] != ParameterTypes [i])
+ equal = false;
+ }
+
+ // TODO: make operator compatible with MethodCore to avoid this
+ if (this is Operator && method is Operator) {
+ if (MemberType != method.MemberType)
+ equal = may_unify = false;
+ }
+
+ if (equal) {
+ //
+ // Try to report 663: method only differs on out/ref
+ //
+ ParameterData info = ParameterInfo;
+ ParameterData other_info = method.ParameterInfo;
+ for (int i = 0; i < info.Count; i++){
+ if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
+ Report.Error (663, Location,
+ "Overload method only differs " +
+ "in parameter modifier");
+ return false;
+ }
+ }
+
+ Report.SymbolRelatedToPreviousError (method);
+ Report.Error (111, Location, "Type '{0}' already defines a member called '{1}' with the same parameter types", Parent.Name, Name);
+ return true;
+ } else if (may_unify) {
+ Report.Error (408, Location,
+ "`{0}' cannot define overload members that " +
+ "may unify for some type parameter substitutions",
+ Parent.MemberName);
+ return true;
+ }
+
+ return false;
+ }
+
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public override string GetDocCommentName (DeclSpace ds)
+ {
+ return DocUtil.GetMethodDocCommentName (this, ds);
+ }
+
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ // FIXME: with a few effort, it could be done with XmlReader,
+ // that means removal of DOM use.
+ //
+ internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
+ {
+ DocUtil.OnMethodGenerateDocComment (this, ds, el);
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "M:"; }
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ base.VerifyObsoleteAttribute ();
+
+ if (parameter_types == null)
+ return;
+
+ foreach (Type type in parameter_types) {
+ CheckUsageOfObsoleteAttribute (type);
+ }
+ }
+ }
+
+ public class SourceMethod : ISourceMethod
+ {
+ TypeContainer container;
+ MethodBase builder;
+
+ protected SourceMethod (TypeContainer container, MethodBase builder,
+ ISourceFile file, Location start, Location end)
+ {
+ this.container = container;
+ this.builder = builder;
+
+ CodeGen.SymbolWriter.OpenMethod (
+ file, this, start.Row, 0, end.Row, 0);
+ }
+
+ public string Name {
+ get { return builder.Name; }
+ }
+
+ public int NamespaceID {
+ get { return container.NamespaceEntry.SymbolFileID; }
+ }
+
+ public int Token {
+ get {
+ if (builder is MethodBuilder)
+ return ((MethodBuilder) builder).GetToken ().Token;
+ else if (builder is ConstructorBuilder)
+ return ((ConstructorBuilder) builder).GetToken ().Token;
+ else
+ throw new NotSupportedException ();
+ }
+ }
+
+ public void CloseMethod ()
+ {
+ if (CodeGen.SymbolWriter != null)
+ CodeGen.SymbolWriter.CloseMethod ();
+ }
+
+ public static SourceMethod Create (TypeContainer parent,
+ MethodBase builder, Block block)
+ {
+ if (CodeGen.SymbolWriter == null)
+ return null;
+ if (block == null)
+ return null;
+
+ Location start_loc = block.StartLocation;
+ if (Location.IsNull (start_loc))
+ return null;
+
+ Location end_loc = block.EndLocation;
+ if (Location.IsNull (end_loc))
+ return null;
+
+ ISourceFile file = start_loc.SourceFile;
+ if (file == null)
+ return null;
+
+ return new SourceMethod (
+ parent, builder, file, start_loc, end_loc);
+ }
+ }
+
+ public class Method : MethodCore, IIteratorContainer, IMethodData {
+ public MethodBuilder MethodBuilder;
+ public MethodData MethodData;
+ ReturnParameter return_attributes;
+ ListDictionary declarative_security;
+
+ /// <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.METHOD_YIELDS |
+ Modifiers.EXTERN;
+
+ const int AllowedInterfaceModifiers =
+ Modifiers.NEW | Modifiers.UNSAFE;
+
+ //
+ // return_type can be "null" for VOID values.
+ //
+ public Method (TypeContainer parent, GenericMethod generic,
+ Expression return_type, int mod, bool is_iface,
+ MemberName name, Parameters parameters, Attributes attrs,
+ Location l)
+ : base (parent, generic, return_type, mod,
+ is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
+ is_iface, name, attrs, parameters, l)
+ {
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method;
+ }
+ }
+
+ public override string GetSignatureForError()
+ {
+ if (MethodBuilder == null) {
+ return GetSignatureForError (Parent);
+ }
+ return TypeManager.CSharpSignature (MethodBuilder);
+ }
+
+ /// <summary>
+ /// Use this method when MethodBuilder is null
+ /// </summary>
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ // TODO: get params from somewhere
+ if (parameter_info == null)
+ return base.GetSignatureForError (tc);
+
+ // TODO: move to parameters
+ System.Text.StringBuilder args = new System.Text.StringBuilder ();
+ if (parameter_info.Parameters.FixedParameters != null) {
+ for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
+ Parameter p = parameter_info.Parameters.FixedParameters [i];
+ args.Append (p.GetSignatureForError ());
+
+ if (i < parameter_info.Parameters.FixedParameters.Length - 1)
+ args.Append (',');
+ }
+ }
+
+ return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
+ }
+
+ void DuplicateEntryPoint (MethodInfo b, Location location)
+ {
+ Report.Error (
+ 17, location,
+ "Program `" + CodeGen.FileName +
+ "' has more than one entry point defined: `" +
+ TypeManager.CSharpSignature(b) + "'");
+ }
+
+ 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;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Target == AttributeTargets.ReturnValue) {
+ if (return_attributes == null)
+ return_attributes = new ReturnParameter (MethodBuilder, Location);
+
+ return_attributes.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
+ MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
+ }
+
+ if (a.Type == TypeManager.dllimport_type) {
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+ if ((ModFlags & extern_static) != extern_static) {
+ Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
+ }
+
+ return;
+ }
+
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
+ if (declarative_security == null)
+ declarative_security = new ListDictionary ();
+ a.ExtractSecurityPermissionSet (declarative_security);
+ return;
+ }
+
+ if (a.Type == TypeManager.conditional_attribute_type) {
+ if (IsOperator || IsExplicitImpl) {
+ Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
+ return;
+ }
+
+ if (ReturnType != TypeManager.void_type) {
+ Report.Error (578, Location, "Conditional not valid on '{0}' because its return new ErrorData ( type is not void", GetSignatureForError ());
+ return;
+ }
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+ Report.Error (243, Location, "Conditional not valid on '{0}' because it is an override method", GetSignatureForError ());
+ return;
+ }
+
+ if (IsInterface) {
+ Report.Error (582, Location, "Conditional not valid on interface members");
+ return;
+ }
+
+ if (MethodData.IsImplementing) {
+ Report.Error (629, Location, "Conditional member '{0}' cannot implement interface member", GetSignatureForError ());
+ return;
+ }
+
+ for (int i = 0; i < parameter_info.Count; ++i) {
+ if ((parameter_info.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
+ Report.Error (685, Location, "Conditional method '{0}' cannot have an out parameter", GetSignatureForError ());
+ return;
+ }
+ }
+ }
+
+ MethodBuilder.SetCustomAttribute (cb);
+ }
+
+ protected override bool CheckForDuplications ()
+ {
+ ArrayList ar = Parent.Methods;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Method m = (Method) ar [i];
+ if (IsDuplicateImplementation (m))
+ return false;
+ }
+ }
+
+ ar = Parent.Properties;
+ if (ar != null) {
+ for (int i = 0; i < ar.Count; ++i) {
+ PropertyBase pb = (PropertyBase) ar [i];
+ if (pb.AreAccessorsDuplicateImplementation (this))
+ return false;
+ }
+ }
+
+ ar = Parent.Indexers;
+ if (ar != null) {
+ for (int i = 0; i < ar.Count; ++i) {
+ PropertyBase pb = (PropertyBase) ar [i];
+ if (pb.AreAccessorsDuplicateImplementation (this))
+ return false;
+ }
+ }
+
+ ar = Parent.Events;
+ if (ar != null) {
+ for (int i = 0; i < ar.Count; ++i) {
+ Event ev = (Event) ar [i];
+ if (ev.AreAccessorsDuplicateImplementation (this))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //
+ // Creates the type
+ //
+ public override bool Define ()
+ {
+ if (!DoDefineBase ())
+ return false;
+
+ MethodBuilder mb = null;
+ if (GenericMethod != null) {
+ string mname = MemberName.GetMethodName ();
+ mb = Parent.TypeBuilder.DefineGenericMethod (mname, flags);
+ if (!GenericMethod.Define (mb, ReturnType))
+ return false;
+ }
+
+ if (!DoDefine (ds))
+ return false;
+
+ if (!CheckBase ())
+ return false;
+
+ if (IsOperator)
+ flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+
+ MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
+ this, mb, GenericMethod, parent_method);
+
+ if (!MethodData.Define (Parent))
+ return false;
+
+ //
+ // Setup iterator if we are one
+ //
+ if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
+ Iterator iterator = new Iterator (
+ Parent, Name, MemberType, ParameterTypes,
+ ParameterInfo, ModFlags, block, Location);
+
+ if (!iterator.DefineIterator ())
+ return false;
+
+ block = iterator.Block;
+ }
+
+ MethodBuilder = MethodData.MethodBuilder;
+
+ //
+ // This is used to track the Entry Point,
+ //
+ if (Name == "Main" &&
+ ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
+ (RootContext.MainClass == null ||
+ RootContext.MainClass == Parent.TypeBuilder.FullName)){
+ if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
+ if (RootContext.EntryPoint == null) {
+ if (Parent.IsGeneric){
+ Report.Error (-201, Location,
+ "Entry point can not be defined in a generic class");
+ }
+
+ RootContext.EntryPoint = MethodBuilder;
+ RootContext.EntryPointLocation = Location;
+ } else {
+ DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
+ DuplicateEntryPoint (MethodBuilder, Location);
+ }
+ } else {
+ if (RootContext.WarningLevel >= 4)
+ Report.Warning (28, Location, "'{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder) );
+ }
+ }
+
+ if (MemberType.IsAbstract && MemberType.IsSealed) {
+ Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
+ return false;
+ }
+
+ return true;
+ }
+
+ //
+ // Emits the code
+ //
+ public override void Emit ()
+ {
+ MethodData.Emit (Parent, this);
+ base.Emit ();
+
+ if (declarative_security != null) {
+ foreach (DictionaryEntry de in declarative_security) {
+ MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
+ }
+ }
+
+ Block = null;
+ MethodData = null;
+ }
+
+ protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
+ {
+ MethodInfo mi = (MethodInfo) container.ParentCache.FindMemberToOverride (
+ container.TypeBuilder, Name, ParameterTypes, false);
+
+ if (mi == null)
+ return null;
+
+ parent_ret_type = mi.ReturnType;
+ return mi;
+ }
+
+ protected override bool VerifyClsCompliance(DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds))
+ return false;
+
+ if (parameter_types.Length > 0) {
+ ArrayList al = (ArrayList)ds.MemberCache.Members [Name];
+ if (al.Count > 1)
+ ds.MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
+ }
+
+ return true;
+ }
+
+
+ void IIteratorContainer.SetYields ()
+ {
+ ModFlags |= Modifiers.METHOD_YIELDS;
+ }
+
+ #region IMethodData Members
+
+ public CallingConventions CallingConventions {
+ get {
+ CallingConventions cc = Parameters.GetCallingConvention ();
+ if (Parameters.HasArglist)
+ block.HasVarargs = true;
+
+ if (!IsInterface)
+ if ((ModFlags & Modifiers.STATIC) == 0)
+ cc |= CallingConventions.HasThis;
+
+ // FIXME: How is `ExplicitThis' used in C#?
+
+ return cc;
+ }
+ }
+
+ public Type ReturnType {
+ get {
+ return MemberType;
+ }
+ }
+
+ public MemberName MethodName {
+ get {
+ return MemberName;
+ }
+ }
+
+ public new Location Location {
+ get {
+ return base.Location;
+ }
+ }
+
+ public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
+ {
+ return new EmitContext (
+ tc, ds, Location, ig, ReturnType, ModFlags, false);
+ }
+
+ public ObsoleteAttribute GetObsoleteAttribute ()
+ {
+ return GetObsoleteAttribute (ds);
+ }
+
+ /// <summary>
+ /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
+ /// </summary>
+ public bool IsExcluded (EmitContext ec)
+ {
+ if ((caching_flags & Flags.Excluded_Undetected) == 0)
+ return (caching_flags & Flags.Excluded) != 0;
+
+ caching_flags &= ~Flags.Excluded_Undetected;
+
+ if (parent_method == null) {
+ if (OptAttributes == null)
+ return false;
+
+ Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
+
+ if (attrs == null)
+ return false;
+
+ foreach (Attribute a in attrs) {
+ string condition = a.GetConditionalAttributeValue (ds);
+ if (RootContext.AllDefines.Contains (condition))
+ return false;
+ }
+
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+
+ IMethodData md = TypeManager.GetMethod (parent_method);
+ if (md == null) {
+ if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+ return false;
+ }
+
+ if (md.IsExcluded (ec)) {
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+ return false;
+ }
+
+ GenericMethod IMethodData.GenericMethod {
+ get {
+ return GenericMethod;
+ }
+ }
+
+ #endregion
+ }
+
+ public abstract class ConstructorInitializer {
+ ArrayList argument_list;
+ protected 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 (ConstructorBuilder caller_builder, EmitContext ec)
+ {
+ Expression parent_constructor_group;
+ Type t;
+
+ ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
+
+ 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, ".ctor", MemberTypes.Constructor,
+ BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+ loc);
+
+ if (parent_constructor_group == null){
+ parent_constructor_group = Expression.MemberLookup (
+ ec, t, ".ctor", MemberTypes.Constructor,
+ BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+ loc);
+
+ if (parent_constructor_group != null)
+ Report.Error (
+ 112, loc, "`{0}.{1}' is inaccessible due to " +
+ "its protection level", t.FullName, t.Name);
+ else
+ 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,
+ false, loc);
+
+ if (parent_constructor == null){
+ Report.Error (1501, loc,
+ "Can not find a constructor for this argument list");
+ return false;
+ }
+
+ if (parent_constructor == caller_builder){
+ Report.Error (516, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Method search for base ctor. (We do not cache it).
+ /// </summary>
+ Constructor GetOverloadedConstructor (TypeContainer tc)
+ {
+ if (tc.InstanceConstructors == null)
+ return null;
+
+ foreach (Constructor c in tc.InstanceConstructors) {
+ if (Arguments == null) {
+ if (c.ParameterTypes.Length == 0)
+ return c;
+
+ continue;
+ }
+
+ bool ok = true;
+
+ int count = c.ParameterInfo.Count;
+ if ((count > 0) &&
+ c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
+ for (int i = 0; i < count-1; i++)
+ if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
+ ok = false;
+ break;
+ }
+ } else {
+ if (c.ParameterTypes.Length != Arguments.Count)
+ continue;
+
+ for (int i = 0; i < Arguments.Count; ++i)
+ if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (!ok)
+ continue;
+
+ return c;
+ }
+
+ return null;
+ }
+
+ //TODO: implement caching when it will be necessary
+ public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
+ {
+ Constructor ctor = GetOverloadedConstructor (tc);
+ if (ctor == null)
+ return;
+
+ ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
+ if (oa == null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
+ }
+ }
+
+ public class ConstructorBaseInitializer : ConstructorInitializer {
+ public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
+ {
+ }
+
+ public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
+ if (parent_constructor == null)
+ return;
+
+ TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.TypeBuilder.BaseType);
+ if (type_ds == null) {
+ ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
+
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
+
+ return;
+ }
+
+ base.CheckObsoleteAttribute (type_ds, loc);
+ }
+
+ }
+
+ public class ConstructorThisInitializer : ConstructorInitializer {
+ public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
+ {
+ }
+ }
+
+ public class Constructor : MethodCore, IMethodData {
+ public ConstructorBuilder ConstructorBuilder;
+ public ConstructorInitializer Initializer;
+ ListDictionary declarative_security;
+
+ // <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;
+
+ bool has_compliant_args = false;
+ //
+ // The spec claims that static is not permitted, but
+ // my very own code has static constructors.
+ //
+ public Constructor (TypeContainer ds, string name, int mod, Parameters args,
+ ConstructorInitializer init, Location l)
+ : base (ds, null, null, mod, AllowedModifiers, false,
+ new MemberName (name), null, args, l)
+ {
+ Initializer = init;
+ }
+
+ public override string GetSignatureForError()
+ {
+ if (ConstructorBuilder == null)
+ return GetSignatureForError (Parent);
+
+ return TypeManager.CSharpSignature (ConstructorBuilder);
+ }
+
+ public bool HasCompliantArgs {
+ get {
+ return has_compliant_args;
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Constructor;
+ }
+ }
+
+
+ //
+ // 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);
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
+ if (declarative_security == null) {
+ declarative_security = new ListDictionary ();
+ }
+ a.ExtractSecurityPermissionSet (declarative_security);
+ return;
+ }
+
+ ConstructorBuilder.SetCustomAttribute (cb);
+ }
+
+ protected override bool CheckForDuplications ()
+ {
+ ArrayList ar = Parent.InstanceConstructors;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Constructor m = (Constructor) ar [i];
+ if (IsDuplicateImplementation (m))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected override bool CheckBase ()
+ {
+ // Check whether arguments were correct.
+ if (!DoDefineParameters ())
+ return false;
+
+ // TODO: skip the rest for generated ctor
+ if ((ModFlags & Modifiers.STATIC) != 0)
+ return true;
+
+ if (!CheckForDuplications ())
+ return false;
+
+ if (Parent.Kind == Kind.Struct) {
+ if (ParameterTypes.Length == 0) {
+ Report.Error (568, Location,
+ "Structs can not contain explicit parameterless " +
+ "constructors");
+ return false;
+ }
+
+ if ((ModFlags & Modifiers.PROTECTED) != 0) {
+ Report.Error (666, Location, "Protected member in struct declaration");
+ return false;
+ }
+ }
+
+ if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
+ Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
+ }
+
+ return true;
+ }
+
+ //
+ // Creates the ConstructorBuilder
+ //
+ public override bool Define ()
+ {
+ MethodAttributes ca = (MethodAttributes.RTSpecialName |
+ MethodAttributes.SpecialName);
+
+ if ((ModFlags & Modifiers.STATIC) != 0){
+ ca |= MethodAttributes.Static | MethodAttributes.Private;
+ } else {
+ 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;
+ }
+
+ // Check if arguments were correct.
+ if (!CheckBase ())
+ return false;
+
+ ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
+ ca, CallingConventions,
+ ParameterTypes);
+
+ if ((ModFlags & Modifiers.UNSAFE) != 0)
+ ConstructorBuilder.InitLocals = false;
+
+ TypeManager.AddMethod (ConstructorBuilder, this);
+
+ //
+ // HACK because System.Reflection.Emit is lame
+ //
+ TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
+
+ return true;
+ }
+
+ //
+ // Emits the code
+ //
+ public override void Emit ()
+ {
+ EmitContext ec = CreateEmitContext (null, null);
+
+ //
+ // 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 (Parent.Kind == Kind.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 (ConstructorBuilder, ec))
+ return;
+ ec.IsStatic = false;
+ }
+
+ Parameters.LabelParameters (ec, ConstructorBuilder, Location);
+
+ SourceMethod source = SourceMethod.Create (
+ Parent, ConstructorBuilder, block);
+
+ //
+ // Classes can have base initializers and instance field initializers.
+ //
+ if (Parent.Kind == Kind.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))
+ Parent.EmitFieldInitializers (ec);
+ }
+ }
+ if (Initializer != null) {
+ if (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent.Parent) == null)
+ Initializer.CheckObsoleteAttribute (Parent, Location);
+ else
+ ec.TestObsoleteMethodUsage = false;
+ Initializer.Emit (ec);
+ }
+
+ if ((ModFlags & Modifiers.STATIC) != 0)
+ Parent.EmitFieldInitializers (ec);
+
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ // If this is a non-static `struct' constructor and doesn't have any
+ // initializer, it must initialize all of the struct's fields.
+ if ((Parent.Kind == Kind.Struct) &&
+ ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
+ Block.AddThisVariable (Parent, Location);
+
+ ec.EmitTopBlock (block, ParameterInfo, Location);
+
+ if (source != null)
+ source.CloseMethod ();
+
+ base.Emit ();
+
+ if (declarative_security != null) {
+ foreach (DictionaryEntry de in declarative_security) {
+ ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
+ }
+ }
+
+ block = null;
+ }
+
+ // Is never override
+ protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
+ {
+ return null;
+ }
+
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
+ return false;
+ }
+
+ if (parameter_types.Length > 0) {
+ ArrayList al = (ArrayList)ds.MemberCache.Members [".ctor"];
+ if (al.Count > 3)
+ ds.MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
+
+ if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
+ foreach (Type param in parameter_types) {
+ if (param.IsArray) {
+ return true;
+ }
+ }
+ }
+ }
+ has_compliant_args = true;
+ return true;
+ }
+
+ #region IMethodData Members
+
+ public System.Reflection.CallingConventions CallingConventions {
+ get {
+ CallingConventions cc = Parameters.GetCallingConvention ();
+
+ if (Parent.Kind == Kind.Class)
+ if ((ModFlags & Modifiers.STATIC) == 0)
+ cc |= CallingConventions.HasThis;
+
+ // FIXME: How is `ExplicitThis' used in C#?
+
+ return cc;
+ }
+ }
+
+ public new Location Location {
+ get {
+ return base.Location;
+ }
+ }
+
+ public MemberName MethodName {
+ get {
+ return MemberName;
+ }
+ }
+
+ public Type ReturnType {
+ get {
+ return MemberType;
+ }
+ }
+
+ public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
+ {
+ ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
+ return new EmitContext (Parent, Location, ig_, null, ModFlags, true);
+ }
+
+ public ObsoleteAttribute GetObsoleteAttribute ()
+ {
+ return null;
+ }
+
+ public bool IsExcluded(EmitContext ec)
+ {
+ return false;
+ }
+
+ GenericMethod IMethodData.GenericMethod {
+ get {
+ return null;
+ }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
+ /// </summary>
+ public interface IMethodData
+ {
+ CallingConventions CallingConventions { get; }
+ Location Location { get; }
+ MemberName MethodName { get; }
+ Type[] ParameterTypes { get; }
+ Type ReturnType { get; }
+ GenericMethod GenericMethod { get; }
+
+ Attributes OptAttributes { get; }
+ ToplevelBlock Block { get; }
+
+ EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
+ ObsoleteAttribute GetObsoleteAttribute ();
+ string GetSignatureForError (TypeContainer tc);
+ bool IsExcluded (EmitContext ec);
+ bool IsClsCompliaceRequired (DeclSpace ds);
+ }
+
+ //
+ // Encapsulates most of the Method's state
+ //
+ public class MethodData {
+
+ readonly IMethodData method;
+
+ //
+ // The return type of this method
+ //
+ public readonly GenericMethod GenericMethod;
+ public readonly InternalParameters ParameterInfo;
+
+ //
+ // Are we implementing an interface ?
+ //
+ public bool IsImplementing = false;
+
+ //
+ // Protected data.
+ //
+ protected MemberBase member;
+ protected int modifiers;
+ protected MethodAttributes flags;
+ protected Type declaring_type;
+ protected MethodInfo parent_method;
+
+ EmitContext ec;
+
+ MethodBuilder builder = null;
+ public MethodBuilder MethodBuilder {
+ get {
+ return builder;
+ }
+ }
+
+ public Type DeclaringType {
+ get {
+ return declaring_type;
+ }
+ }
+
+ public MethodData (MemberBase member, InternalParameters parameters,
+ int modifiers, MethodAttributes flags, IMethodData method)
+ {
+ this.member = member;
+ this.ParameterInfo = parameters;
+ this.modifiers = modifiers;
+ this.flags = flags;
+
+ this.method = method;
+ }
+
+ public MethodData (MemberBase member, InternalParameters parameters,
+ int modifiers, MethodAttributes flags,
+ IMethodData method, MethodBuilder builder,
+ GenericMethod generic, MethodInfo parent_method)
+ : this (member, parameters, modifiers, flags, method)
+ {
+ this.builder = builder;
+ this.GenericMethod = generic;
+ this.parent_method = parent_method;
+ }
+
+ static string RemoveArity (string name)
+ {
+ int start = 0;
+ StringBuilder sb = new StringBuilder ();
+ while (start < name.Length) {
+ int pos = name.IndexOf ('`', start);
+ if (pos < 0) {
+ sb.Append (name.Substring (start));
+ break;
+ }
+
+ sb.Append (name.Substring (start, pos-start));
+
+ pos++;
+ while ((pos < name.Length) && Char.IsNumber (name [pos]))
+ pos++;
+
+ start = pos;
+ }
+
+ return sb.ToString ();
+ }
+
+ public bool Define (TypeContainer container)
+ {
+ MethodInfo implementing = null;
+
+ string prefix;
+ if (member.IsExplicitImpl)
+ prefix = member.InterfaceType.FullName + ".";
+ else
+ prefix = "";
+
+ string name = method.MethodName.Basename;
+ string method_name = prefix + name;
+
+ Type[] ParameterTypes = method.ParameterTypes;
+
+ if (container.Pending != null){
+ if (member is Indexer)
+ implementing = container.Pending.IsInterfaceIndexer (
+ member.InterfaceType, method.ReturnType, ParameterTypes);
+ else
+ implementing = container.Pending.IsInterfaceMethod (
+ member.InterfaceType, name, method.ReturnType, ParameterTypes);
+
+ if (member.InterfaceType != null){
+ if (implementing == null){
+ Report.Error (539, method.Location,
+ "'{0}' in explicit interface declaration is not an interface", method_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 (method.Location, "public, virtual or abstract");
+ implementing = null;
+ }
+ } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
+ if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
+ //
+ // If this is an interface method implementation,
+ // check for public accessibility
+ //
+ implementing = null;
+ } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
+ // We may never be private.
+ implementing = null;
+ } else if ((modifiers & Modifiers.OVERRIDE) == 0){
+ //
+ // We may be protected if we're overriding something.
+ //
+ implementing = null;
+ }
+ }
+
+ //
+ // Static is not allowed
+ //
+ if ((modifiers & Modifiers.STATIC) != 0){
+ implementing = null;
+ Modifiers.Error_InvalidModifier (method.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;
+
+ IsImplementing = true;
+ }
+
+ EmitContext ec = method.CreateEmitContext (container, null);
+
+ DefineMethodBuilder (ec, container, method_name, ParameterTypes);
+
+ if (builder == null)
+ return false;
+
+ if (container.CurrentType != null)
+ declaring_type = container.CurrentType;
+ else
+ declaring_type = container.TypeBuilder;
+
+ 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, method.ReturnType,
+ ParameterTypes, member.IsExplicitImpl);
+ } else
+ container.Pending.ImplementMethod (
+ member.InterfaceType, name, method.ReturnType,
+ ParameterTypes, member.IsExplicitImpl);
+
+ if (member.IsExplicitImpl)
+ container.TypeBuilder.DefineMethodOverride (
+ builder, implementing);
+
+ }
+
+ TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes);
+ TypeManager.AddMethod (builder, method);
+
+ if (GenericMethod != null) {
+ bool is_override = member.IsExplicitImpl |
+ ((modifiers & Modifiers.OVERRIDE) != 0);
+
+ if (implementing != null)
+ parent_method = implementing;
+
+ if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Create the MethodBuilder for the method
+ /// </summary>
+ void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
+ {
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+
+ if ((modifiers & extern_static) == extern_static) {
+
+ if (method.OptAttributes != null) {
+ Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
+ if (dllimport_attribute != null) {
+ flags |= MethodAttributes.PinvokeImpl;
+ builder = dllimport_attribute.DefinePInvokeMethod (
+ ec, container.TypeBuilder, method_name, flags,
+ method.ReturnType, ParameterTypes);
+
+ return;
+ }
+ }
+
+ // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
+ // We are more strict than Microsoft and report CS0626 like error
+ if (method.OptAttributes == null ||
+ !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
+ Report.Error (626, method.Location, "Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation", method.GetSignatureForError (container));
+ return;
+ }
+ }
+
+ if (builder == null)
+ builder = container.TypeBuilder.DefineMethod (
+ method_name, flags, method.CallingConventions,
+ method.ReturnType, ParameterTypes);
+ else
+ builder.SetGenericMethodSignature (
+ flags, method.CallingConventions,
+ method.ReturnType, ParameterTypes);
+ }
+
+ //
+ // Emits the code
+ //
+ public void Emit (TypeContainer container, Attributable kind)
+ {
+ EmitContext ec;
+ if ((flags & MethodAttributes.PinvokeImpl) == 0)
+ ec = method.CreateEmitContext (container, builder.GetILGenerator ());
+ else
+ ec = method.CreateEmitContext (container, null);
+
+ if (method.GetObsoleteAttribute () != null || container.GetObsoleteAttribute (container.Parent) != null)
+ ec.TestObsoleteMethodUsage = false;
+
+ Location loc = method.Location;
+ Attributes OptAttributes = method.OptAttributes;
+
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, kind);
+
+ if (member is MethodCore)
+ ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
+
+ SymbolWriter sw = CodeGen.SymbolWriter;
+ ToplevelBlock block = method.Block;
+
+ //
+ // abstract or extern methods have no bodies
+ //
+ if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
+ if (block == null)
+ return;
+
+ //
+ // abstract or extern methods have no bodies.
+ //
+ if ((modifiers & Modifiers.ABSTRACT) != 0)
+ Report.Error (
+ 500, method.Location, "Abstract method `" +
+ TypeManager.CSharpSignature (builder) +
+ "' can not have a body");
+
+ if ((modifiers & Modifiers.EXTERN) != 0)
+ Report.Error (
+ 179, method.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, method.Location, "Method `" +
+ TypeManager.CSharpSignature (builder) +
+ "' must declare a body since it is not marked " +
+ "abstract or extern");
+ return;
+ }
+
+ SourceMethod source = SourceMethod.Create (
+ container, MethodBuilder, method.Block);
+
+ //
+ // Handle destructors specially
+ //
+ // FIXME: This code generates buggy code
+ //
+ if (member is Destructor)
+ EmitDestructor (ec, block);
+ else
+ ec.EmitTopBlock (block, ParameterInfo, loc);
+
+ if (source != null)
+ source.CloseMethod ();
+ }
+
+ void EmitDestructor (EmitContext ec, ToplevelBlock block)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label finish = ig.DefineLabel ();
+
+ block.SetDestructor ();
+
+ ig.BeginExceptionBlock ();
+ ec.ReturnLabel = finish;
+ ec.HasReturnLabel = true;
+ ec.EmitTopBlock (block, null, method.Location);
+
+ // ig.MarkLabel (finish);
+ 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, method.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]);
+ }
+ }
+
+ ig.EndExceptionBlock ();
+ //ig.MarkLabel (ec.ReturnLabel);
+ ig.Emit (OpCodes.Ret);
+ }
+ }
+
+ public class Destructor : Method {
+
+ public Destructor (TypeContainer ds, Expression return_type, int mod, string name,
+ Parameters parameters, Attributes attrs, Location l)
+ : base (ds, null, return_type, mod, false, new MemberName (name),
+ parameters, attrs, l)
+ { }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.conditional_attribute_type) {
+ Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+ }
+
+ abstract public class MemberBase : MemberCore {
+ public Expression Type;
+
+ public MethodAttributes flags;
+
+ protected readonly int explicit_mod_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 MemberName ExplicitInterfaceName = null;
+
+ //
+ // Whether this is an interface member.
+ //
+ public bool IsInterface;
+
+ //
+ // If true, the interface type we are explicitly implementing
+ //
+ public Type InterfaceType = null;
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected MemberBase (TypeContainer parent, Expression type, int mod,
+ int allowed_mod, int def_mod, MemberName name,
+ Attributes attrs, Location loc)
+ : base (parent, name, attrs, loc)
+ {
+ explicit_mod_flags = mod;
+ Type = type;
+ ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
+
+ // Check for explicit interface implementation
+ if (MemberName.Left != null) {
+ ExplicitInterfaceName = MemberName.Left;
+ ShortName = MemberName.Name;
+ IsExplicitImpl = true;
+ } else
+ ShortName = Name;
+ }
+
+ protected virtual bool CheckBase ()
+ {
+ if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.Kind == Kind.Struct) {
+ Report.Error (666, Location, "Protected member in struct declaration");
+ return false;
+ }
+
+ if ((RootContext.WarningLevel >= 4) &&
+ ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
+ ((ModFlags & Modifiers.PROTECTED) != 0) &&
+ ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
+ Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
+ }
+
+ return true;
+ }
+
+ protected abstract bool CheckGenericOverride (MethodInfo method, string name);
+
+ protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
+ {
+ bool error = false;
+
+ foreach (Type partype in parameters){
+ if (partype == TypeManager.void_type) {
+ Report.Error (
+ 1547, Location, "Keyword 'void' cannot " +
+ "be used in this context");
+ return false;
+ }
+
+ if (partype.IsPointer){
+ if (!UnsafeOK (ds))
+ error = true;
+ if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
+ error = true;
+ }
+
+ if (ds.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 DoDefineBase ()
+ {
+ EmitContext ec = Parent.EmitContext;
+ if (ec == null)
+ throw new InternalErrorException ("MemberBase.DoDefine called too early");
+
+ if (Name == null)
+ throw new InternalErrorException ();
+
+ if (IsInterface) {
+ ModFlags = Modifiers.PUBLIC |
+ Modifiers.ABSTRACT |
+ Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
+
+ flags = MethodAttributes.Public |
+ MethodAttributes.Abstract |
+ MethodAttributes.HideBySig |
+ MethodAttributes.NewSlot |
+ MethodAttributes.Virtual;
+ } else {
+ if (!Parent.MethodModifiersValid (ModFlags, Name, Location))
+ return false;
+
+ flags = Modifiers.MethodAttr (ModFlags);
+ }
+
+ return true;
+ }
+
+ protected virtual bool DoDefine (DeclSpace decl)
+ {
+ EmitContext ec = decl.EmitContext;
+ if (ec == null)
+ throw new InternalErrorException ("MemberBase.DoDefine called too early");
+
+ ec.InUnsafe = InUnsafe;
+
+ // Lookup Type, verify validity
+ bool old_unsafe = ec.InUnsafe;
+ ec.InUnsafe = InUnsafe;
+ TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
+ ec.InUnsafe = old_unsafe;
+
+ if (texpr == null)
+ return false;
+
+ MemberType = texpr.Type;
+
+ if ((Parent.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 (!Parent.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 MethodCore) {
+ if (this is Operator)
+ 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 (Parent))
+ return false;
+
+ if (IsExplicitImpl) {
+ Expression expr = ExplicitInterfaceName.GetTypeExpression (Location);
+ TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (ec);
+ if (iface_texpr == null)
+ return false;
+
+ InterfaceType = iface_texpr.Type;
+
+ if (!InterfaceType.IsInterface) {
+ Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
+ return false;
+ }
+
+ if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
+ return false;
+
+ Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// The name of the member can be changed during definition (see IndexerName attribute)
+ /// </summary>
+ protected virtual void UpdateMemberName ()
+ {
+ MemberName.Name = ShortName;
+ }
+
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', base.GetSignatureForError (tc));
+ }
+
+ protected bool IsTypePermitted ()
+ {
+ if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
+ Report.Error (610, Location, "Field or property cannot be of type '{0}'", TypeManager.CSharpName (MemberType));
+ return false;
+ }
+ return true;
+ }
+
+ protected override bool VerifyClsCompliance(DeclSpace ds)
+ {
+ if (base.VerifyClsCompliance (ds)) {
+ return true;
+ }
+
+ if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
+ Report.Error (3010, Location, "'{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
+ }
+ return false;
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ CheckUsageOfObsoleteAttribute (MemberType);
+ }
+ }
+
+ //
+ // 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,
+ HAS_OFFSET = 4 // Used by FieldMember.
+ }
+
+ static string[] attribute_targets = new string [] { "field" };
+
+ /// <summary>
+ /// Symbol with same name in parent class/struct
+ /// </summary>
+ public MemberInfo conflict_symbol;
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected FieldBase (TypeContainer parent, Expression type, int mod,
+ int allowed_mod, MemberName name, object init,
+ Attributes attrs, Location loc)
+ : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
+ name, attrs, loc)
+ {
+ this.init = init;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Field;
+ }
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.marshal_as_attr_type) {
+ UnmanagedMarshal marshal = a.GetMarshal (this);
+ if (marshal != null) {
+ FieldBuilder.SetMarshal (marshal);
+ }
+ return;
+ }
+
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
+ a.Error_InvalidSecurityParent ();
+ return;
+ }
+
+ FieldBuilder.SetCustomAttribute (cb);
+ }
+
+ //
+ // 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;
+
+ protected override bool CheckGenericOverride (MethodInfo method, string name)
+ {
+ return true;
+ }
+
+ //
+ // 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;
+ }
+
+ protected override bool CheckBase ()
+ {
+ if (!base.CheckBase ())
+ return false;
+
+ // TODO: Implement
+ if (IsInterface)
+ return true;
+
+ conflict_symbol = Parent.FindMemberWithSameName (Name, false);
+ if (conflict_symbol == null) {
+ if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
+ Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
+ }
+ return true;
+ }
+
+ if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
+
+ return true;
+ }
+
+ protected override bool DoDefine (DeclSpace ds)
+ {
+ if (!base.DoDefine (ds))
+ return false;
+
+ if (MemberType == TypeManager.void_type) {
+ Report.Error (1547, Location,
+ "Keyword 'void' cannot be used in this context");
+ return false;
+ }
+ return true;
+ }
+
+ public override string GetSignatureForError ()
+ {
+ if (FieldBuilder == null) {
+ return base.GetSignatureForError (Parent);
+ }
+ return TypeManager.GetFullNameSignature (FieldBuilder);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds))
+ return false;
+
+ if (FieldBuilder == null) {
+ return true;
+ }
+
+ if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
+ Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
+ }
+ return true;
+ }
+
+
+ public void SetAssigned ()
+ {
+ status |= Status.ASSIGNED;
+ }
+ }
+
+ public abstract class FieldMember: FieldBase
+ {
+
+
+ protected FieldMember (TypeContainer parent, Expression type, int mod,
+ int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
+ : base (parent, type, mod, allowed_mod, name, init, attrs, loc)
+ {
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.field_offset_attribute_type)
+ {
+ status |= Status.HAS_OFFSET;
+
+ if (!Parent.HasExplicitLayout) {
+ Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
+ return;
+ }
+
+ if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
+ Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
+ return;
+ }
+ }
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+
+ public override bool Define()
+ {
+ EmitContext ec = Parent.EmitContext;
+ if (ec == null)
+ throw new InternalErrorException ("FieldMember.Define called too early");
+
+ bool old_unsafe = ec.InUnsafe;
+ ec.InUnsafe = InUnsafe;
+ TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
+ ec.InUnsafe = old_unsafe;
+ if (texpr == null)
+ return false;
+
+ MemberType = texpr.Type;
+
+ if (!CheckBase ())
+ return false;
+
+ if (!Parent.AsAccessible (MemberType, ModFlags)) {
+ Report.Error (52, Location,
+ "Inconsistent accessibility: field type `" +
+ TypeManager.CSharpName (MemberType) + "' is less " +
+ "accessible than field `" + Name + "'");
+ return false;
+ }
+
+ if (!IsTypePermitted ())
+ return false;
+
+ if (MemberType.IsPointer && !UnsafeOK (Parent))
+ return false;
+
+ return true;
+ }
+
+ public override void Emit ()
+ {
+ if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
+ Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
+ }
+
+ base.Emit ();
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "F:"; }
+ }
+ }
+
+ //
+ // The Field class is used to represents class/struct fields during parsing.
+ //
+ public class Field : FieldMember {
+ // <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 (TypeContainer parent, Expression type, int mod, string name,
+ Object expr_or_array_init, Attributes attrs, Location loc)
+ : base (parent, type, mod, AllowedModifiers, new MemberName (name),
+ expr_or_array_init, attrs, loc)
+ {
+ }
+
+ public override bool Define ()
+ {
+ if (!base.Define ())
+ return false;
+
+ if (RootContext.WarningLevel > 1){
+ Type ptype = Parent.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 (!MemberType.IsClass){
+ Type vt = MemberType;
+
+ if (TypeManager.IsEnumType (vt))
+ vt = TypeManager.EnumToUnderlying (MemberType);
+
+ 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) ||
+ (!vt.IsValueType))){
+ Report.Error (
+ 677, Location, Parent.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 (Parent.Kind == Kind.Struct &&
+ ((fa & FieldAttributes.Static) == 0) &&
+ MemberType == Parent.TypeBuilder &&
+ !TypeManager.IsBuiltinType (MemberType)){
+ Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
+ "' causes a cycle in the structure layout");
+ return false;
+ }
+
+ try {
+ FieldBuilder = Parent.TypeBuilder.DefineField (
+ Name, MemberType, Modifiers.FieldAttr (ModFlags));
+
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+ }
+ catch (ArgumentException) {
+ Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
+ return false;
+ }
+
+ return true;
+ }
+
+ public override void Emit ()
+ {
+ if (OptAttributes != null) {
+ EmitContext ec = new EmitContext (
+ Parent, Location, null, FieldBuilder.FieldType,
+ ModFlags);
+ OptAttributes.Emit (ec, this);
+ }
+
+ base.Emit ();
+ }
+ }
+
+ //
+ // `set' and `get' accessors are represented with an Accessor.
+ //
+ public class Accessor {
+ //
+ // Null if the accessor is empty, or a Block if not
+ //
+ public const int AllowedModifiers =
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE;
+
+ public ToplevelBlock Block;
+ public Attributes Attributes;
+ public Location Location;
+ public int ModFlags;
+
+ public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
+ {
+ Block = b;
+ Attributes = attrs;
+ Location = loc;
+ ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
+ }
+ }
+
+
+ // Ooouh Martin, templates are missing here.
+ // When it will be possible move here a lot of child code and template method type.
+ public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
+ protected MethodData method_data;
+ protected ToplevelBlock block;
+ protected ListDictionary declarative_security;
+
+ // The accessor are created event if they are not wanted.
+ // But we need them because their names are reserved.
+ // Field says whether accessor will be emited or not
+ public readonly bool IsDummy;
+
+ protected readonly string prefix;
+
+ ReturnParameter return_attributes;
+
+ public AbstractPropertyEventMethod (MemberBase member, string prefix)
+ : base (null, SetupName (prefix, member), null, member.Location)
+ {
+ this.prefix = prefix;
+ IsDummy = true;
+ }
+
+ public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
+ string prefix)
+ : base (null, SetupName (prefix, member),
+ accessor.Attributes, accessor.Location)
+ {
+ this.prefix = prefix;
+ this.block = accessor.Block;
+ }
+
+ static MemberName SetupName (string prefix, MemberBase member)
+ {
+ MemberName name = member.MemberName.Clone ();
+ name.Name = prefix + member.ShortName;
+ return name;
+ }
+
+ public void UpdateName (MemberBase member)
+ {
+ MemberName.Name = prefix + member.ShortName;
+ }
+
+ #region IMethodData Members
+
+ public ToplevelBlock Block {
+ get {
+ return block;
+ }
+
+ set {
+ block = value;
+ }
+ }
+
+ public CallingConventions CallingConventions {
+ get {
+ return CallingConventions.Standard;
+ }
+ }
+
+ public bool IsExcluded (EmitContext ec)
+ {
+ return false;
+ }
+
+ GenericMethod IMethodData.GenericMethod {
+ get {
+ return null;
+ }
+ }
+
+ public MemberName MethodName {
+ get {
+ return MemberName;
+ }
+ }
+
+ public abstract ObsoleteAttribute GetObsoleteAttribute ();
+ public abstract Type[] ParameterTypes { get; }
+ public abstract Type ReturnType { get; }
+ public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
+
+ #endregion
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
+ a.Type == TypeManager.conditional_attribute_type) {
+ Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on {1} declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
+ return;
+ }
+
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
+ if (declarative_security == null)
+ declarative_security = new ListDictionary ();
+ a.ExtractSecurityPermissionSet (declarative_security);
+ return;
+ }
+
+ if (a.Target == AttributeTargets.Method) {
+ method_data.MethodBuilder.SetCustomAttribute (cb);
+ return;
+ }
+
+ if (a.Target == AttributeTargets.ReturnValue) {
+ if (return_attributes == null)
+ return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
+
+ return_attributes.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ ApplyToExtraTarget (a, cb);
+ }
+
+ virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
+ {
+ System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
+ }
+
+ public override bool Define()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public virtual void Emit (TypeContainer container)
+ {
+ method_data.Emit (container, this);
+
+ if (declarative_security != null) {
+ foreach (DictionaryEntry de in declarative_security) {
+ method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
+ }
+ }
+
+ block = null;
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return false;
+ }
+
+ public bool IsDuplicateImplementation (MethodCore method)
+ {
+ if (Name != method.Name)
+ return false;
+
+ Type[] param_types = method.ParameterTypes;
+
+ if (param_types.Length != ParameterTypes.Length)
+ return false;
+
+ for (int i = 0; i < param_types.Length; i++)
+ if (param_types [i] != ParameterTypes [i])
+ return false;
+
+ Report.SymbolRelatedToPreviousError (method);
+ Report.Error (111, Location, "Type '{0}' already defines a member called '{1}' with " +
+ "the same parameter types", Parent.Name, Name);
+ return true;
+ }
+
+ public new Location Location {
+ get {
+ return base.Location;
+ }
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ }
+
+ }
+
+ //
+ // Properties and Indexers both generate PropertyBuilders, we use this to share
+ // their common bits.
+ //
+ abstract public class PropertyBase : MethodCore {
+
+ public class GetMethod: PropertyMethod
+ {
+ static string[] attribute_targets = new string [] { "method", "return" };
+ Parameters parameters;
+
+ public GetMethod (MethodCore method):
+ base (method, "get_")
+ {
+ }
+
+ public GetMethod (MethodCore method, Accessor accessor):
+ base (method, accessor, "get_")
+ {
+ }
+
+ public GetMethod (MethodCore method, Parameters parameters):
+ base (method, "get_")
+ {
+ this.parameters = parameters;
+ }
+
+ public GetMethod (MethodCore method, Accessor accessor, Parameters parameters):
+ base (method, accessor, "get_")
+ {
+ this.parameters = parameters;
+ }
+
+ protected virtual InternalParameters GetParameterInfo (EmitContext ec)
+ {
+ if (parameters == null) {
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (method.Type, "Screwed", Parameter.Modifier.NONE, null);
+ parameters = new Parameters (parms, null, method.Location);
+ }
+
+ Type [] types = parameters.GetParameterInfo (ec);
+ return new InternalParameters (types, parameters);
+ }
+
+ public override MethodBuilder Define(TypeContainer container)
+ {
+ base.Define (container);
+
+ method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
+
+ if (!method_data.Define (container))
+ return null;
+
+ return method_data.MethodBuilder;
+ }
+
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (base.GetSignatureForError (tc), ".get");
+ }
+
+ public override Type ReturnType {
+ get {
+ return method.MemberType;
+ }
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+ public class SetMethod: PropertyMethod {
+
+ static string[] attribute_targets = new string [] { "method", "param", "return" };
+ ImplicitParameter param_attr;
+
+ Parameters parameters;
+
+ public SetMethod (MethodCore method):
+ base (method, "set_")
+ {
+ }
+
+ public SetMethod (MethodCore method, Accessor accessor):
+ base (method, accessor, "set_")
+ {
+ }
+
+ public SetMethod (MethodCore method, Parameters parameters):
+ base (method, "set_")
+ {
+ this.parameters = parameters;
+ }
+
+ public SetMethod (MethodCore method, Accessor accessor, Parameters parameters):
+ base (method, accessor, "set_")
+ {
+ this.parameters = parameters;
+ }
+ protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Target == AttributeTargets.Parameter) {
+ if (param_attr == null)
+ param_attr = new ImplicitParameter (method_data.MethodBuilder);
+
+ param_attr.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ protected virtual InternalParameters GetParameterInfo (EmitContext ec)
+ {
+
+ if (parameters == null) {
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
+ parameters = new Parameters (parms, null, method.Location);
+ }
+
+ Type [] types = parameters.GetParameterInfo (ec);
+
+ return new InternalParameters (types, parameters);
+ }
+
+ public override MethodBuilder Define(TypeContainer container)
+ {
+ if (container.EmitContext == null)
+ throw new InternalErrorException ("SetMethod.Define called too early");
+
+ base.Define (container);
+
+ method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
+
+ if (!method_data.Define (container))
+ return null;
+
+ return method_data.MethodBuilder;
+ }
+
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (base.GetSignatureForError (tc), ".set");
+ }
+
+ public override Type[] ParameterTypes {
+ get {
+ return new Type[] { method.MemberType };
+ }
+ }
+
+ public override Type ReturnType {
+ get {
+ return TypeManager.void_type;
+ }
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+ static string[] attribute_targets = new string [] { "property" };
+
+ public abstract class PropertyMethod: AbstractPropertyEventMethod {
+ protected readonly MethodCore method;
+ protected MethodAttributes flags;
+
+ public PropertyMethod (MethodCore method, string prefix)
+ : base (method, prefix)
+ {
+ this.method = method;
+ }
+
+ public PropertyMethod (MethodCore method, Accessor accessor, string prefix)
+ : base (method, accessor, prefix)
+ {
+ this.method = method;
+ this.ModFlags = accessor.ModFlags;
+
+ if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (Location, "accessor modifiers");
+ Environment.Exit (1);
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return method.IsClsCompliaceRequired (ds);
+ }
+
+ public InternalParameters ParameterInfo
+ {
+ get {
+ return method_data.ParameterInfo;
+ }
+ }
+
+ public virtual MethodBuilder Define (TypeContainer container)
+ {
+ //
+ // Check for custom access modifier
+ //
+ if (ModFlags == 0) {
+ ModFlags = method.ModFlags;
+ flags = method.flags;
+ } else {
+ CheckModifiers (container, ModFlags);
+ ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
+ flags = Modifiers.MethodAttr (ModFlags);
+ flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
+ }
+
+ return null;
+
+ }
+
+ public override Type[] ParameterTypes {
+ get {
+ return TypeManager.NoTypes;
+ }
+ }
+
+ public override EmitContext CreateEmitContext (TypeContainer tc,
+ ILGenerator ig)
+ {
+ return new EmitContext (
+ tc, method.ds, method.Location, ig, ReturnType,
+ method.ModFlags, false);
+ }
+
+ public override ObsoleteAttribute GetObsoleteAttribute ()
+ {
+ return method.GetObsoleteAttribute (method.ds);
+ }
+
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', method.Name);
+ }
+
+ void CheckModifiers (TypeContainer container, int modflags)
+ {
+ int flags = 0;
+ int mflags = method.ModFlags & Modifiers.Accessibility;
+
+ if ((mflags & Modifiers.PUBLIC) != 0) {
+ flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
+ }
+ else if ((mflags & Modifiers.PROTECTED) != 0) {
+ if ((mflags & Modifiers.INTERNAL) != 0)
+ flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
+
+ flags |= Modifiers.PRIVATE;
+ }
+ else if ((mflags & Modifiers.INTERNAL) != 0)
+ flags |= Modifiers.PRIVATE;
+
+ if ((mflags == modflags) || (modflags & (~flags)) != 0)
+ Report.Error (273, Location, "{0}: accessibility modifier must be more restrictive than the property or indexer",
+ GetSignatureForError (container));
+ }
+ }
+
+ public PropertyMethod Get, Set;
+ public PropertyBuilder PropertyBuilder;
+ public MethodBuilder GetBuilder, SetBuilder;
+
+ protected EmitContext ec;
+
+ public PropertyBase (TypeContainer parent, Expression type, int mod_flags,
+ int allowed_mod, bool is_iface, MemberName name,
+ Parameters parameters, Attributes attrs,
+ Location loc)
+ : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
+ attrs, parameters, loc)
+ {
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
+ a.Error_InvalidSecurityParent ();
+ return;
+ }
+
+ PropertyBuilder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Property;
+ }
+ }
+
+ public override bool Define ()
+ {
+ if (!DoDefine (Parent))
+ return false;
+
+ if (!IsTypePermitted ())
+ return false;
+
+ return true;
+ }
+
+ protected override bool DoDefine (DeclSpace ds)
+ {
+ if (!base.DoDefine (ds))
+ return false;
+
+ //
+ // Accessors modifiers check
+ //
+
+ if (Get.ModFlags != 0 && Set.ModFlags != 0) {
+ Report.Error (274, Location, "'{0}': cannot specify accessibility modifiers for both accessors of the property or indexer.",
+ GetSignatureForError ());
+ return false;
+ }
+
+ if ((Get.IsDummy || Set.IsDummy)
+ && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
+ Report.Error (276, Location,
+ "'{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor.",
+ GetSignatureForError ());
+ return false;
+ }
+
+ if (MemberType.IsAbstract && MemberType.IsSealed) {
+ Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
+ return false;
+ }
+
+ ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
+ return true;
+ }
+
+ public override string GetSignatureForError()
+ {
+ if (PropertyBuilder == null)
+ return GetSignatureForError (Parent);
+
+ return TypeManager.CSharpSignature (PropertyBuilder, false);
+ }
+
+
+ protected override bool CheckForDuplications ()
+ {
+ ArrayList ar = Parent.Indexers;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Indexer m = (Indexer) ar [i];
+ if (IsDuplicateImplementation (m))
+ return false;
+ }
+ }
+
+ ar = Parent.Properties;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Property m = (Property) ar [i];
+ if (IsDuplicateImplementation (m))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // TODO: rename to Resolve......
+ protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
+ {
+ PropertyInfo parent_property = container.ParentCache.FindMemberToOverride (
+ container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
+
+ if (parent_property == null)
+ return null;
+
+ parent_ret_type = parent_property.PropertyType;
+ MethodInfo get_accessor = parent_property.GetGetMethod (true);
+ MethodInfo set_accessor = parent_property.GetSetMethod (true);
+ MethodAttributes get_accessor_access, set_accessor_access;
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+ if (Get != null && !Get.IsDummy && get_accessor == null) {
+ Report.SymbolRelatedToPreviousError (parent_property);
+ Report.Error (545, Location, "'{0}': cannot override because '{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
+ }
+
+ if (Set != null && !Set.IsDummy && set_accessor == null) {
+ Report.SymbolRelatedToPreviousError (parent_property);
+ Report.Error (546, Location, "'{0}': cannot override because '{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
+ }
+ }
+
+ //
+ // Check parent accessors access
+ //
+ get_accessor_access = set_accessor_access = 0;
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ if (get_accessor != null) {
+ MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
+ get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
+
+ if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
+ Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
+ GetSignatureForError (), TypeManager.GetFullNameSignature (parent_property));
+ }
+
+ if (set_accessor != null) {
+ MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
+ set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
+
+ if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
+ Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
+ GetSignatureForError (container), TypeManager.GetFullNameSignature (parent_property));
+ }
+ }
+
+ //
+ // Get the less restrictive access
+ //
+ return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
+ }
+
+ public override void Emit ()
+ {
+ //
+ // 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 && OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ if (!Get.IsDummy)
+ Get.Emit (Parent);
+
+ if (!Set.IsDummy)
+ Set.Emit (Parent);
+
+ base.Emit ();
+ }
+
+ /// <summary>
+ /// Tests whether accessors are not in collision with some method (CS0111)
+ /// </summary>
+ public bool AreAccessorsDuplicateImplementation (MethodCore mc)
+ {
+ return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
+ }
+
+ protected override void UpdateMemberName ()
+ {
+ base.UpdateMemberName ();
+
+ Get.UpdateName (this);
+ Set.UpdateName (this);
+ }
+
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "P:"; }
+ }
+ }
+
+ public class Property : PropertyBase, IIteratorContainer {
+ 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.METHOD_YIELDS |
+ Modifiers.VIRTUAL;
+
+ const int AllowedInterfaceModifiers =
+ Modifiers.NEW;
+
+ public Property (TypeContainer parent, Expression type, int mod_flags,
+ bool is_iface, MemberName name, Attributes attrs,
+ Accessor get_block, Accessor set_block, Location loc)
+ : base (parent, type, mod_flags,
+ is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
+ is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
+ loc)
+ {
+ if (get_block == null)
+ Get = new GetMethod (this);
+ else
+ Get = new GetMethod (this, get_block);
+
+ if (set_block == null)
+ Set = new SetMethod (this);
+ else
+ Set = new SetMethod (this, set_block);
+ }
+
+ public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
+ MemberName name, Attributes attrs, Parameters get_params, Accessor get_block,
+ Parameters set_params, Accessor set_block, Location loc)
+ : base (ds, type, mod,
+ is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
+ is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
+ loc)
+ {
+ if (get_block == null)
+ Get = new GetMethod (this, get_params);
+ else
+ Get = new GetMethod (this, get_block, get_params);
+
+ if (set_block == null)
+ Set = new SetMethod (this, set_params);
+ else
+ Set = new SetMethod (this, set_block, set_params);
+ }
+
+ public override bool Define ()
+ {
+ if (!DoDefineBase ())
+ return false;
+
+ if (!base.Define ())
+ return false;
+
+ if (!CheckBase ())
+ return false;
+
+ flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
+
+ if (!Get.IsDummy) {
+
+ GetBuilder = Get.Define (Parent);
+ if (GetBuilder == null)
+ return false;
+
+ //
+ // Setup iterator if we are one
+ //
+ if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
+ Iterator iterator = new Iterator (
+ Parent, "get", MemberType,
+ TypeManager.NoTypes, Get.ParameterInfo,
+ ModFlags, Get.Block, Location);
+
+ if (!iterator.DefineIterator ())
+ return false;
+ Get.Block = iterator.Block;
+ }
+ }
+
+ if (!Set.IsDummy) {
+ SetBuilder = Set.Define (Parent);
+ if (SetBuilder == null)
+ return false;
+
+ SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
+ }
+
+ // FIXME - PropertyAttributes.HasDefault ?
+
+ PropertyAttributes prop_attr = PropertyAttributes.None;
+ if (!IsInterface)
+ prop_attr |= PropertyAttributes.RTSpecialName |
+ PropertyAttributes.SpecialName;
+
+ PropertyBuilder = Parent.TypeBuilder.DefineProperty (
+ Name, prop_attr, MemberType, null);
+
+ if (!Get.IsDummy)
+ PropertyBuilder.SetGetMethod (GetBuilder);
+
+ if (!Set.IsDummy)
+ PropertyBuilder.SetSetMethod (SetBuilder);
+
+ TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
+ return true;
+ }
+
+ public void SetYields ()
+ {
+ ModFlags |= Modifiers.METHOD_YIELDS;
+ }
+ }
+
+ /// </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);
+ }
+ }
+
+ /// <summary>
+ /// For case when event is declared like property (with add and remove accessors).
+ /// </summary>
+ public class EventProperty: Event {
+
+ static string[] attribute_targets = new string [] { "event", "property" };
+
+ public EventProperty (TypeContainer parent, Expression type, int mod_flags,
+ bool is_iface, MemberName name, Object init,
+ Attributes attrs, Accessor add, Accessor remove,
+ Location loc)
+ : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
+ {
+ Add = new AddDelegateMethod (this, add);
+ Remove = new RemoveDelegateMethod (this, remove);
+
+ // For this event syntax we don't report error CS0067
+ // because it is hard to do it.
+ SetAssigned ();
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Event is declared like field.
+ /// </summary>
+ public class EventField: Event {
+
+ static string[] attribute_targets = new string [] { "event", "field", "method" };
+ static string[] attribute_targets_interface = new string[] { "event", "method" };
+
+ public EventField (TypeContainer parent, Expression type, int mod_flags,
+ bool is_iface, MemberName name, Object init,
+ Attributes attrs, Location loc)
+ : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
+ {
+ Add = new AddDelegateMethod (this);
+ Remove = new RemoveDelegateMethod (this);
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Target == AttributeTargets.Field) {
+ FieldBuilder.SetCustomAttribute (cb);
+ return;
+ }
+
+ if (a.Target == AttributeTargets.Method) {
+ Add.ApplyAttributeBuilder (a, cb);
+ Remove.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return IsInterface ? attribute_targets_interface : attribute_targets;
+ }
+ }
+ }
+
+ public abstract class Event : FieldBase {
+
+ protected sealed class AddDelegateMethod: DelegateMethod
+ {
+
+ public AddDelegateMethod (Event method):
+ base (method, "add_")
+ {
+ }
+
+ public AddDelegateMethod (Event method, Accessor accessor):
+ base (method, accessor, "add_")
+ {
+ }
+
+ protected override MethodInfo DelegateMethodInfo {
+ get {
+ return TypeManager.delegate_combine_delegate_delegate;
+ }
+ }
+
+ }
+
+ protected sealed class RemoveDelegateMethod: DelegateMethod
+ {
+ public RemoveDelegateMethod (Event method):
+ base (method, "remove_")
+ {
+ }
+
+ public RemoveDelegateMethod (Event method, Accessor accessor):
+ base (method, accessor, "remove_")
+ {
+ }
+
+ protected override MethodInfo DelegateMethodInfo {
+ get {
+ return TypeManager.delegate_remove_delegate_delegate;
+ }
+ }
+
+ }
+
+ public abstract class DelegateMethod: AbstractPropertyEventMethod
+ {
+ protected readonly Event method;
+ ImplicitParameter param_attr;
+
+ static string[] attribute_targets = new string [] { "method", "param", "return" };
+
+ public DelegateMethod (Event method, string prefix)
+ : base (method, prefix)
+ {
+ this.method = method;
+ }
+
+ public DelegateMethod (Event method, Accessor accessor, string prefix)
+ : base (method, accessor, prefix)
+ {
+ this.method = method;
+ }
+
+ protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Target == AttributeTargets.Parameter) {
+ if (param_attr == null)
+ param_attr = new ImplicitParameter (method_data.MethodBuilder);
+
+ param_attr.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return method.IsClsCompliaceRequired (ds);
+ }
+
+ public MethodBuilder Define (TypeContainer container, InternalParameters ip)
+ {
+ method_data = new MethodData (method, ip, method.ModFlags,
+ method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
+
+ if (!method_data.Define (container))
+ return null;
+
+ MethodBuilder mb = method_data.MethodBuilder;
+ mb.DefineParameter (1, ParameterAttributes.None, "value");
+ return mb;
+ }
+
+
+ public override void Emit (TypeContainer tc)
+ {
+ if (block != null) {
+ base.Emit (tc);
+ return;
+ }
+
+ ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
+ EmitContext ec = CreateEmitContext (tc, ig);
+ FieldInfo field_info = (FieldInfo)method.FieldBuilder;
+
+ method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
+ if ((method.ModFlags & Modifiers.STATIC) != 0) {
+ ig.Emit (OpCodes.Ldsfld, field_info);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, DelegateMethodInfo);
+ ig.Emit (OpCodes.Castclass, method.MemberType);
+ ig.Emit (OpCodes.Stsfld, field_info);
+ } else {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, field_info);
+ ig.Emit (OpCodes.Ldarg_1);
+ ig.Emit (OpCodes.Call, DelegateMethodInfo);
+ ig.Emit (OpCodes.Castclass, method.MemberType);
+ ig.Emit (OpCodes.Stfld, field_info);
+ }
+ ig.Emit (OpCodes.Ret);
+ }
+
+ protected abstract MethodInfo DelegateMethodInfo { get; }
+
+ public override Type[] ParameterTypes {
+ get {
+ return new Type[] { method.MemberType };
+ }
+ }
+
+ public override Type ReturnType {
+ get {
+ return TypeManager.void_type;
+ }
+ }
+
+ public override EmitContext CreateEmitContext (TypeContainer tc,
+ ILGenerator ig)
+ {
+ return new EmitContext (
+ tc, method.Parent, Location, ig, ReturnType,
+ method.ModFlags, false);
+ }
+
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', method.Name);
+ }
+
+ public override ObsoleteAttribute GetObsoleteAttribute ()
+ {
+ return method.GetObsoleteAttribute (method.Parent);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+
+ 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;
+
+ const int AllowedInterfaceModifiers =
+ Modifiers.NEW;
+
+ public DelegateMethod Add, Remove;
+ public MyEventBuilder EventBuilder;
+ public MethodBuilder AddBuilder, RemoveBuilder;
+
+ MethodData AddData, RemoveData;
+
+ public Event (TypeContainer parent, Expression type, int mod_flags,
+ bool is_iface, MemberName name, Object init, Attributes attrs,
+ Location loc)
+ : base (parent, type, mod_flags,
+ is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
+ name, init, attrs, loc)
+ {
+ IsInterface = is_iface;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
+ a.Error_InvalidSecurityParent ();
+ return;
+ }
+
+ EventBuilder.SetCustomAttribute (cb);
+ }
+
+ public bool AreAccessorsDuplicateImplementation (MethodCore mc)
+ {
+ return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Event;
+ }
+ }
+
+ public override bool Define ()
+ {
+ EventAttributes e_attr;
+ e_attr = EventAttributes.None;
+
+ if (!DoDefineBase ())
+ return false;
+
+ if (!DoDefine (Parent))
+ return false;
+
+ if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
+ Report.Error (74, Location, "'" + Parent.Name + "." + Name +
+ "': abstract event can not have an initializer");
+ return false;
+ }
+
+ if (!TypeManager.IsDelegateType (MemberType)) {
+ Report.Error (66, Location, "'" + Parent.Name + "." + Name +
+ "' : event must be of a delegate type");
+ return false;
+ }
+
+ EmitContext ec = Parent.EmitContext;
+ if (ec == null)
+ throw new InternalErrorException ("Event.Define called too early?");
+ bool old_unsafe = ec.InUnsafe;
+ ec.InUnsafe = InUnsafe;
+
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
+ Parameters parameters = new Parameters (parms, null, Location);
+ Type [] types = parameters.GetParameterInfo (ec);
+ InternalParameters ip = new InternalParameters (types, parameters);
+
+ ec.InUnsafe = old_unsafe;
+
+ if (!CheckBase ())
+ return false;
+
+ //
+ // Now define the accessors
+ //
+
+ AddBuilder = Add.Define (Parent, ip);
+ if (AddBuilder == null)
+ return false;
+
+ RemoveBuilder = Remove.Define (Parent, ip);
+ if (RemoveBuilder == null)
+ return false;
+
+ EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
+
+ if (Add.Block == null && Remove.Block == null && !IsInterface) {
+ FieldBuilder = Parent.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);
+
+ TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
+ return true;
+ }
+
+ protected override bool CheckBase ()
+ {
+ if (!base.CheckBase ())
+ return false;
+
+ if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
+ if (!(conflict_symbol is EventInfo)) {
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Error (72, Location, "Event '{0}' can override only event", GetSignatureForError (Parent));
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override void Emit ()
+ {
+ if (OptAttributes != null) {
+ EmitContext ec = new EmitContext (
+ Parent, Location, null, MemberType, ModFlags);
+ OptAttributes.Emit (ec, this);
+ }
+
+ if (!IsInterface) {
+ Add.Emit (Parent);
+ Remove.Emit (Parent);
+ }
+
+ base.Emit ();
+ }
+
+ public override string GetSignatureForError ()
+ {
+ if (EventBuilder == null)
+ return base.GetSignatureForError (Parent);
+
+ return TypeManager.GetFullNameSignature (EventBuilder);
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "E:"; }
+ }
+ }
+
+
+ public class Indexer : PropertyBase {
+
+ class GetIndexerMethod: GetMethod
+ {
+ public GetIndexerMethod (MethodCore method):
+ base (method)
+ {
+ }
+
+ public GetIndexerMethod (MethodCore method, Accessor accessor):
+ base (method, accessor)
+ {
+ }
+
+ public override Type[] ParameterTypes {
+ get {
+ return method.ParameterTypes;
+ }
+ }
+ }
+
+ class SetIndexerMethod: SetMethod
+ {
+ readonly Parameters parameters;
+
+ public SetIndexerMethod (MethodCore method):
+ base (method)
+ {
+ }
+
+ public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
+ base (method, accessor)
+ {
+ this.parameters = parameters;
+ }
+
+ public override Type[] ParameterTypes {
+ get {
+ int top = method.ParameterTypes.Length;
+ Type [] set_pars = new Type [top + 1];
+ method.ParameterTypes.CopyTo (set_pars, 0);
+ set_pars [top] = method.MemberType;
+ return set_pars;
+ }
+ }
+
+ protected override InternalParameters GetParameterInfo (EmitContext ec)
+ {
+ Parameter [] fixed_parms = parameters.FixedParameters;
+
+ if (fixed_parms == null){
+ throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.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 (
+ method.Type, "value", Parameter.Modifier.NONE, null);
+
+ Parameters set_formal_params = new Parameters (tmp, null, method.Location);
+ Type [] types = set_formal_params.GetParameterInfo (ec);
+
+ return new InternalParameters (types, set_formal_params);
+ }
+ }
+
+ 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;
+
+ const int AllowedInterfaceModifiers =
+ Modifiers.NEW;
+
+ //
+ // Are we implementing an interface ?
+ //
+ public Indexer (TypeContainer parent, Expression type, MemberName name, int mod,
+ bool is_iface, Parameters parameters, Attributes attrs,
+ Accessor get_block, Accessor set_block, Location loc)
+ : base (parent, type, mod,
+ is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
+ is_iface, name, parameters, attrs, loc)
+ {
+ if (get_block == null)
+ Get = new GetIndexerMethod (this);
+ else
+ Get = new GetIndexerMethod (this, get_block);
+
+ if (set_block == null)
+ Set = new SetIndexerMethod (this);
+ else
+ Set = new SetIndexerMethod (this, parameters, set_block);
+ }
+
+ public override bool Define ()
+ {
+ PropertyAttributes prop_attr =
+ PropertyAttributes.RTSpecialName |
+ PropertyAttributes.SpecialName;
+
+ if (!DoDefineBase ())
+ return false;
+
+ if (!base.Define ())
+ return false;
+
+ if (OptAttributes != null) {
+ Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
+ if (indexer_attr != null) {
+ // Remove the attribute from the list because it is not emitted
+ OptAttributes.Attrs.Remove (indexer_attr);
+
+ ShortName = indexer_attr.GetIndexerAttributeValue (ec);
+
+ if (IsExplicitImpl) {
+ Report.Error (415, indexer_attr.Location,
+ "The 'IndexerName' attribute is valid only on an" +
+ "indexer that is not an explicit interface member declaration");
+ return false;
+ }
+
+ if ((ModFlags & Modifiers.OVERRIDE) != 0) {
+ Report.Error (609, indexer_attr.Location,
+ "Cannot set the 'IndexerName' attribute on an indexer marked override");
+ return false;
+ }
+
+// if (!Tokenizer.IsValidIdentifier (ShortName)) {
+// Report.Error (633, indexer_attr.Location,
+// "The argument to the 'IndexerName' attribute must be a valid identifier");
+// return false;
+// }
+
+ UpdateMemberName ();
+ }
+ }
+
+ if (InterfaceType != null) {
+ string parent_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
+ if (parent_IndexerName != Name)
+ ShortName = parent_IndexerName;
+ UpdateMemberName ();
+ }
+
+ if (!Parent.AddToMemberContainer (this, true) ||
+ !Parent.AddToMemberContainer (Get, true) || !Parent.AddToMemberContainer (Set, true))
+ return false;
+
+ if (!CheckBase ())
+ return false;
+
+ flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
+ if (!Get.IsDummy){
+ GetBuilder = Get.Define (Parent);
+ if (GetBuilder == null)
+ return false;
+ }
+
+ if (!Set.IsDummy){
+ SetBuilder = Set.Define (Parent);
+ if (SetBuilder == null)
+ return false;
+ }
+
+ //
+ // Now name the parameters
+ //
+ Parameter [] p = Parameters.FixedParameters;
+ if (p != null) {
+ if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
+ Report.Error (631, Location, "ref and out are not valid in this context");
+ return false;
+ }
+
+ int i;
+
+ for (i = 0; i < p.Length; ++i) {
+ if (!Get.IsDummy)
+ GetBuilder.DefineParameter (
+ i + 1, p [i].Attributes, p [i].Name);
+
+ if (!Set.IsDummy)
+ SetBuilder.DefineParameter (
+ i + 1, p [i].Attributes, p [i].Name);
+ }
+
+ if (!Set.IsDummy)
+ 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);
+ }
+ }
+
+ PropertyBuilder = Parent.TypeBuilder.DefineProperty (
+ Name, prop_attr, MemberType, ParameterTypes);
+
+ if (!Get.IsDummy)
+ PropertyBuilder.SetGetMethod (GetBuilder);
+
+ if (!Set.IsDummy)
+ PropertyBuilder.SetSetMethod (SetBuilder);
+
+ TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
+
+ return true;
+ }
+
+ public override string GetSignatureForError ()
+ {
+ if (PropertyBuilder == null)
+ return GetSignatureForError (Parent);
+
+ return TypeManager.CSharpSignature (PropertyBuilder, true);
+ }
+
+ public override string GetSignatureForError(TypeContainer tc)
+ {
+ return String.Concat (tc.Name, ".this[", Parameters.FixedParameters [0].TypeName.ToString (), ']');
+ }
+ }
+
+ public class Operator : MethodCore, IIteratorContainer {
+
+ const int AllowedModifiers =
+ Modifiers.PUBLIC |
+ Modifiers.UNSAFE |
+ Modifiers.EXTERN |
+ 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 MethodBuilder OperatorMethodBuilder;
+
+ public Method OperatorMethod;
+
+ static string[] attribute_targets = new string [] { "method", "return" };
+
+ public Operator (TypeContainer parent, OpType type, Expression ret_type,
+ int mod_flags, Parameters parameters,
+ ToplevelBlock block, Attributes attrs, Location loc)
+ : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
+ new MemberName ("op_" + type), attrs, parameters, loc)
+ {
+ OperatorType = type;
+ Block = block;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ OperatorMethod.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method;
+ }
+ }
+
+ protected override bool CheckGenericOverride (MethodInfo method, string name)
+ {
+ return true;
+ }
+
+ protected override bool CheckForDuplications()
+ {
+ ArrayList ar = Parent.Operators;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Operator o = (Operator) ar [i];
+ if (IsDuplicateImplementation (o))
+ return false;
+ }
+ }
+
+ ar = Parent.Methods;
+ if (ar != null) {
+ int arLen = ar.Count;
+
+ for (int i = 0; i < arLen; i++) {
+ Method m = (Method) ar [i];
+ if (IsDuplicateImplementation (m))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override bool Define ()
+ {
+ const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
+ if ((ModFlags & RequiredModifiers) != RequiredModifiers){
+ Report.Error (558, Location, "User defined operators '{0}' must be declared static and public", GetSignatureForError (Parent));
+ return false;
+ }
+
+ if (!DoDefine (ds))
+ return false;
+
+ OperatorMethod = new Method (
+ Parent, null, Type, ModFlags, false, MemberName,
+ Parameters, OptAttributes, Location);
+
+ OperatorMethod.Block = Block;
+ OperatorMethod.IsOperator = true;
+ OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+ OperatorMethod.Define ();
+
+ if (OperatorMethod.MethodBuilder == null)
+ return false;
+
+ OperatorMethodBuilder = OperatorMethod.MethodBuilder;
+
+ parameter_types = OperatorMethod.ParameterTypes;
+ Type declaring_type = OperatorMethod.MethodData.DeclaringType;
+ Type return_type = OperatorMethod.ReturnType;
+ Type first_arg_type = parameter_types [0];
+
+ if (!CheckBase ())
+ return false;
+
+ // 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)){
+ if (declaring_type.IsSubclassOf (return_type)) {
+ Report.Error (553, Location, "'{0}' : user defined conversion to/from base class", GetSignatureForError ());
+ return false;
+ }
+ Report.Error (554, Location, "'{0}' : user defined conversion to/from derived class", GetSignatureForError ());
+ return false;
+ }
+ } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
+ if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
+ Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
+ return false;
+ }
+ } else if (Parameters.FixedParameters.Length == 1) {
+ // Checks for Unary operators
+
+ if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
+ if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
+ Report.Error (448, Location,
+ "The return type for ++ or -- operator must be the containing type or derived from the containing type");
+ return false;
+ }
+ if (first_arg_type != declaring_type){
+ Report.Error (
+ 559, Location, "The parameter type for ++ or -- operator must be the containing type");
+ return false;
+ }
+ }
+
+ 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.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 &&
+ parameter_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 override void Emit ()
+ {
+ //
+ // abstract or extern methods have no bodies
+ //
+ if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
+ return;
+
+ OperatorMethod.Emit ();
+ Block = null;
+ }
+
+ // Operator cannot be override
+ protected override MethodInfo FindOutParentMethod (TypeContainer container, ref Type parent_ret_type)
+ {
+ return 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 GetSignatureForError (TypeContainer tc)
+ {
+ StringBuilder sb = new StringBuilder ();
+ sb.AppendFormat ("{0}.operator {1} {2}({3}", tc.Name, GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type),
+ Parameters.FixedParameters [0].GetSignatureForError ());
+
+ if (Parameters.FixedParameters.Length > 1) {
+ sb.Append (",");
+ sb.Append (Parameters.FixedParameters [1].GetSignatureForError ());
+ }
+ sb.Append (")");
+ return sb.ToString ();
+ }
+
+ public override string GetSignatureForError ()
+ {
+ return ToString ();
+ }
+
+ public override string ToString ()
+ {
+ if (OperatorMethod == null)
+ return Name;
+
+ Type return_type = OperatorMethod.ReturnType;
+ Type [] param_types = OperatorMethod.ParameterTypes;
+
+ if (Parameters.FixedParameters.Length == 1)
+ 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]);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ public void SetYields ()
+ {
+ ModFlags |= Modifiers.METHOD_YIELDS;
+ }
+ }
+
+ //
+ // 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 = new MemberFilter (MemberSignatureCompare);
+
+ 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;
+ }
+ }
+}
--- /dev/null
+//
+// codegen.cs: The code generator
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2004 Novell, Inc.
+//
+//#define PRODUCTION
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Permissions;
+
+using Mono.Security.Cryptography;
+
+namespace Mono.CSharp {
+
+ /// <summary>
+ /// Code generator class.
+ /// </summary>
+ public class CodeGen {
+ static AppDomain current_domain;
+ static public SymbolWriter SymbolWriter;
+
+ public static AssemblyClass Assembly;
+ public static ModuleClass Module;
+
+ static CodeGen ()
+ {
+ Assembly = new AssemblyClass ();
+ Module = new ModuleClass (RootContext.Unsafe);
+ }
+
+ 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 (string filename)
+ {
+ SymbolWriter = SymbolWriter.GetSymbolWriter (Module.Builder, filename);
+
+ //
+ // If we got an ISymbolWriter instance, initialize it.
+ //
+ if (SymbolWriter == null) {
+ Report.Warning (
+ -18, "Could not find the symbol writer assembly (Mono.CompilerServices.SymbolWriter.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CompilerServices.SymbolWriter directory.");
+ return;
+ }
+ }
+
+ //
+ // Initializes the code generator variables
+ //
+ static public void Init (string name, string output, bool want_debugging_support)
+ {
+ FileName = output;
+ AssemblyName an = Assembly.GetAssemblyName (name, output);
+
+ if (an.KeyPair != null) {
+ // If we are going to strong name our assembly make
+ // sure all its refs are strong named
+ foreach (Assembly a in TypeManager.GetAssemblies ()) {
+ AssemblyName ref_name = a.GetName ();
+ byte [] b = ref_name.GetPublicKeyToken ();
+ if (b == null || b.Length == 0) {
+ Report.Warning (1577, "Assembly generation failed " +
+ "-- Referenced assembly '" +
+ ref_name.Name +
+ "' does not have a strong name.");
+ //Environment.Exit (1);
+ }
+ }
+ }
+
+ current_domain = AppDomain.CurrentDomain;
+
+ try {
+ Assembly.Builder = current_domain.DefineDynamicAssembly (an,
+ AssemblyBuilderAccess.Save, Dirname (name));
+ }
+ catch (ArgumentException) {
+ // specified key may not be exportable outside it's container
+ if (RootContext.StrongNameKeyContainer != null) {
+ Report.Error (1548, "Could not access the key inside the container `" +
+ RootContext.StrongNameKeyContainer + "'.");
+ Environment.Exit (1);
+ }
+ throw;
+ }
+ catch (CryptographicException) {
+ if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
+ Report.Error (1548, "Could not use the specified key to strongname the assembly.");
+ Environment.Exit (1);
+ }
+ throw;
+ }
+
+ //
+ // 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.
+ //
+ Module.Builder = Assembly.Builder.DefineDynamicModule (
+ Basename (name), Basename (output), false);
+
+ if (want_debugging_support)
+ InitializeSymbolWriter (output);
+ }
+
+ static public void Save (string name)
+ {
+ try {
+ Assembly.Builder.Save (Basename (name));
+ }
+ catch (COMException) {
+ if ((RootContext.StrongNameKeyFile == null) || (!RootContext.StrongNameDelaySign))
+ throw;
+
+ // FIXME: it seems Microsoft AssemblyBuilder doesn't like to delay sign assemblies
+ Report.Error (1548, "Couldn't delay-sign the assembly with the '" +
+ RootContext.StrongNameKeyFile +
+ "', Use MCS with the Mono runtime or CSC to compile this assembly.");
+ }
+ catch (System.IO.IOException io) {
+ Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
+ }
+
+ if (SymbolWriter != null)
+ SymbolWriter.WriteSymbolFile ();
+ }
+
+ public static void AddGlobalAttributes (ArrayList attrs)
+ {
+ foreach (Attribute attr in attrs) {
+ if (attr.IsAssemblyAttribute)
+ Assembly.AddAttribute (attr);
+ else if (attr.IsModuleAttribute)
+ Module.AddAttribute (attr);
+ }
+ }
+ }
+
+ //
+ // Provides "local" store across code that can yield: locals
+ // or fields, notice that this should not be used by anonymous
+ // methods to create local storage, those only require
+ // variable mapping.
+ //
+ public class VariableStorage {
+ FieldBuilder fb;
+ LocalBuilder local;
+
+ static int count;
+
+ public VariableStorage (EmitContext ec, Type t)
+ {
+ count++;
+ if (ec.InIterator)
+ fb = ec.CurrentIterator.MapVariable ("s_", count.ToString (), t);
+ else
+ local = ec.ig.DeclareLocal (t);
+ }
+
+ public void EmitThis (ILGenerator ig)
+ {
+ if (fb != null)
+ ig.Emit (OpCodes.Ldarg_0);
+ }
+
+ public void EmitStore (ILGenerator ig)
+ {
+ if (fb == null)
+ ig.Emit (OpCodes.Stloc, local);
+ else
+ ig.Emit (OpCodes.Stfld, fb);
+ }
+
+ public void EmitLoad (ILGenerator ig)
+ {
+ if (fb == null)
+ ig.Emit (OpCodes.Ldloc, local);
+ else
+ ig.Emit (OpCodes.Ldfld, fb);
+ }
+
+ public void EmitLoadAddress (ILGenerator ig)
+ {
+ if (fb == null)
+ ig.Emit (OpCodes.Ldloca, local);
+ else
+ ig.Emit (OpCodes.Ldflda, fb);
+ }
+
+ public void EmitCall (ILGenerator ig, MethodInfo mi)
+ {
+ // FIXME : we should handle a call like tostring
+ // here, where boxing is needed. However, we will
+ // never encounter that with the current usage.
+
+ bool value_type_call;
+ EmitThis (ig);
+ if (fb == null) {
+ value_type_call = local.LocalType.IsValueType;
+
+ if (value_type_call)
+ ig.Emit (OpCodes.Ldloca, local);
+ else
+ ig.Emit (OpCodes.Ldloc, local);
+ } else {
+ value_type_call = fb.FieldType.IsValueType;
+
+ if (value_type_call)
+ ig.Emit (OpCodes.Ldflda, fb);
+ else
+ ig.Emit (OpCodes.Ldfld, fb);
+ }
+
+ ig.Emit (value_type_call ? OpCodes.Call : OpCodes.Callvirt, mi);
+ }
+ }
+
+ /// <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 inside an iterator block.
+ /// </summary>
+ public bool InIterator;
+
+ public bool IsLastStatement;
+
+ /// <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 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 AnonymousMethod CurrentAnonymousMethod;
+
+ /// <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;
+
+ /// <summary>
+ /// Anonymous methods can capture local variables and fields,
+ /// this object tracks it. It is copied from the TopLevelBlock
+ /// field.
+ /// </summary>
+ public CaptureContext capture_context;
+
+ /// <summary>
+ /// Trace when method is called and is obsolete then this member suppress message
+ /// when call is inside next [Obsolete] method or type.
+ /// </summary>
+ public bool TestObsoleteMethodUsage = true;
+
+ /// <summary>
+ /// The current iterator
+ /// </summary>
+ public Iterator CurrentIterator;
+
+ /// <summary>
+ /// Whether we are in the resolving stage or not
+ /// </summary>
+ enum Phase {
+ Created,
+ Resolving,
+ Emitting
+ }
+
+ Phase current_phase;
+
+ FlowBranching current_flow_branching;
+
+ 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;
+ current_phase = Phase.Created;
+
+ 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;
+
+ 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 current_flow_branching;
+ }
+ }
+
+ public bool HaveCaptureInfo {
+ get {
+ return capture_context != null;
+ }
+ }
+
+ // <summary>
+ // Starts a new code branching. This inherits the state of all local
+ // variables and parameters from the current branching.
+ // </summary>
+ public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
+ {
+ current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc);
+ return current_flow_branching;
+ }
+
+ // <summary>
+ // Starts a new code branching for block `block'.
+ // </summary>
+ public FlowBranching StartFlowBranching (Block block)
+ {
+ FlowBranching.BranchingType type;
+
+ if (CurrentBranching.Type == FlowBranching.BranchingType.Switch)
+ type = FlowBranching.BranchingType.SwitchSection;
+ else
+ type = FlowBranching.BranchingType.Block;
+
+ current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, block, block.StartLocation);
+ return current_flow_branching;
+ }
+
+ public FlowBranchingException StartFlowBranching (ExceptionStatement stmt)
+ {
+ FlowBranchingException branching = new FlowBranchingException (
+ CurrentBranching, stmt);
+ current_flow_branching = branching;
+ return branching;
+ }
+
+ // <summary>
+ // Ends a code branching. Merges the state of locals and parameters
+ // from all the children of the ending branching.
+ // </summary>
+ public FlowBranching.UsageVector DoEndFlowBranching ()
+ {
+ FlowBranching old = current_flow_branching;
+ current_flow_branching = current_flow_branching.Parent;
+
+ return current_flow_branching.MergeChild (old);
+ }
+
+ // <summary>
+ // Ends a code branching. Merges the state of locals and parameters
+ // from all the children of the ending branching.
+ // </summary>
+ public FlowBranching.Reachability EndFlowBranching ()
+ {
+ FlowBranching.UsageVector vector = DoEndFlowBranching ();
+
+ return vector.Reachability;
+ }
+
+ // <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 ()
+ {
+ current_flow_branching = current_flow_branching.Parent;
+ }
+
+ public void CaptureVariable (LocalInfo li)
+ {
+ capture_context.AddLocal (CurrentAnonymousMethod, li);
+ li.IsCaptured = true;
+ }
+
+ public void CaptureParameter (string name, Type t, int idx)
+ {
+
+ capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
+ }
+
+ //
+ // Use to register a field as captured
+ //
+ public void CaptureField (FieldExpr fe)
+ {
+ capture_context.AddField (fe);
+ }
+
+ //
+ // Whether anonymous methods have captured variables
+ //
+ public bool HaveCapturedVariables ()
+ {
+ if (capture_context != null)
+ return capture_context.HaveCapturedVariables;
+ return false;
+ }
+
+ //
+ // Whether anonymous methods have captured fields or this.
+ //
+ public bool HaveCapturedFields ()
+ {
+ if (capture_context != null)
+ return capture_context.HaveCapturedFields;
+ return false;
+ }
+
+ //
+ // Emits the instance pointer for the host method
+ //
+ public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
+ {
+ if (capture_context != null)
+ capture_context.EmitMethodHostInstance (target, am);
+ else if (IsStatic)
+ target.ig.Emit (OpCodes.Ldnull);
+ else
+ target.ig.Emit (OpCodes.Ldarg_0);
+ }
+
+ //
+ // Returns whether the `local' variable has been captured by an anonymous
+ // method
+ //
+ public bool IsCaptured (LocalInfo local)
+ {
+ return capture_context.IsCaptured (local);
+ }
+
+ public bool IsParameterCaptured (string name)
+ {
+ if (capture_context != null)
+ return capture_context.IsParameterCaptured (name);
+ return false;
+ }
+
+ public void EmitMeta (ToplevelBlock b, InternalParameters ip)
+ {
+ if (capture_context != null)
+ capture_context.EmitHelperClasses (this);
+ b.EmitMeta (this);
+
+ if (HasReturnLabel)
+ ReturnLabel = ig.DefineLabel ();
+ }
+
+ public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc)
+ {
+ EmitTopBlock (block, ip, loc, "");
+ }
+
+ //
+ // Here until we can fix the problem with Mono.CSharp.Switch, which
+ // currently can not cope with ig == null during resolve (which must
+ // be fixed for switch statements to work on anonymous methods).
+ //
+ public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc, string methodName)
+ {
+ if (block == null)
+ return;
+
+ bool unreachable;
+
+ if (ResolveTopBlock (null, block, ip, loc, out unreachable)){
+ EmitMeta (block, ip);
+
+ current_phase = Phase.Emitting;
+ EmitResolvedTopBlock (block, unreachable);
+ }
+ }
+
+ public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
+ InternalParameters ip, Location loc, out bool unreachable)
+ {
+ current_phase = Phase.Resolving;
+
+ unreachable = false;
+
+ capture_context = block.CaptureContext;
+
+ if (!Location.IsNull (loc))
+ CurrentFile = loc.File;
+
+#if PRODUCTION
+ try {
+#endif
+ int errors = Report.Errors;
+
+ block.ResolveMeta (block, this, ip);
+
+
+ if (Report.Errors == errors){
+ bool old_do_flow_analysis = DoFlowAnalysis;
+ DoFlowAnalysis = true;
+
+ if (anonymous_method_host != null)
+ current_flow_branching = FlowBranching.CreateBranching (
+ anonymous_method_host.CurrentBranching, FlowBranching.BranchingType.Block,
+ block, loc);
+ else
+ current_flow_branching = FlowBranching.CreateBranching (
+ null, FlowBranching.BranchingType.Block, block, loc);
+
+ if (!block.Resolve (this)) {
+ current_flow_branching = null;
+ DoFlowAnalysis = old_do_flow_analysis;
+ return false;
+ }
+
+ FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
+ current_flow_branching = null;
+
+ DoFlowAnalysis = old_do_flow_analysis;
+
+ if (reachability.AlwaysReturns ||
+ reachability.AlwaysThrows ||
+ reachability.IsUnreachable)
+ unreachable = true;
+ }
+#if PRODUCTION
+ } catch (Exception e) {
+ 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);
+ }
+ Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
+ throw;
+ }
+#endif
+
+ if (ReturnType != null && !unreachable){
+ if (!InIterator){
+ if (CurrentAnonymousMethod != null){
+ Report.Error (1643, loc, "Not all code paths return a value in anonymous method of type `{0}'",
+ CurrentAnonymousMethod.Type);
+ } else {
+ Report.Error (161, loc, "Not all code paths return a value");
+ }
+
+ return false;
+ }
+ }
+ block.CompleteContexts ();
+
+ return true;
+ }
+
+ public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
+ {
+ if (block != null)
+ block.Emit (this);
+
+ if (HasReturnLabel)
+ ig.MarkLabel (ReturnLabel);
+
+ if (return_value != null){
+ ig.Emit (OpCodes.Ldloc, return_value);
+ ig.Emit (OpCodes.Ret);
+ } else {
+ //
+ // If `HasReturnLabel' is set, then we already emitted a
+ // jump to the end of the method, so we must emit a `ret'
+ // there.
+ //
+ // 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, we're always creating a return label in
+ // this case.
+ //
+
+ if ((block != null) && block.IsDestructor) {
+ // Nothing to do; S.R.E automatically emits a leave.
+ } else if (HasReturnLabel || (!unreachable && !InIterator)) {
+ if (ReturnType != null)
+ ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
+ ig.Emit (OpCodes.Ret);
+ }
+ }
+
+ //
+ // Close pending helper classes if we are the toplevel
+ //
+ if (capture_context != null && capture_context.ParentToplevel == null)
+ capture_context.CloseHelperClasses ();
+ }
+
+ /// <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;
+
+ CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, 0);
+ }
+
+ public void DefineLocalVariable (string name, LocalBuilder builder)
+ {
+ if (CodeGen.SymbolWriter == null)
+ return;
+
+ CodeGen.SymbolWriter.DefineLocalVariable (name, builder);
+ }
+
+ /// <summary>
+ /// Returns a temporary storage for a variable of type t as
+ /// a local variable in the current body.
+ /// </summary>
+ public LocalBuilder GetTemporaryLocal (Type t)
+ {
+ LocalBuilder location = null;
+
+ if (temporary_storage != null){
+ object o = temporary_storage [t];
+ if (o != null){
+ if (o is ArrayList){
+ ArrayList al = (ArrayList) o;
+
+ for (int i = 0; i < al.Count; i++){
+ if (al [i] != null){
+ location = (LocalBuilder) al [i];
+ al [i] = null;
+ break;
+ }
+ }
+ } else
+ location = (LocalBuilder) o;
+ if (location != null)
+ return location;
+ }
+ }
+
+ return ig.DeclareLocal (t);
+ }
+
+ public void FreeTemporaryLocal (LocalBuilder b, Type t)
+ {
+ if (temporary_storage == null){
+ temporary_storage = new Hashtable ();
+ temporary_storage [t] = b;
+ return;
+ }
+ object o = temporary_storage [t];
+ if (o == null){
+ temporary_storage [t] = b;
+ return;
+ }
+ if (o is ArrayList){
+ ArrayList al = (ArrayList) o;
+ for (int i = 0; i < al.Count; i++){
+ if (al [i] == null){
+ al [i] = b;
+ return;
+ }
+ }
+ al.Add (b);
+ return;
+ }
+ ArrayList replacement = new ArrayList ();
+ replacement.Add (o);
+ temporary_storage.Remove (t);
+ temporary_storage [t] = replacement;
+ }
+
+ /// <summary>
+ /// Current loop begin and end labels.
+ /// </summary>
+ public Label LoopBegin, LoopEnd;
+
+ /// <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.
+ ///
+ /// This method is typically invoked from the Emit phase, so
+ /// we allow the creation of a return label if it was not
+ /// requested during the resolution phase. Could be cleaned
+ /// up, but it would replicate a lot of logic in the Emit phase
+ /// of the code that uses it.
+ /// </summary>
+ public LocalBuilder TemporaryReturn ()
+ {
+ if (return_value == null){
+ return_value = ig.DeclareLocal (ReturnType);
+ if (!HasReturnLabel){
+ ReturnLabel = ig.DefineLabel ();
+ HasReturnLabel = true;
+ }
+ }
+
+ return return_value;
+ }
+
+ /// <summary>
+ /// This method is used during the Resolution phase to flag the
+ /// need to define the ReturnLabel
+ /// </summary>
+ public void NeedReturnLabel ()
+ {
+ if (current_phase != Phase.Resolving){
+ //
+ // The reason is that the `ReturnLabel' is declared between
+ // resolution and emission
+ //
+ throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");
+ }
+
+ if (!InIterator && !HasReturnLabel)
+ HasReturnLabel = true;
+ }
+
+ //
+ // Creates a field `name' with the type `t' on the proxy class
+ //
+ public FieldBuilder MapVariable (string name, Type t)
+ {
+ if (InIterator)
+ return CurrentIterator.MapVariable ("v_", name, t);
+
+ throw new Exception ("MapVariable for an unknown state");
+ }
+
+ public Expression RemapParameter (int idx)
+ {
+ FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolve (this);
+ }
+
+ public Expression RemapParameterLValue (int idx, Expression right_side)
+ {
+ FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
+ fe.InstanceExpression = new ProxyInstance ();
+ return fe.DoResolveLValue (this, right_side);
+ }
+
+ //
+ // 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 (InIterator){
+ if (!IsStatic){
+ FieldBuilder this_field = CurrentIterator.this_field.FieldBuilder;
+ if (TypeManager.IsValueType (this_field.FieldType))
+ ig.Emit (OpCodes.Ldflda, this_field);
+ else
+ ig.Emit (OpCodes.Ldfld, this_field);
+ }
+ } else if (capture_context != null && CurrentAnonymousMethod != null){
+ ScopeInfo si = CurrentAnonymousMethod.Scope;
+ while (si != null){
+ if (si.ParentLink != null)
+ ig.Emit (OpCodes.Ldfld, si.ParentLink);
+ if (si.THIS != null){
+ ig.Emit (OpCodes.Ldfld, si.THIS);
+ break;
+ }
+ si = si.ParentScope;
+ }
+ }
+ }
+
+ //
+ // Emits the code necessary to load the instance required
+ // to access the captured LocalInfo
+ //
+ public void EmitCapturedVariableInstance (LocalInfo li)
+ {
+ if (RemapToProxy){
+ ig.Emit (OpCodes.Ldarg_0);
+ return;
+ }
+
+ if (capture_context == null)
+ throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
+
+ capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
+ }
+
+ public void EmitParameter (string name)
+ {
+ capture_context.EmitParameter (this, name);
+ }
+
+ public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load);
+ }
+
+ public void EmitAddressOfParameter (string name)
+ {
+ capture_context.EmitAddressOfParameter (this, name);
+ }
+
+ 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;
+ }
+ }
+
+
+ public abstract class CommonAssemblyModulClass: Attributable {
+ protected CommonAssemblyModulClass ():
+ base (null)
+ {
+ }
+
+ public void AddAttribute (Attribute attr)
+ {
+ if (OptAttributes == null) {
+ OptAttributes = new Attributes (attr);
+ return;
+ }
+ OptAttributes.AddAttribute (attr);
+ }
+
+ public void AddAttributes (ArrayList attrs)
+ {
+ if (OptAttributes == null) {
+ OptAttributes = new Attributes (attrs);
+ return;
+ }
+ OptAttributes.AddAttributes (attrs);
+ }
+
+ public virtual void Emit (TypeContainer tc)
+ {
+ if (OptAttributes == null)
+ return;
+
+ EmitContext ec = new EmitContext (tc, Mono.CSharp.Location.Null, null, null, 0, false);
+ OptAttributes.Emit (ec, this);
+ }
+
+ protected Attribute GetClsCompliantAttribute ()
+ {
+ if (OptAttributes == null)
+ return null;
+
+ EmitContext temp_ec = new EmitContext (RootContext.Tree.Types, Mono.CSharp.Location.Null, null, null, 0, false);
+ Attribute a = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, temp_ec);
+ if (a != null) {
+ a.Resolve (temp_ec);
+ }
+ return a;
+ }
+ }
+
+ public class AssemblyClass: CommonAssemblyModulClass {
+ // TODO: make it private and move all builder based methods here
+ public AssemblyBuilder Builder;
+
+ bool is_cls_compliant;
+
+ ListDictionary declarative_security;
+
+ static string[] attribute_targets = new string [] { "assembly" };
+
+ public AssemblyClass (): base ()
+ {
+ is_cls_compliant = false;
+ }
+
+ public bool IsClsCompliant {
+ get {
+ return is_cls_compliant;
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Assembly;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return is_cls_compliant;
+ }
+
+ public void ResolveClsCompliance ()
+ {
+ Attribute a = GetClsCompliantAttribute ();
+ if (a == null)
+ return;
+
+ is_cls_compliant = a.GetClsCompliantAttributeValue (null);
+ }
+
+ // fix bug #56621
+ private void SetPublicKey (AssemblyName an, byte[] strongNameBlob)
+ {
+ try {
+ // check for possible ECMA key
+ if (strongNameBlob.Length == 16) {
+ // will be rejected if not "the" ECMA key
+ an.SetPublicKey (strongNameBlob);
+ }
+ else {
+ // take it, with or without, a private key
+ RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameBlob);
+ // and make sure we only feed the public part to Sys.Ref
+ byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
+
+ // AssemblyName.SetPublicKey requires an additional header
+ byte[] publicKeyHeader = new byte [12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 };
+
+ byte[] encodedPublicKey = new byte [12 + publickey.Length];
+ Buffer.BlockCopy (publicKeyHeader, 0, encodedPublicKey, 0, 12);
+ Buffer.BlockCopy (publickey, 0, encodedPublicKey, 12, publickey.Length);
+ an.SetPublicKey (encodedPublicKey);
+ }
+ }
+ catch (Exception) {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile + "' incorrectly encoded.");
+ Environment.Exit (1);
+ }
+ }
+
+ // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way.
+ public AssemblyName GetAssemblyName (string name, string output)
+ {
+ if (OptAttributes != null) {
+ foreach (Attribute a in OptAttributes.Attrs) {
+ // cannot rely on any resolve-based members before you call Resolve
+ if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly")
+ continue;
+
+ // TODO: This code is buggy: comparing Attribute name without resolving it is wrong.
+ // However, this is invoked by CodeGen.Init, at which time none of the namespaces
+ // are loaded yet.
+ switch (a.Name) {
+ case "AssemblyKeyFile":
+ case "AssemblyKeyFileAttribute":
+ case "System.Reflection.AssemblyKeyFileAttribute":
+ if (RootContext.StrongNameKeyFile != null) {
+ Report.SymbolRelatedToPreviousError (a.Location, a.Name);
+ Report.Warning (1616, "Compiler option '{0}' overrides '{1}' given in source", "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
+ }
+ else {
+ string value = a.GetString ();
+ if (value != String.Empty)
+ RootContext.StrongNameKeyFile = value;
+ }
+ break;
+ case "AssemblyKeyName":
+ case "AssemblyKeyNameAttribute":
+ case "System.Reflection.AssemblyKeyNameAttribute":
+ if (RootContext.StrongNameKeyContainer != null) {
+ Report.SymbolRelatedToPreviousError (a.Location, a.Name);
+ Report.Warning (1616, "keycontainer", "Compiler option '{0}' overrides '{1}' given in source", "System.Reflection.AssemblyKeyNameAttribute");
+ }
+ else {
+ string value = a.GetString ();
+ if (value != String.Empty)
+ RootContext.StrongNameKeyContainer = value;
+ }
+ break;
+ case "AssemblyDelaySign":
+ case "AssemblyDelaySignAttribute":
+ case "System.Reflection.AssemblyDelaySignAttribute":
+ RootContext.StrongNameDelaySign = a.GetBoolean ();
+ break;
+ }
+ }
+ }
+
+ AssemblyName an = new AssemblyName ();
+ an.Name = Path.GetFileNameWithoutExtension (name);
+
+ // note: delay doesn't apply when using a key container
+ if (RootContext.StrongNameKeyContainer != null) {
+ an.KeyPair = new StrongNameKeyPair (RootContext.StrongNameKeyContainer);
+ return an;
+ }
+
+ // strongname is optional
+ if (RootContext.StrongNameKeyFile == null)
+ return an;
+
+ string AssemblyDir = Path.GetDirectoryName (output);
+
+ // the StrongName key file may be relative to (a) the compiled
+ // file or (b) to the output assembly. See bugzilla #55320
+ // http://bugzilla.ximian.com/show_bug.cgi?id=55320
+
+ // (a) relative to the compiled file
+ string filename = Path.GetFullPath (RootContext.StrongNameKeyFile);
+ bool exist = File.Exists (filename);
+ if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) {
+ // (b) relative to the outputed assembly
+ filename = Path.GetFullPath (Path.Combine (AssemblyDir, RootContext.StrongNameKeyFile));
+ exist = File.Exists (filename);
+ }
+
+ if (exist) {
+ using (FileStream fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) {
+ byte[] snkeypair = new byte [fs.Length];
+ fs.Read (snkeypair, 0, snkeypair.Length);
+
+ if (RootContext.StrongNameDelaySign) {
+ // delayed signing - DO NOT include private key
+ SetPublicKey (an, snkeypair);
+ }
+ else {
+ // no delay so we make sure we have the private key
+ try {
+ CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
+ an.KeyPair = new StrongNameKeyPair (snkeypair);
+ }
+ catch (CryptographicException) {
+ if (snkeypair.Length == 16) {
+ // error # is different for ECMA key
+ Report.Error (1606, "Could not strongname the assembly. " +
+ "ECMA key can only be used to delay-sign assemblies");
+ }
+ else {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile +
+ "' doesn't have a private key.");
+ }
+ Environment.Exit (1);
+ }
+ }
+ }
+ }
+ else {
+ Report.Error (1548, "Could not strongname the assembly. File `" +
+ RootContext.StrongNameKeyFile + "' not found.");
+ Environment.Exit (1);
+ }
+ return an;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
+ {
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) {
+ if (declarative_security == null)
+ declarative_security = new ListDictionary ();
+
+ a.ExtractSecurityPermissionSet (declarative_security);
+ return;
+ }
+
+ Builder.SetCustomAttribute (customBuilder);
+ }
+
+ public override void Emit (TypeContainer tc)
+ {
+ base.Emit (tc);
+
+ if (declarative_security != null) {
+
+ MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
+ object builder_instance = Builder;
+
+ try {
+ // Microsoft runtime hacking
+ if (add_permission == null) {
+ Type assembly_builder = typeof (AssemblyBuilder).Assembly.GetType ("System.Reflection.Emit.AssemblyBuilderData");
+ add_permission = assembly_builder.GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
+
+ FieldInfo fi = typeof (AssemblyBuilder).GetField ("m_assemblyData", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
+ builder_instance = fi.GetValue (Builder);
+ }
+
+ object[] args = new object [] { declarative_security [SecurityAction.RequestMinimum],
+ declarative_security [SecurityAction.RequestOptional],
+ declarative_security [SecurityAction.RequestRefuse] };
+ add_permission.Invoke (builder_instance, args);
+ }
+ catch {
+ Report.RuntimeMissingSupport (Location.Null, "assembly permission setting");
+ }
+ }
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+ public class ModuleClass: CommonAssemblyModulClass {
+ // TODO: make it private and move all builder based methods here
+ public ModuleBuilder Builder;
+ bool m_module_is_unsafe;
+
+ static string[] attribute_targets = new string [] { "module" };
+
+ public ModuleClass (bool is_unsafe)
+ {
+ m_module_is_unsafe = is_unsafe;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Module;
+ }
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return CodeGen.Assembly.IsClsCompliant;
+ }
+
+ public override void Emit (TypeContainer tc)
+ {
+ base.Emit (tc);
+
+ if (!m_module_is_unsafe)
+ return;
+
+ if (TypeManager.unverifiable_code_ctor == null) {
+ Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute.");
+ return;
+ }
+
+ ApplyAttributeBuilder (null, new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0]));
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
+ {
+ if (a != null && a.Type == TypeManager.cls_compliant_attribute_type) {
+ Report.Warning (3012, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
+ }
+
+ Builder.SetCustomAttribute (customBuilder);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// const.cs: Constant declarations.
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
+//
+// (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 : FieldMember {
+ public Expression Expr;
+ EmitContext const_ec;
+
+ bool resolved = false;
+ object ConstantValue = null;
+
+ bool in_transit = false;
+
+ public const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE;
+
+ public Const (TypeContainer parent, Expression constant_type, string name,
+ Expression expr, int mod_flags, Attributes attrs, Location loc)
+ : base (parent, constant_type, mod_flags, AllowedModifiers,
+ new MemberName (name), null, attrs, loc)
+ {
+ Expr = expr;
+ ModFlags |= Modifiers.STATIC;
+ }
+
+#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 ()
+ {
+ if (!base.Define ())
+ return false;
+
+ const_ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
+
+ Type ttype = MemberType;
+ while (ttype.IsArray)
+ ttype = TypeManager.GetElementType (ttype);
+
+ if (!TypeManager.IsBuiltinType(ttype) && (!ttype.IsSubclassOf(TypeManager.enum_type)) && !(Expr is NullLiteral)){
+ Report.Error (
+ -3, Location,
+ "Constant type is not valid (only system types are allowed)");
+ return false;
+ }
+
+ FieldAttributes field_attr = FieldAttributes.Static | Modifiers.FieldAttr (ModFlags);
+ // I don't know why but they emit decimal constant as InitOnly
+ if (ttype == TypeManager.decimal_type) {
+ field_attr |= FieldAttributes.InitOnly;
+ }
+ else {
+ field_attr |= FieldAttributes.Literal;
+ }
+
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType, field_attr);
+
+ TypeManager.RegisterConstant (FieldBuilder, this);
+
+ return true;
+ }
+
+ //
+ // Changes the type of the constant expression `expr' to the Type `type'
+ // Returns null on failure.
+ //
+ public static Constant ChangeType (Location loc, Constant expr, Type type)
+ {
+ if (type == TypeManager.object_type)
+ return expr;
+
+ bool fail;
+
+ // from the null type to any reference-type.
+ if (expr.Type == TypeManager.null_type && !type.IsValueType && !TypeManager.IsEnumType (type))
+ return NullLiteral.Null;
+
+ if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, expr, type)){
+ Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
+ return null;
+ }
+
+ // Special-case: The 0 literal can be converted to an enum value,
+ // and ImplicitStandardConversionExists will return true in that case.
+ if (expr.Type == TypeManager.int32_type && TypeManager.IsEnumType (type)){
+ if (expr is IntLiteral && ((IntLiteral) expr).Value == 0)
+ return new EnumConstant (expr, type);
+ }
+
+ object constant_value = TypeManager.ChangeType (expr.GetValue (), type, out fail);
+ if (fail){
+ Convert.Error_CannotImplicitConversion (loc, expr.Type, type);
+
+ //
+ // We should always catch the error before this is ever
+ // reached, by calling Convert.ImplicitStandardConversionExists
+ //
+ throw new Exception (
+ String.Format ("LookupConstantValue: This should never be reached {0} {1}", expr.Type, type));
+ }
+
+ Constant retval;
+ if (type == TypeManager.int32_type)
+ retval = new IntConstant ((int) constant_value);
+ else if (type == TypeManager.uint32_type)
+ retval = new UIntConstant ((uint) constant_value);
+ else if (type == TypeManager.int64_type)
+ retval = new LongConstant ((long) constant_value);
+ else if (type == TypeManager.uint64_type)
+ retval = new ULongConstant ((ulong) constant_value);
+ else if (type == TypeManager.float_type)
+ retval = new FloatConstant ((float) constant_value);
+ else if (type == TypeManager.double_type)
+ retval = new DoubleConstant ((double) constant_value);
+ else if (type == TypeManager.string_type)
+ retval = new StringConstant ((string) constant_value);
+ else if (type == TypeManager.short_type)
+ retval = new ShortConstant ((short) constant_value);
+ else if (type == TypeManager.ushort_type)
+ retval = new UShortConstant ((ushort) constant_value);
+ else if (type == TypeManager.sbyte_type)
+ retval = new SByteConstant ((sbyte) constant_value);
+ else if (type == TypeManager.byte_type)
+ retval = new ByteConstant ((byte) constant_value);
+ else if (type == TypeManager.char_type)
+ retval = new CharConstant ((char) constant_value);
+ else if (type == TypeManager.bool_type)
+ retval = new BoolConstant ((bool) constant_value);
+ else if (type == TypeManager.decimal_type)
+ retval = new DecimalConstant ((decimal) constant_value);
+ else
+ throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
+
+ return retval;
+ }
+
+ /// <summary>
+ /// Looks up the value of a constant field. Defines it if it hasn't
+ /// already been. Similar to LookupEnumValue in spirit.
+ /// </summary>
+ public bool LookupConstantValue (out object value)
+ {
+ if (resolved) {
+ value = ConstantValue;
+ return true;
+ }
+
+ if (in_transit) {
+ Report.Error (110, Location,
+ "The evaluation of the constant value for `" +
+ Name + "' involves a circular definition.");
+ value = null;
+ return false;
+ }
+
+ in_transit = true;
+ int errors = Report.Errors;
+
+ //
+ // We might have cleared Expr ourselves in a recursive definition
+ //
+ if (Expr == null){
+ value = null;
+ return false;
+ }
+
+ Expr = Expr.Resolve (const_ec);
+
+ in_transit = false;
+
+ if (Expr == null) {
+ if (errors == Report.Errors)
+ Report.Error (150, Location, "A constant value is expected");
+ value = null;
+ return false;
+ }
+
+ Expression real_expr = Expr;
+
+ Constant ce = Expr as Constant;
+ if (ce == null){
+ UnCheckedExpr un_expr = Expr as UnCheckedExpr;
+ CheckedExpr ch_expr = Expr as CheckedExpr;
+ EmptyCast ec_expr = Expr as EmptyCast;
+
+ 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 ((ec_expr != null) && (ec_expr.Child is Constant))
+ Expr = ec_expr.Child;
+ else if (Expr is ArrayCreation){
+ Report.Error (133, Location, "Arrays can not be constant");
+ } else {
+ if (errors == Report.Errors)
+ Report.Error (150, Location, "A constant value is expected");
+ value = null;
+ return false;
+ }
+
+ ce = Expr as Constant;
+ }
+
+ if (MemberType != real_expr.Type) {
+ ce = ChangeType (Location, ce, MemberType);
+ if (ce == null){
+ value = null;
+ return false;
+ }
+ Expr = ce;
+ }
+ ConstantValue = ce.GetValue ();
+
+ if (MemberType.IsEnum){
+ //
+ // This sadly does not work for our user-defined enumerations types ;-(
+ //
+ try {
+ ConstantValue = System.Enum.ToObject (
+ MemberType, ConstantValue);
+ } catch (ArgumentException){
+ Report.Error (
+ -16, Location,
+ ".NET SDK 1.0 does not permit to create the constant "+
+ " field from a user-defined enumeration");
+ }
+ }
+
+ if (ce is DecimalConstant) {
+ Decimal d = ((DecimalConstant)ce).Value;
+ int[] bits = Decimal.GetBits (d);
+ object[] args = new object[] { (byte)(bits [3] >> 16), (byte)(bits [3] >> 31), (uint)bits [2], (uint)bits [1], (uint)bits [0] };
+ CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.decimal_constant_attribute_ctor, args);
+ FieldBuilder.SetCustomAttribute (cab);
+ }
+ else{
+ FieldBuilder.SetConstant (ConstantValue);
+ }
+
+ if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
+ throw new Exception ("Cannot register const value");
+
+ value = ConstantValue;
+ resolved = true;
+ return true;
+ }
+
+
+ /// <summary>
+ /// Emits the field value by evaluating the expression
+ /// </summary>
+ public override void Emit ()
+ {
+ object value;
+ LookupConstantValue (out value);
+
+ if (OptAttributes != null) {
+ OptAttributes.Emit (const_ec, this);
+ }
+
+ base.Emit ();
+ }
+ }
+}
+
+
--- /dev/null
+//
+// 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 DecimalConstant ToDecimal (Location loc)
+ {
+ DecimalConstant c = ConvertToDecimal ();
+
+ if (c == null)
+ Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
+
+ return c;
+ }
+
+ public virtual DecimalConstant ConvertToDecimal ()
+ {
+ return null;
+ }
+
+ 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 abstract bool IsNegative {
+ get;
+ }
+
+ //
+ // Returns true iff 1) the stack type of this is one of Object,
+ // int32, int64 and 2) this == 0 or this == null.
+ //
+ public virtual bool IsZeroInteger {
+ get { return false; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == false; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == '\0'; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+
+ public override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 DecimalConstant ConvertToDecimal()
+ {
+ return new DecimalConstant (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 override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return Value == 0; }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+ }
+
+ 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 override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+ }
+
+ 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)
+ {
+ ILGenerator ig = ec.ig;
+
+ int [] words = Decimal.GetBits (Value);
+ int power = (words [3] >> 16) & 0xff;
+
+ if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
+ {
+ IntConstant.EmitInt (ig, (int)Value);
+ ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
+ return;
+ }
+
+
+ //
+ // FIXME: we could optimize this, and call a better
+ // constructor
+ //
+
+ 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, power);
+
+ ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
+ }
+
+ public override bool IsNegative {
+ get {
+ return Value < 0;
+ }
+ }
+ }
+
+ 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)
+ {
+ if (Value == null)
+ ec.ig.Emit (OpCodes.Ldnull);
+ else
+ ec.ig.Emit (OpCodes.Ldstr, Value);
+ }
+
+ public override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+ }
+
+}
+
+
--- /dev/null
+//
+// 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 {
+ //
+ // This is used to prettify the code: a null argument is allowed
+ // for ImplicitStandardConversion as long as it is known that
+ // no anonymous method will play a role.
+ //
+ // FIXME: renamed from `const' to `static' to allow bootstraping from older
+ // versions of the compiler that could not cope with this construct.
+ //
+ public static EmitContext ConstantEC = null;
+
+ 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 Expression TypeParameter_to_Null (Expression expr, Type target_type,
+ Location loc)
+ {
+ if (!TypeParameter_to_Null (target_type)) {
+ Report.Error (403, loc, "Cannot convert null to the type " +
+ "parameter `{0}' becaues it could be a value " +
+ "type. Consider using `default ({0})' instead.",
+ target_type);
+ return null;
+ }
+
+ return new NullCast (expr, target_type);
+ }
+
+ static bool TypeParameter_to_Null (Type target_type)
+ {
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (target_type);
+ if (gc == null)
+ return false;
+
+ if (gc.HasReferenceTypeConstraint)
+ return true;
+ if (gc.HasClassConstraint && !TypeManager.IsValueType (gc.ClassConstraint))
+ return true;
+
+ return false;
+ }
+
+ static Type TypeParam_EffectiveBaseType (EmitContext ec, Type t)
+ {
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
+ if (gc == null)
+ return TypeManager.object_type;
+
+ return TypeParam_EffectiveBaseType (ec, gc);
+ }
+
+ static Type TypeParam_EffectiveBaseType (EmitContext ec, GenericConstraints gc)
+ {
+ ArrayList list = new ArrayList ();
+ list.Add (gc.EffectiveBaseClass);
+ foreach (Type t in gc.InterfaceConstraints) {
+ if (!t.IsGenericParameter)
+ continue;
+
+ GenericConstraints new_gc = TypeManager.GetTypeParameterConstraints (t);
+ if (new_gc != null)
+ list.Add (TypeParam_EffectiveBaseType (ec, new_gc));
+ }
+ return FindMostEncompassedType (ec, list);
+ }
+
+ static Expression TypeParameterConversion (Expression expr, bool is_reference, Type target_type)
+ {
+ if (is_reference)
+ return new EmptyCast (expr, target_type);
+ else
+ return new BoxedCast (expr, target_type);
+ }
+
+ static Expression ImplicitTypeParameterConversion (EmitContext ec, Expression expr,
+ Type target_type)
+ {
+ Type expr_type = expr.Type;
+
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (expr_type);
+
+ if (gc == null) {
+ if (target_type == TypeManager.object_type)
+ return new BoxedCast (expr);
+
+ return null;
+ }
+
+ // We're converting from a type parameter which is known to be a reference type.
+ bool is_reference = gc.IsReferenceType;
+ Type base_type = TypeParam_EffectiveBaseType (ec, gc);
+
+ if (TypeManager.IsSubclassOf (base_type, target_type))
+ return TypeParameterConversion (expr, is_reference, target_type);
+
+ if (target_type.IsInterface) {
+ if (TypeManager.ImplementsInterface (base_type, target_type))
+ return TypeParameterConversion (expr, is_reference, target_type);
+
+ foreach (Type t in gc.InterfaceConstraints) {
+ if (TypeManager.IsSubclassOf (t, target_type))
+ return TypeParameterConversion (expr, is_reference, target_type);
+ }
+ }
+
+ foreach (Type t in gc.InterfaceConstraints) {
+ if (!t.IsGenericParameter)
+ continue;
+ if (TypeManager.IsSubclassOf (t, target_type))
+ return TypeParameterConversion (expr, is_reference, target_type);
+ }
+
+ return null;
+ }
+
+ static EmptyExpression MyEmptyExpr;
+ static public Expression ImplicitReferenceConversion (EmitContext ec, 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);
+ }
+
+ if (expr_type == TypeManager.void_type)
+ return null;
+
+ if (expr_type.IsGenericParameter)
+ return ImplicitTypeParameterConversion (ec, expr, target_type);
+
+ //
+ // 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 (TypeManager.IsValueType (expr_type))
+ return new BoxedCast (expr);
+ if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type){
+ if (expr_type == TypeManager.anonymous_method_type)
+ return null;
+ return new EmptyCast (expr, target_type);
+ }
+
+ return null;
+ } else if (target_type == TypeManager.value_type) {
+ if (TypeManager.IsValueType (expr_type))
+ return new BoxedCast (expr);
+ if (expr_type == TypeManager.null_type)
+ return new NullCast (expr, target_type);
+
+ return null;
+ } else if (TypeManager.IsSubclassOf (expr_type, 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 || expr_type.IsGenericParameter)
+ return new BoxedCast (expr);
+
+ return new EmptyCast (expr, target_type);
+ }
+
+ // 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_type == TypeManager.null_type){
+ if (target_type.IsPointer)
+ return new EmptyCast (expr, target_type);
+
+ 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 (target_type != TypeManager.iconvertible_type &&
+ expr_type.IsValueType && (expr is Constant) &&
+ !(expr is IntLiteral || expr is BoolLiteral ||
+ expr is FloatLiteral || expr is DoubleLiteral ||
+ expr is LongLiteral || expr is CharLiteral ||
+ expr is StringLiteral || expr is DecimalLiteral ||
+ expr is UIntLiteral || expr is ULongLiteral)) {
+ return null;
+ }
+
+ if (TypeManager.ImplementsInterface (expr_type, target_type)){
+ if (expr_type.IsGenericParameter || TypeManager.IsValueType (expr_type))
+ return new BoxedCast (expr, target_type);
+ else
+ return new EmptyCast (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 (ConstantEC, 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 || TypeManager.IsDelegateType (expr_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 || TypeManager.IsDelegateType (expr_type))
+ if (target_type == TypeManager.icloneable_type)
+ return new EmptyCast (expr, target_type);
+
+ // from a generic type definition to a generic instance.
+ if (TypeManager.IsEqual (expr_type, target_type))
+ return new EmptyCast (expr, target_type);
+
+ return null;
+ }
+
+ //
+ // Tests whether an implicit reference conversion exists between expr_type
+ // and target_type
+ //
+ public static bool ImplicitReferenceConversionExists (EmitContext ec, Expression expr, Type target_type)
+ {
+ Type expr_type = expr.Type;
+
+ if (expr_type.IsGenericParameter)
+ return ImplicitTypeParameterConversion (ec, expr, target_type) != null;
+
+ //
+ // This is the boxed case.
+ //
+ if (target_type == TypeManager.object_type) {
+ if (expr_type.IsClass || TypeManager.IsValueType (expr_type) ||
+ expr_type.IsInterface || expr_type == TypeManager.enum_type)
+ if (target_type != TypeManager.anonymous_method_type)
+ return true;
+
+ return false;
+ } else if (TypeManager.IsSubclassOf (expr_type, target_type))
+ return true;
+
+ // 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 (target_type != TypeManager.iconvertible_type &&
+ expr_type.IsValueType && (expr is Constant) &&
+ !(expr is IntLiteral || expr is BoolLiteral ||
+ expr is FloatLiteral || expr is DoubleLiteral ||
+ expr is LongLiteral || expr is CharLiteral ||
+ expr is StringLiteral || expr is DecimalLiteral ||
+ expr is UIntLiteral || expr is ULongLiteral)) {
+ return false;
+ }
+
+ 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 (ConstantEC, 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 || TypeManager.IsDelegateType (expr_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 || TypeManager.IsDelegateType (expr_type))
+ if (target_type == TypeManager.icloneable_type)
+ return true;
+
+ // from the null type to any reference-type.
+ if (expr_type == TypeManager.null_type){
+ if (target_type.IsPointer)
+ return true;
+
+ if (!target_type.IsValueType)
+ return true;
+ }
+
+ // from a generic type definition to a generic instance.
+ if (TypeManager.IsEqual (expr_type, 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 ((expr is NullLiteral) && target_type.IsGenericParameter)
+ return TypeParameter_to_Null (target_type);
+
+ if (ImplicitStandardConversionExists (ec, 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
+ ///
+ /// ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
+ /// </summary>
+ public static bool ImplicitStandardConversionExists (EmitContext ec, 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.Equals (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;
+ }
+
+ if (ImplicitReferenceConversionExists (ec, expr, target_type))
+ return true;
+
+ //
+ // Implicit Constant Expression Conversions
+ //
+ 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;
+
+ if (expr_type == TypeManager.anonymous_method_type){
+ if (!TypeManager.IsDelegateType (target_type))
+ return false;
+
+ AnonymousMethod am = (AnonymousMethod) expr;
+ int errors = Report.Errors;
+
+ Expression conv = am.Compatible (ec, target_type, true);
+ if (conv != null)
+ 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 (EmitContext ec, 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 (ec, 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 (EmitContext ec, 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 (ec, 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 (EmitContext ec, 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 (ec, priv_fms_expr, source_type))
+ src_types_set.Add (param_type);
+ else {
+ if (ImplicitStandardConversionExists (ec, source, param_type))
+ src_types_set.Add (param_type);
+ }
+ } else {
+ //
+ // Only if S is encompassed by param_type
+ //
+ if (ImplicitStandardConversionExists (ec, 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 (ec, source, param_type))
+ candidate_set.Add (param_type);
+ }
+
+ if (candidate_set.Count != 0)
+ return FindMostEncompassedType (ec, candidate_set);
+ }
+
+ //
+ // Final case
+ //
+ if (apply_explicit_conv_rules)
+ return FindMostEncompassingType (ec, src_types_set);
+ else
+ return FindMostEncompassedType (ec, 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 (EmitContext ec, 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 (ec, priv_fms_expr, target))
+ tgt_types_set.Add (ret_type);
+ else {
+ priv_fms_expr.SetType (target);
+ if (ImplicitStandardConversionExists (ec, 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 (ec, 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 (ec, priv_fmt_expr, target))
+ candidate_set.Add (ret_type);
+ }
+
+ if (candidate_set.Count != 0)
+ return FindMostEncompassingType (ec, candidate_set);
+ }
+
+ //
+ // Okay, final case !
+ //
+ if (apply_explicit_conv_rules)
+ return FindMostEncompassedType (ec, tgt_types_set);
+ else
+ return FindMostEncompassingType (ec, 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);
+ }
+
+ static DoubleHash explicit_conv = new DoubleHash (100);
+ static DoubleHash implicit_conv = new DoubleHash (100);
+ /// <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;
+ object r;
+ if ((look_for_explicit ? explicit_conv : implicit_conv).Lookup (source_type, target_type, out r))
+ return (MethodGroupExpr) r;
+
+ 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);
+ }
+
+ MethodGroupExpr ret = Invocation.MakeUnionSet (union3, union4, loc);
+ (look_for_explicit ? explicit_conv : implicit_conv).Insert (source_type, target_type, ret);
+ return ret;
+ }
+
+ /// <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;
+
+ most_specific_source = FindMostSpecificSource (ec, union, source, look_for_explicit, loc);
+ if (most_specific_source == null)
+ return null;
+
+ most_specific_target = FindMostSpecificTarget (ec, 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)
+ {
+ 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 is NullLiteral) && target_type.IsGenericParameter)
+ return TypeParameter_to_Null (expr, target_type, loc);
+
+ if (expr.eclass == ExprClass.MethodGroup){
+ if (!TypeManager.IsDelegateType (target_type)){
+ return null;
+ }
+
+ //
+ // Only allow anonymous method conversions on post ISO_1
+ //
+ if (RootContext.Version != LanguageVersion.ISO_1){
+ MethodGroupExpr mg = expr as MethodGroupExpr;
+ if (mg != null)
+ return ImplicitDelegateCreation.Create (ec, mg, target_type, loc);
+ }
+ }
+
+ if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
+ return expr;
+
+ e = ImplicitNumericConversion (ec, expr, target_type, loc);
+ if (e != null)
+ return e;
+
+ e = ImplicitReferenceConversion (ec, 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_type == TypeManager.null_type)
+ return new EmptyCast (expr, target_type);
+
+ if (expr_type == TypeManager.void_ptr_type)
+ return new EmptyCast (expr, target_type);
+ }
+ }
+
+ if (expr_type == TypeManager.anonymous_method_type){
+ if (!TypeManager.IsDelegateType (target_type)){
+ Report.Error (1660, loc,
+ "Cannot convert anonymous method to `{0}', since it is not a delegate",
+ TypeManager.CSharpName (target_type));
+ return null;
+ }
+
+ AnonymousMethod am = (AnonymousMethod) expr;
+ int errors = Report.Errors;
+
+ Expression conv = am.Compatible (ec, target_type, false);
+ if (conv != null)
+ return conv;
+
+ //
+ // We return something instead of null, to avoid
+ // the duplicate error, since am.Compatible would have
+ // reported that already
+ //
+ if (errors != Report.Errors)
+ return new EmptyCast (expr, target_type);
+ }
+
+ return null;
+ }
+
+ /// <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 (value >= Byte.MinValue && 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
+ //
+ 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)
+ {
+ if (source.Name == target.Name){
+ Report.ExtraInformation (loc,
+ String.Format (
+ "The type {0} has two conflicting definitons, one comes from {0} and the other from {1}",
+ source.Assembly.FullName, target.Assembly.FullName));
+
+ }
+ Report.Error (29, loc, "Cannot convert implicitly from {0} to `{1}'",
+ source == TypeManager.anonymous_method_type ?
+ "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
+ TypeManager.CSharpName (target));
+ }
+
+ /// <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;
+
+ int errors = Report.Errors;
+ e = ImplicitConversion (ec, source, target_type, loc);
+ if (Report.Errors > errors)
+ return null;
+ if (e != null)
+ return e;
+
+ if (source is DoubleLiteral) {
+ if (target_type == TypeManager.float_type) {
+ Error_664 (loc, "float", "f");
+ return null;
+ }
+ if (target_type == TypeManager.decimal_type) {
+ Error_664 (loc, "decimal", "m");
+ return null;
+ }
+ }
+
+ if (source is Constant){
+ Constant c = (Constant) source;
+
+ Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
+ return null;
+ }
+
+ Error_CannotImplicitConversion (loc, source.Type, target_type);
+
+ return null;
+ }
+
+ static void Error_664 (Location loc, string type, string suffix) {
+ Report.Error (664, loc,
+ "Literal of type double cannot be implicitly converted to type '{0}'. Add suffix '{1}' to create a literal of this type",
+ type, suffix);
+ }
+
+ /// <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 (ec, 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_type_param = target_type.IsGenericParameter;
+ bool target_is_value_type = target_type.IsValueType;
+
+ if (source_type == target_type)
+ return true;
+
+ //
+ // From object to a generic parameter
+ //
+ if (source_type == TypeManager.object_type && target_is_type_param)
+ 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 (TypeManager.IsSubclassOf (target_type, 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 (!TypeManager.IsSubclassOf (target_type, 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 &&
+ TypeManager.IsDelegateType (target_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_type_param = target_type.IsGenericParameter;
+ bool target_is_value_type = target_type.IsValueType;
+
+ //
+ // From object to a generic parameter
+ //
+ if (source_type == TypeManager.object_type && target_is_type_param)
+ return new UnboxCast (source, target_type);
+
+ //
+ // From object to any reference type
+ //
+ if (source_type == TypeManager.object_type && !target_is_value_type)
+ return new ClassCast (source, target_type);
+
+ //
+ // Unboxing conversion.
+ //
+ if (((source_type == TypeManager.enum_type &&
+ !(source is EmptyCast)) ||
+ source_type == TypeManager.value_type) && target_is_value_type)
+ return new UnboxCast (source, target_type);
+
+ //
+ // From any class S to any class-type T, provided S is a base class of T
+ //
+ if (TypeManager.IsSubclassOf (target_type, 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)) {
+ if (target_type.IsClass)
+ return new ClassCast (source, target_type);
+ else
+ return new UnboxCast (source, target_type);
+ }
+
+ 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 &&
+ TypeManager.IsDelegateType (target_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;
+ }
+
+ int errors = Report.Errors;
+ Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+ if (Report.Errors > errors)
+ return null;
+
+ 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)
+ return new UnboxCast (expr, target_type);
+
+ //
+ // Skip the ExplicitReferenceConversion because we can not convert
+ // from Null to a ValueType, and ExplicitReference wont check against
+ // null literal explicitly
+ //
+ if (expr_type != TypeManager.null_type){
+ ne = ExplicitReferenceConversion (expr, target_type);
+ if (ne != null)
+ return ne;
+ }
+
+ skip_explicit:
+ 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;
+
+ if (expr is NullLiteral){
+ Report.Error (37, loc, "Cannot convert null to value type `" +
+ TypeManager.CSharpName (target_type) + "'");
+ return null;
+ }
+
+ 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)
+ {
+ int errors = Report.Errors;
+ Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
+ if (Report.Errors > errors)
+ return null;
+
+ 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;
+ }
+ }
+}
--- /dev/null
+//
+// decl.cs: Declaration base class for structs, classes, enums and interfaces.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+// Marek Safar (marek.safar@seznam.cz)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+// TODO: Move the method verification stuff from the class.cs and interface.cs here
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Reflection.Emit;
+using System.Reflection;
+using System.Xml;
+
+namespace Mono.CSharp {
+
+ public class MemberName {
+ public string Name;
+ public readonly TypeArguments TypeArguments;
+
+ public readonly MemberName Left;
+
+ public static readonly MemberName Null = new MemberName ("");
+
+ public MemberName (string name)
+ {
+ this.Name = name;
+ }
+
+ public MemberName (string name, TypeArguments args)
+ : this (name)
+ {
+ this.TypeArguments = args;
+ }
+
+ public MemberName (MemberName left, string name, TypeArguments args)
+ : this (name, args)
+ {
+ this.Left = left;
+ }
+
+ public MemberName (MemberName left, MemberName right)
+ : this (left, right.Name, right.TypeArguments)
+ {
+ }
+
+ public string GetName ()
+ {
+ if (Left != null)
+ return Left.GetName () + "." + Name;
+ else
+ return Name;
+ }
+
+ public bool IsGeneric {
+ get {
+ if (TypeArguments != null)
+ return true;
+ else if (Left != null)
+ return Left.IsGeneric;
+ else
+ return false;
+ }
+ }
+
+ public string GetName (bool is_generic)
+ {
+ string name = is_generic ? Basename : Name;
+ if (Left != null)
+ return Left.GetName (is_generic) + "." + name;
+ else
+ return name;
+ }
+
+ public int CountTypeArguments {
+ get {
+ if (TypeArguments == null)
+ return 0;
+ else
+ return TypeArguments.Count;
+ }
+ }
+
+ public string GetMethodName ()
+ {
+ if (Left != null)
+ return Left.GetTypeName () + "." + Name;
+ else
+ return Name;
+ }
+
+ public static string MakeName (string name, TypeArguments args)
+ {
+ if (args == null)
+ return name;
+ else
+ return name + "`" + args.Count;
+ }
+
+ public static string MakeName (string name, int count)
+ {
+ return name + "`" + count;
+ }
+
+ public string GetTypeName ()
+ {
+ string suffix = "";
+ if (Left != null)
+ return Left.GetTypeName () + "." +
+ MakeName (Name, TypeArguments);
+ else
+ return MakeName (Name, TypeArguments);
+ }
+
+ protected bool IsUnbound {
+ get {
+ if ((Left != null) && Left.IsUnbound)
+ return true;
+ else if (TypeArguments == null)
+ return false;
+ else
+ return TypeArguments.IsUnbound;
+ }
+ }
+
+ protected bool CheckUnbound (Location loc)
+ {
+ if ((Left != null) && !Left.CheckUnbound (loc))
+ return false;
+ if ((TypeArguments != null) && !TypeArguments.IsUnbound) {
+ Report.Error (1031, loc, "Type expected");
+ return false;
+ }
+
+ return true;
+ }
+
+ public Expression GetTypeExpression (Location loc)
+ {
+ if (IsUnbound) {
+ if (!CheckUnbound (loc))
+ return null;
+
+ return new UnboundTypeExpression (GetTypeName ());
+ }
+
+ if (Left != null) {
+ Expression lexpr = Left.GetTypeExpression (loc);
+
+ return new MemberAccess (lexpr, Name, TypeArguments, loc);
+ } else {
+ if (TypeArguments != null)
+ return new ConstructedType (Name, TypeArguments, loc);
+ else
+ return new SimpleName (Name, loc);
+ }
+ }
+
+ public MemberName Clone ()
+ {
+ if (Left != null)
+ return new MemberName (Left.Clone (), Name, TypeArguments);
+ else
+ return new MemberName (Name, TypeArguments);
+ }
+
+ public string Basename {
+ get {
+ if (TypeArguments != null)
+ return MakeName (Name, TypeArguments);
+ else
+ return Name;
+ }
+ }
+
+ public override string ToString ()
+ {
+ string full_name;
+ if (TypeArguments != null)
+ full_name = Name + "<" + TypeArguments + ">";
+ else
+ full_name = Name;
+
+ if (Left != null)
+ return Left + "." + full_name;
+ else
+ return full_name;
+ }
+ }
+
+ /// <summary>
+ /// Base representation for members. This is used to keep track
+ /// of Name, Location and Modifier flags, and handling Attributes.
+ /// </summary>
+ public abstract class MemberCore : Attributable {
+ /// <summary>
+ /// Public name
+ /// </summary>
+ public string Name {
+ get {
+ return MemberName.GetName (!(this is GenericMethod) && !(this is Method));
+ }
+ }
+
+ // Is not readonly because of IndexerName attribute
+ public MemberName MemberName;
+
+ /// <summary>
+ /// Modifier flags that the user specified in the source code
+ /// </summary>
+ public int ModFlags;
+
+ public readonly TypeContainer Parent;
+
+ /// <summary>
+ /// Location where this declaration happens
+ /// </summary>
+ public readonly Location Location;
+
+ /// <summary>
+ /// XML documentation comment
+ /// </summary>
+ public string DocComment;
+
+ /// <summary>
+ /// Represents header string for documentation comment
+ /// for each member types.
+ /// </summary>
+ public abstract string DocCommentHeader { get; }
+
+ [Flags]
+ public enum Flags {
+ Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet
+ Obsolete = 1 << 1, // Type has obsolete attribute
+ ClsCompliance_Undetected = 1 << 2, // CLS Compliance has not been detected yet
+ ClsCompliant = 1 << 3, // Type is CLS Compliant
+ CloseTypeCreated = 1 << 4, // Tracks whether we have Closed the type
+ HasCompliantAttribute_Undetected = 1 << 5, // Presence of CLSCompliantAttribute has not been detected
+ HasClsCompliantAttribute = 1 << 6, // Type has CLSCompliantAttribute
+ ClsCompliantAttributeTrue = 1 << 7, // Type has CLSCompliant (true)
+ Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet
+ Excluded = 1 << 9, // Method is conditional
+ TestMethodDuplication = 1 << 10 // Test for duplication must be performed
+ }
+
+ /// <summary>
+ /// MemberCore flags at first detected then cached
+ /// </summary>
+ internal Flags caching_flags;
+
+ public MemberCore (TypeContainer parent, MemberName name, Attributes attrs,
+ Location loc)
+ : base (attrs)
+ {
+ Parent = parent;
+ MemberName = name;
+ Location = loc;
+ caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
+ }
+
+ /// <summary>
+ /// Tests presence of ObsoleteAttribute and report proper error
+ /// </summary>
+ protected void CheckUsageOfObsoleteAttribute (Type type)
+ {
+ if (type == null)
+ return;
+
+ ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
+ if (obsolete_attr == null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, Location);
+ }
+
+ public abstract bool Define ();
+
+ //
+ // Returns full member name for error message
+ //
+ public virtual string GetSignatureForError ()
+ {
+ return Name;
+ }
+
+ /// <summary>
+ /// Use this method when MethodBuilder is null
+ /// </summary>
+ public virtual string GetSignatureForError (TypeContainer tc)
+ {
+ return Name;
+ }
+
+ /// <summary>
+ /// Base Emit method. This is also entry point for CLS-Compliant verification.
+ /// </summary>
+ public virtual void Emit ()
+ {
+ // Hack with Parent == null is for EnumMember
+ if (Parent == null || (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent) == null))
+ VerifyObsoleteAttribute ();
+
+ if (!RootContext.VerifyClsCompliance)
+ return;
+
+ VerifyClsCompliance (Parent);
+ }
+
+ public bool InUnsafe {
+ get {
+ return ((ModFlags & Modifiers.UNSAFE) != 0) || Parent.UnsafeContext;
+ }
+ }
+
+ //
+ // 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;
+ }
+
+ /// <summary>
+ /// Returns instance of ObsoleteAttribute for this MemberCore
+ /// </summary>
+ public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+ {
+ // ((flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) is slower, but why ?
+ if ((caching_flags & Flags.Obsolete_Undetected) == 0 && (caching_flags & Flags.Obsolete) == 0) {
+ return null;
+ }
+
+ caching_flags &= ~Flags.Obsolete_Undetected;
+
+ if (OptAttributes == null)
+ return null;
+
+ Attribute obsolete_attr = OptAttributes.Search (
+ TypeManager.obsolete_attribute_type, ds.EmitContext);
+ if (obsolete_attr == null)
+ return null;
+
+ ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (ds);
+ if (obsolete == null)
+ return null;
+
+ caching_flags |= Flags.Obsolete;
+ return obsolete;
+ }
+
+ /// <summary>
+ /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
+ /// </summary>
+ public override bool IsClsCompliaceRequired (DeclSpace container)
+ {
+ if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
+ return (caching_flags & Flags.ClsCompliant) != 0;
+
+ if (GetClsCompliantAttributeValue (container) && IsExposedFromAssembly (container)) {
+ caching_flags &= ~Flags.ClsCompliance_Undetected;
+ caching_flags |= Flags.ClsCompliant;
+ return true;
+ }
+
+ caching_flags &= ~Flags.ClsCompliance_Undetected;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true when MemberCore is exposed from assembly.
+ /// </summary>
+ public bool IsExposedFromAssembly (DeclSpace ds)
+ {
+ if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
+ return false;
+
+ DeclSpace parentContainer = ds;
+ while (parentContainer != null && parentContainer.ModFlags != 0) {
+ if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
+ return false;
+ parentContainer = parentContainer.Parent;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Resolve CLSCompliantAttribute value or gets cached value.
+ /// </summary>
+ bool GetClsCompliantAttributeValue (DeclSpace ds)
+ {
+ if (OptAttributes != null) {
+ Attribute cls_attribute = OptAttributes.Search (
+ TypeManager.cls_compliant_attribute_type, ds.EmitContext);
+ if (cls_attribute != null) {
+ caching_flags |= Flags.HasClsCompliantAttribute;
+ return cls_attribute.GetClsCompliantAttributeValue (ds);
+ }
+ }
+ return ds.GetClsCompliantAttributeValue ();
+ }
+
+ /// <summary>
+ /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
+ /// </summary>
+ protected bool HasClsCompliantAttribute {
+ get {
+ return (caching_flags & Flags.HasClsCompliantAttribute) != 0;
+ }
+ }
+
+ /// <summary>
+ /// The main virtual method for CLS-Compliant verifications.
+ /// The method returns true if member is CLS-Compliant and false if member is not
+ /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
+ /// and add their extra verifications.
+ /// </summary>
+ protected virtual bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!IsClsCompliaceRequired (ds)) {
+ if ((RootContext.WarningLevel >= 2) && HasClsCompliantAttribute && !IsExposedFromAssembly (ds)) {
+ Report.Warning (3019, Location, "CLS compliance checking will not be performed on '{0}' because it is private or internal", GetSignatureForError ());
+ }
+ return false;
+ }
+
+ if (!CodeGen.Assembly.IsClsCompliant) {
+ if (HasClsCompliantAttribute) {
+ Report.Error (3014, Location, "'{0}' cannot be marked as CLS-compliant because the assembly does not have a CLSCompliant attribute", GetSignatureForError ());
+ }
+ return false;
+ }
+
+ int index = Name.LastIndexOf ('.');
+ if (Name [index > 0 ? index + 1 : 0] == '_') {
+ Report.Error (3008, Location, "Identifier '{0}' is not CLS-compliant", GetSignatureForError () );
+ }
+ return true;
+ }
+
+ protected abstract void VerifyObsoleteAttribute ();
+
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ internal virtual void OnGenerateDocComment (DeclSpace ds, XmlElement intermediateNode)
+ {
+ }
+
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public virtual string GetDocCommentName (DeclSpace ds)
+ {
+ if (ds == null || this is DeclSpace)
+ return DocCommentHeader + Name;
+ else
+ return String.Concat (DocCommentHeader, ds.Name, ".", Name);
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal virtual void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateDocComment (this, ds);
+ }
+ }
+
+ /// <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, IAlias {
+ /// <summary>
+ /// This points to the actual definition that is being
+ /// created with System.Reflection.Emit
+ /// </summary>
+ public TypeBuilder TypeBuilder;
+
+ /// <summary>
+ /// If we are a generic type, this is the type we are
+ /// currently defining. We need to lookup members on this
+ /// instead of the TypeBuilder.
+ /// </summary>
+ public Type CurrentType;
+
+ //
+ // This is the namespace in which this typecontainer
+ // was declared. We use this to resolve names.
+ //
+ public NamespaceEntry NamespaceEntry;
+
+ public Hashtable Cache = new Hashtable ();
+
+ public string Basename;
+
+ protected Hashtable defined_names;
+
+ readonly bool is_generic;
+ readonly int count_type_params;
+
+ // The emit context for toplevel objects.
+ protected EmitContext ec;
+
+ public EmitContext EmitContext {
+ get { return ec; }
+ }
+
+ //
+ // Whether we are Generic
+ //
+ public bool IsGeneric {
+ get {
+ if (is_generic)
+ return true;
+ else if (Parent != null)
+ return Parent.IsGeneric;
+ else
+ return false;
+ }
+ }
+
+ static string[] attribute_targets = new string [] { "type" };
+
+ public DeclSpace (NamespaceEntry ns, TypeContainer parent, MemberName name,
+ Attributes attrs, Location l)
+ : base (parent, name, attrs, l)
+ {
+ NamespaceEntry = ns;
+ Basename = name.Name;
+ defined_names = new Hashtable ();
+ if (name.TypeArguments != null) {
+ is_generic = true;
+ count_type_params = name.TypeArguments.Count;
+ }
+ if (parent != null)
+ count_type_params += parent.count_type_params;
+ }
+
+ /// <summary>
+ /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
+ /// </summary>
+ protected bool AddToContainer (MemberCore symbol, bool is_method, string fullname, string basename)
+ {
+ if (basename == Basename && !(this is Interface)) {
+ if (symbol is TypeParameter)
+ Report.Error (694, "Type parameter `{0}' has same name as " +
+ "containing type or method", basename);
+ else {
+ Report.SymbolRelatedToPreviousError (this);
+ Report.Error (542, "'{0}': member names cannot be the same as their " +
+ "enclosing type", symbol.Location, symbol.GetSignatureForError ());
+ }
+ return false;
+ }
+
+ MemberCore mc = (MemberCore)defined_names [fullname];
+
+ if (is_method && (mc is MethodCore || mc is IMethodData)) {
+ symbol.caching_flags |= Flags.TestMethodDuplication;
+ mc.caching_flags |= Flags.TestMethodDuplication;
+ return true;
+ }
+
+ if (mc != null) {
+ if (symbol is TypeParameter)
+ Report.Error (692, symbol.Location, "Duplicate type parameter `{0}'", basename);
+ else {
+ Report.SymbolRelatedToPreviousError (mc);
+ Report.Error (102, symbol.Location,
+ "The type '{0}' already contains a definition for '{1}'",
+ GetSignatureForError (), basename);
+ }
+ return false;
+ }
+
+ defined_names.Add (fullname, symbol);
+ return true;
+ }
+
+ public void RecordDecl ()
+ {
+ if ((NamespaceEntry != null) && (Parent == RootContext.Tree.Types))
+ NamespaceEntry.DefineName (MemberName.Basename, this);
+ }
+
+ /// <summary>
+ /// Returns the MemberCore associated with a given name in the declaration
+ /// space. It doesn't return method based symbols !!
+ /// </summary>
+ ///
+ public MemberCore GetDefinition (string name)
+ {
+ return (MemberCore)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;
+ }
+ }
+
+ /// <summary>
+ /// Looks up the alias for the name
+ /// </summary>
+ public IAlias LookupAlias (string name)
+ {
+ if (NamespaceEntry != null)
+ return NamespaceEntry.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 ((caching_flags & Flags.CloseTypeCreated) == 0){
+ 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
+ }
+ caching_flags |= Flags.CloseTypeCreated;
+ }
+ }
+
+ /// <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;
+ }
+
+ public Type ResolveNestedType (Type t, Location loc)
+ {
+ TypeContainer tc = TypeManager.LookupTypeContainer (t);
+ if ((tc != null) && tc.IsGeneric) {
+ if (!IsGeneric) {
+ int tnum = TypeManager.GetNumberOfTypeArguments (t);
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (t), tnum);
+ return null;
+ }
+
+ TypeParameter[] args;
+ if (this is GenericMethod)
+ args = Parent.TypeParameters;
+ else
+ args = TypeParameters;
+
+ TypeExpr ctype = new ConstructedType (t, args, loc);
+ ctype = ctype.ResolveAsTypeTerminal (ec);
+ if (ctype == null)
+ return null;
+
+ t = ctype.Type;
+ }
+
+ return t;
+ }
+
+ // <summary>
+ // Resolves the expression `e' for a type, and will recursively define
+ // types. This should only be used for resolving base types.
+ // </summary>
+ public TypeExpr ResolveTypeExpr (Expression e, Location loc)
+ {
+ if (type_resolve_ec == null)
+ type_resolve_ec = GetTypeResolveEmitContext (Parent, loc);
+ type_resolve_ec.loc = loc;
+ if (this is GenericMethod)
+ type_resolve_ec.ContainerType = Parent.TypeBuilder;
+ else
+ type_resolve_ec.ContainerType = TypeBuilder;
+
+ return e.ResolveAsTypeTerminal (type_resolve_ec);
+ }
+
+ public bool CheckAccessLevel (Type check_type)
+ {
+ TypeBuilder tb;
+ if ((this is GenericMethod) || (this is Iterator))
+ tb = Parent.TypeBuilder;
+ else
+ tb = TypeBuilder;
+
+ if (check_type.IsGenericInstance)
+ check_type = check_type.GetGenericTypeDefinition ();
+
+ if (check_type == tb)
+ return true;
+
+ if (TypeBuilder == null)
+ // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+ // However, this is invoked again later -- so safe to return true.
+ // May also be null when resolving top-level attributes.
+ return true;
+
+ if (check_type.IsGenericParameter)
+ return true; // FIXME
+
+ 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:
+
+ if (TypeBuilder == null)
+ // FIXME: TypeBuilder will be null when invoked by Class.GetNormalBases().
+ // However, this is invoked again later -- so safe to return true.
+ // May also be null when resolving top-level attributes.
+ return true;
+ //
+ // This test should probably use the declaringtype.
+ //
+ return check_type.Assembly == TypeBuilder.Assembly;
+
+ case TypeAttributes.NestedPublic:
+ return true;
+
+ case TypeAttributes.NestedPrivate:
+ return NestedAccessible (tb, check_type);
+
+ case TypeAttributes.NestedFamily:
+ //
+ // Only accessible to methods in current type or any subtypes
+ //
+ return FamilyAccessible (tb, check_type);
+
+ case TypeAttributes.NestedFamANDAssem:
+ return (check_type.Assembly == tb.Assembly) &&
+ FamilyAccessible (tb, check_type);
+
+ case TypeAttributes.NestedFamORAssem:
+ return (check_type.Assembly == tb.Assembly) ||
+ FamilyAccessible (tb, check_type);
+
+ case TypeAttributes.NestedAssembly:
+ return check_type.Assembly == tb.Assembly;
+ }
+
+ Console.WriteLine ("HERE: " + check_attr);
+ return false;
+
+ }
+
+ protected bool NestedAccessible (Type tb, Type check_type)
+ {
+ string check_type_name = check_type.FullName;
+
+ // At this point, we already know check_type is a nested class.
+ int cio = check_type_name.LastIndexOf ('+');
+
+ // Ensure that the string 'container' has a '+' in it to avoid false matches
+ string container = check_type_name.Substring (0, cio + 1);
+
+ // Ensure that type_name ends with a '+' so that it can match 'container', if necessary
+ string type_name = tb.FullName + "+";
+
+ // If the current class is nested inside the container of check_type,
+ // we can access check_type even if it is private or protected.
+ return type_name.StartsWith (container);
+ }
+
+ protected bool FamilyAccessible (Type tb, Type check_type)
+ {
+ Type declaring = check_type.DeclaringType;
+ if (tb == declaring || TypeManager.IsFamilyAccessible (tb, declaring))
+ return true;
+
+ return NestedAccessible (tb, check_type);
+ }
+
+ // Access level of a type.
+ const int X = 1;
+ enum AccessLevel { // Each column represents `is this scope larger or equal to Blah scope'
+ // Public Assembly Protected
+ Protected = (0 << 0) | (0 << 1) | (X << 2),
+ Public = (X << 0) | (X << 1) | (X << 2),
+ Private = (0 << 0) | (0 << 1) | (0 << 2),
+ Internal = (0 << 0) | (X << 1) | (0 << 2),
+ ProtectedOrInternal = (0 << 0) | (X << 1) | (X << 2),
+ }
+
+ static AccessLevel GetAccessLevelFromModifiers (int flags)
+ {
+ if ((flags & Modifiers.INTERNAL) != 0) {
+
+ if ((flags & Modifiers.PROTECTED) != 0)
+ return AccessLevel.ProtectedOrInternal;
+ else
+ return AccessLevel.Internal;
+
+ } else if ((flags & Modifiers.PROTECTED) != 0)
+ return AccessLevel.Protected;
+ else if ((flags & Modifiers.PRIVATE) != 0)
+ return AccessLevel.Private;
+ else
+ return AccessLevel.Public;
+ }
+
+ // What is the effective access level of this?
+ // TODO: Cache this?
+ AccessLevel EffectiveAccessLevel {
+ get {
+ AccessLevel myAccess = GetAccessLevelFromModifiers (ModFlags);
+ if (!IsTopLevel && (Parent != null))
+ return myAccess & Parent.EffectiveAccessLevel;
+ return myAccess;
+ }
+ }
+
+ // Return the access level for type `t'
+ static AccessLevel TypeEffectiveAccessLevel (Type t)
+ {
+ if (t.IsPublic)
+ return AccessLevel.Public;
+ if (t.IsNestedPrivate)
+ return AccessLevel.Private;
+ if (t.IsNotPublic)
+ return AccessLevel.Internal;
+
+ // By now, it must be nested
+ AccessLevel parentLevel = TypeEffectiveAccessLevel (t.DeclaringType);
+
+ if (t.IsNestedPublic)
+ return parentLevel;
+ if (t.IsNestedAssembly)
+ return parentLevel & AccessLevel.Internal;
+ if (t.IsNestedFamily)
+ return parentLevel & AccessLevel.Protected;
+ if (t.IsNestedFamORAssem)
+ return parentLevel & AccessLevel.ProtectedOrInternal;
+ if (t.IsNestedFamANDAssem)
+ throw new NotImplementedException ("NestedFamANDAssem not implemented, cant make this kind of type from c# anyways");
+
+ // nested private is taken care of
+
+ throw new Exception ("I give up, what are you?");
+ }
+
+ //
+ // This answers `is the type P, as accessible as a member M which has the
+ // accessability @flags which is declared as a nested member of the type T, this declspace'
+ //
+ public bool AsAccessible (Type p, int flags)
+ {
+ if (p.IsGenericParameter)
+ return true; // FIXME
+
+ //
+ // 1) if M is private, its accessability is the same as this declspace.
+ // we already know that P is accessible to T before this method, so we
+ // may return true.
+ //
+
+ if ((flags & Modifiers.PRIVATE) != 0)
+ return true;
+
+ while (p.IsArray || p.IsPointer || p.IsByRef)
+ p = TypeManager.GetElementType (p);
+
+ AccessLevel pAccess = TypeEffectiveAccessLevel (p);
+ AccessLevel mAccess = this.EffectiveAccessLevel &
+ GetAccessLevelFromModifiers (flags);
+
+ // for every place from which we can access M, we must
+ // be able to access P as well. So, we want
+ // For every bit in M and P, M_i -> P_1 == true
+ // or, ~ (M -> P) == 0 <-> ~ ( ~M | P) == 0
+
+ return ~ (~ mAccess | pAccess) == 0;
+ }
+
+ static DoubleHash dh = new DoubleHash (1000);
+
+ Type DefineTypeAndParents (DeclSpace tc)
+ {
+ DeclSpace container = tc.Parent;
+
+ if (container.TypeBuilder == null && container.Name != "")
+ DefineTypeAndParents (container);
+
+ return tc.DefineType ();
+ }
+
+ Type LookupInterfaceOrClass (string ns, string name, out bool error)
+ {
+ DeclSpace parent;
+ Type t;
+ object r;
+
+ error = false;
+
+ if (dh.Lookup (ns, name, out r))
+ return (Type) r;
+ else {
+ if (ns != ""){
+ if (Namespace.IsNamespace (ns)){
+ string fullname = (ns != "") ? ns + "." + name : name;
+ t = TypeManager.LookupType (fullname);
+ } else
+ t = null;
+ } else
+ t = TypeManager.LookupType (name);
+ }
+
+ if (t != null) {
+ dh.Insert (ns, name, t);
+ return t;
+ }
+
+ //
+ // In case we are fed a composite name, normalize it.
+ //
+ int p = name.LastIndexOf ('.');
+ if (p != -1){
+ ns = MakeFQN (ns, name.Substring (0, p));
+ name = name.Substring (p+1);
+ }
+
+ parent = RootContext.Tree.LookupByNamespace (ns, name);
+ if (parent == null) {
+ dh.Insert (ns, name, null);
+ return null;
+ }
+
+ t = DefineTypeAndParents (parent);
+ if (t == null){
+ error = true;
+ return null;
+ }
+
+ dh.Insert (ns, name, t);
+ return t;
+ }
+
+ public static void Error_AmbiguousTypeReference (Location loc, string name, string t1, string t2)
+ {
+ Report.Error (104, loc,
+ "`{0}' is an ambiguous reference ({1} or {2})",
+ name, t1, t2);
+ }
+
+ public Type FindNestedType (Location loc, string name,
+ out DeclSpace containing_ds)
+ {
+ Type t;
+ bool error;
+
+ containing_ds = this;
+ while (containing_ds != null){
+ Type container_type = containing_ds.TypeBuilder;
+ Type current_type = container_type;
+
+ while (current_type != null && current_type != TypeManager.object_type) {
+ 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;
+ }
+
+ return null;
+ }
+
+ /// <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 && current_type != TypeManager.object_type) {
+ string pre = current_type.FullName;
+
+ t = LookupInterfaceOrClass (pre, name, out error);
+ if (error)
+ return null;
+
+ if ((t != null) && containing_ds.CheckAccessLevel (t))
+ return ResolveNestedType (t, loc);
+
+ 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 = NamespaceEntry; ns != null; ns = ns.ImplicitParent) {
+ t = LookupInterfaceOrClass (ns.FullName, 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 = NamespaceEntry; ns != null; ns = ns.Parent){
+
+ t = LookupInterfaceOrClass (ns.FullName, name, out error);
+ if (error)
+ return null;
+
+ if (t != null)
+ return t;
+
+ if (name.IndexOf ('.') > 0)
+ continue;
+
+ IAlias alias_value = ns.LookupAlias (name);
+ if (alias_value != null) {
+ t = LookupInterfaceOrClass ("", alias_value.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.FullName, match.FullName);
+ 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;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ try {
+ TypeBuilder.SetCustomAttribute (cb);
+ } catch (System.ArgumentException e) {
+ Report.Warning (-21, a.Location,
+ "The CharSet named property on StructLayout\n"+
+ "\tdoes not work correctly on Microsoft.NET\n"+
+ "\tYou might want to remove the CharSet declaration\n"+
+ "\tor compile using the Mono runtime instead of the\n"+
+ "\tMicrosoft .NET runtime\n"+
+ "\tThe runtime gave the error: " + e);
+ }
+ }
+
+ /// <summary>
+ /// Goes through class hierarchy and get value of first CLSCompliantAttribute that found.
+ /// If no is attribute exists then return assembly CLSCompliantAttribute.
+ /// </summary>
+ public bool GetClsCompliantAttributeValue ()
+ {
+ if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0)
+ return (caching_flags & Flags.ClsCompliantAttributeTrue) != 0;
+
+ caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
+
+ if (OptAttributes != null) {
+ Attribute cls_attribute = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, ec);
+ if (cls_attribute != null) {
+ caching_flags |= Flags.HasClsCompliantAttribute;
+ if (cls_attribute.GetClsCompliantAttributeValue (this)) {
+ caching_flags |= Flags.ClsCompliantAttributeTrue;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ if (Parent == null) {
+ if (CodeGen.Assembly.IsClsCompliant) {
+ caching_flags |= Flags.ClsCompliantAttributeTrue;
+ return true;
+ }
+ return false;
+ }
+
+ if (Parent.GetClsCompliantAttributeValue ()) {
+ caching_flags |= Flags.ClsCompliantAttributeTrue;
+ return true;
+ }
+ return false;
+ }
+
+ //
+ // Extensions for generics
+ //
+ TypeParameter[] type_params;
+ TypeParameter[] type_param_list;
+
+ protected string GetInstantiationName ()
+ {
+ StringBuilder sb = new StringBuilder (Name);
+ sb.Append ("<");
+ for (int i = 0; i < type_param_list.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (type_param_list [i].Name);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ }
+
+ bool check_type_parameter (ArrayList list, int start, string name)
+ {
+ for (int i = 0; i < start; i++) {
+ TypeParameter param = (TypeParameter) list [i];
+
+ if (param.Name != name)
+ continue;
+
+ if (RootContext.WarningLevel >= 3)
+ Report.Warning (
+ 693, Location,
+ "Type parameter `{0}' has same name " +
+ "as type parameter from outer type `{1}'",
+ name, Parent.GetInstantiationName ());
+
+ return false;
+ }
+
+ return true;
+ }
+
+ TypeParameter[] initialize_type_params ()
+ {
+ if (type_param_list != null)
+ return type_param_list;
+
+ DeclSpace the_parent = Parent;
+ if (this is GenericMethod)
+ the_parent = null;
+
+ int start = 0;
+ TypeParameter[] parent_params = null;
+ if ((the_parent != null) && the_parent.IsGeneric) {
+ parent_params = the_parent.initialize_type_params ();
+ start = parent_params != null ? parent_params.Length : 0;
+ }
+
+ ArrayList list = new ArrayList ();
+ if (parent_params != null)
+ list.AddRange (parent_params);
+
+ int count = type_params != null ? type_params.Length : 0;
+ for (int i = 0; i < count; i++) {
+ TypeParameter param = type_params [i];
+ check_type_parameter (list, start, param.Name);
+ list.Add (param);
+ }
+
+ type_param_list = new TypeParameter [list.Count];
+ list.CopyTo (type_param_list, 0);
+ return type_param_list;
+ }
+
+ public void SetParameterInfo (ArrayList constraints_list)
+ {
+ if (!is_generic) {
+ if (constraints_list != null) {
+ Report.Error (
+ 80, Location, "Contraints are not allowed " +
+ "on non-generic declarations");
+ }
+
+ return;
+ }
+
+ string[] names = MemberName.TypeArguments.GetDeclarations ();
+ type_params = new TypeParameter [names.Length];
+
+ //
+ // Register all the names
+ //
+ for (int i = 0; i < type_params.Length; i++) {
+ string name = names [i];
+
+ Constraints constraints = null;
+ if (constraints_list != null) {
+ foreach (Constraints constraint in constraints_list) {
+ if (constraint.TypeParameter == name) {
+ constraints = constraint;
+ break;
+ }
+ }
+ }
+
+ type_params [i] = new TypeParameter (Parent, name, constraints, Location);
+
+ string full_name = Name + "." + name;
+ AddToContainer (type_params [i], false, full_name, name);
+ }
+ }
+
+ public TypeParameter[] TypeParameters {
+ get {
+ if (!IsGeneric)
+ throw new InvalidOperationException ();
+ if (type_param_list == null)
+ initialize_type_params ();
+
+ return type_param_list;
+ }
+ }
+
+ protected TypeParameter[] CurrentTypeParameters {
+ get {
+ if (!IsGeneric)
+ throw new InvalidOperationException ();
+ if (type_params != null)
+ return type_params;
+ else
+ return new TypeParameter [0];
+ }
+ }
+
+ public int CountTypeParameters {
+ get {
+ return count_type_params;
+ }
+ }
+
+ public TypeParameterExpr LookupGeneric (string name, Location loc)
+ {
+ if (!IsGeneric)
+ return null;
+
+ foreach (TypeParameter type_param in CurrentTypeParameters) {
+ if (type_param.Name != name)
+ continue;
+
+ return new TypeParameterExpr (type_param, loc);
+ }
+
+ if (Parent != null)
+ return Parent.LookupGeneric (name, loc);
+
+ return null;
+ }
+
+ bool IAlias.IsType {
+ get { return true; }
+ }
+
+ string IAlias.Name {
+ get { return Name; }
+ }
+
+ TypeExpr IAlias.ResolveAsType (EmitContext ec)
+ {
+ if (TypeBuilder == null)
+ throw new InvalidOperationException ();
+
+ if (CurrentType != null)
+ return new TypeExpression (CurrentType, Location);
+ else
+ return new TypeExpression (TypeBuilder, Location);
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+ }
+
+ /// <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>
+ MemberCache ParentCache {
+ 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;
+
+ /// <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);
+
+ // 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.ParentCache != null)
+ member_hash = SetupCache (Container.ParentCache);
+ 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 && !type.IsGenericParameter) {
+ method_hash = new Hashtable ();
+ AddMethods (type);
+ }
+
+ // Add all members from the current class.
+ AddMembers (Container);
+
+ Timer.StopTimer (TimerType.CacheInit);
+ }
+
+ public MemberCache (Type[] ifaces)
+ {
+ //
+ // The members of this cache all belong to other caches.
+ // So, 'Container' will not be used.
+ //
+ this.Container = null;
+
+ member_hash = new Hashtable ();
+ if (ifaces == null)
+ return;
+
+ foreach (Type itype in ifaces)
+ AddCacheContents (TypeManager.LookupMemberCache (itype));
+ }
+
+ /// <summary>
+ /// Bootstrap this member cache by doing a deep-copy of our parent.
+ /// </summary>
+ Hashtable SetupCache (MemberCache parent)
+ {
+ Hashtable hash = new Hashtable ();
+
+ if (parent == null)
+ return hash;
+
+ IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
+ while (it.MoveNext ()) {
+ hash [it.Key] = ((ArrayList) it.Value).Clone ();
+ }
+
+ return hash;
+ }
+
+ /// <summary>
+ /// Add the contents of `cache' to the member_hash.
+ /// </summary>
+ void AddCacheContents (MemberCache cache)
+ {
+ IDictionaryEnumerator it = cache.member_hash.GetEnumerator ();
+ while (it.MoveNext ()) {
+ ArrayList list = (ArrayList) member_hash [it.Key];
+ if (list == null)
+ member_hash [it.Key] = list = new ArrayList ();
+
+ ArrayList entries = (ArrayList) it.Value;
+ for (int i = entries.Count-1; i >= 0; i--) {
+ CacheEntry entry = (CacheEntry) entries [i];
+
+ if (entry.Container != cache.Container)
+ break;
+ list.Add (entry);
+ }
+ }
+ }
+
+ /// <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.
+ if (!container.IsInterface) {
+ 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);
+
+ foreach (MemberInfo member in members) {
+ string name = member.Name;
+
+ int pos = name.IndexOf ('<');
+ if (pos > 0)
+ name = name.Substring (0, pos);
+
+ // 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);
+
+ Array.Reverse (members);
+
+ foreach (MethodBase member in members) {
+ string name = member.Name;
+
+ // 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);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("CacheEntry ({0}:{1}:{2})", Container.Name,
+ EntryType, Member);
+ }
+ }
+
+ /// <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>
+ ArrayList global = new ArrayList ();
+ bool using_global = false;
+
+ static MemberInfo [] emptyMemberInfo = new MemberInfo [0];
+
+ public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, string name,
+ MemberFilter filter, object criteria)
+ {
+ if (using_global)
+ throw new Exception ();
+
+ 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 emptyMemberInfo;
+
+ //
+ // 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?
+ //
+ global.Clear ();
+ using_global = true;
+
+ 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 (global))
+ 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;
+ global.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 && (global.Count > 0)){
+ using_global = false;
+
+ return FindMembers (MemberTypes.Method, bf, name, filter, criteria);
+ }
+
+ using_global = false;
+ MemberInfo [] copy = new MemberInfo [global.Count];
+ global.CopyTo (copy);
+ return copy;
+ }
+
+ //
+ // This finds the method or property for us to override. invocationType is the type where
+ // the override is going to be declared, name is the name of the method/property, and
+ // paramTypes is the parameters, if any to the method or property
+ //
+ // Because the MemberCache holds members from this class and all the base classes,
+ // we can avoid tons of reflection stuff.
+ //
+ public MemberInfo FindMemberToOverride (Type invocationType, string name, Type [] paramTypes, bool is_property)
+ {
+ ArrayList applicable;
+ if (method_hash != null && !is_property)
+ applicable = (ArrayList) method_hash [name];
+ else
+ applicable = (ArrayList) member_hash [name];
+
+ if (applicable == null)
+ return null;
+ //
+ // Walk the chain of methods, starting from the top.
+ //
+ for (int i = applicable.Count - 1; i >= 0; i--) {
+ CacheEntry entry = (CacheEntry) applicable [i];
+
+ if ((entry.EntryType & (is_property ? (EntryType.Property | EntryType.Field) : EntryType.Method)) == 0)
+ continue;
+
+ PropertyInfo pi = null;
+ MethodInfo mi = null;
+ FieldInfo fi = null;
+ Type [] cmpAttrs = null;
+
+ if (is_property) {
+ if ((entry.EntryType & EntryType.Field) != 0) {
+ fi = (FieldInfo)entry.Member;
+
+ // TODO: For this case we ignore member type
+ //fb = TypeManager.GetField (fi);
+ //cmpAttrs = new Type[] { fb.MemberType };
+ } else {
+ pi = (PropertyInfo) entry.Member;
+ cmpAttrs = TypeManager.GetArgumentTypes (pi);
+ }
+ } else {
+ mi = (MethodInfo) entry.Member;
+ cmpAttrs = TypeManager.GetArgumentTypes (mi);
+ }
+
+ if (fi != null) {
+ // TODO: Almost duplicate !
+ // Check visibility
+ switch (fi.Attributes & FieldAttributes.FieldAccessMask) {
+ case FieldAttributes.Private:
+ //
+ // A private method is Ok if we are a nested subtype.
+ // The spec actually is not very clear about this, see bug 52458.
+ //
+ if (invocationType != entry.Container.Type &
+ TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))
+ continue;
+
+ break;
+ case FieldAttributes.FamANDAssem:
+ case FieldAttributes.Assembly:
+ //
+ // Check for assembly methods
+ //
+ if (mi.DeclaringType.Assembly != CodeGen.Assembly.Builder)
+ continue;
+ break;
+ }
+ return entry.Member;
+ }
+
+ //
+ // Check the arguments
+ //
+ if (cmpAttrs.Length != paramTypes.Length)
+ continue;
+
+ for (int j = cmpAttrs.Length - 1; j >= 0; j --) {
+ if (!TypeManager.IsEqual (paramTypes [j], cmpAttrs [j]))
+ goto next;
+ }
+
+ //
+ // get one of the methods because this has the visibility info.
+ //
+ if (is_property) {
+ mi = pi.GetGetMethod (true);
+ if (mi == null)
+ mi = pi.GetSetMethod (true);
+ }
+
+ //
+ // Check visibility
+ //
+ switch (mi.Attributes & MethodAttributes.MemberAccessMask) {
+ case MethodAttributes.Private:
+ //
+ // A private method is Ok if we are a nested subtype.
+ // The spec actually is not very clear about this, see bug 52458.
+ //
+ if (invocationType.Equals (entry.Container.Type) ||
+ TypeManager.IsNestedChildOf (invocationType, entry.Container.Type))
+ return entry.Member;
+
+ break;
+ case MethodAttributes.FamANDAssem:
+ case MethodAttributes.Assembly:
+ //
+ // Check for assembly methods
+ //
+ if (mi.DeclaringType.Assembly == CodeGen.Assembly.Builder)
+ return entry.Member;
+
+ break;
+ default:
+ //
+ // A protected method is ok, because we are overriding.
+ // public is always ok.
+ //
+ return entry.Member;
+ }
+ next:
+ ;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// The method is looking for conflict with inherited symbols (errors CS0108, CS0109).
+ /// We handle two cases. The first is for types without parameters (events, field, properties).
+ /// The second are methods, indexers and this is why ignore_complex_types is here.
+ /// The latest param is temporary hack. See DoDefineMembers method for more info.
+ /// </summary>
+ public MemberInfo FindMemberWithSameName (string name, bool ignore_complex_types, MemberInfo ignore_member)
+ {
+ ArrayList applicable = null;
+
+ if (method_hash != null)
+ applicable = (ArrayList) method_hash [name];
+
+ if (applicable != null) {
+ for (int i = applicable.Count - 1; i >= 0; i--) {
+ CacheEntry entry = (CacheEntry) applicable [i];
+ if ((entry.EntryType & EntryType.Public) != 0)
+ return entry.Member;
+ }
+ }
+
+ if (member_hash == null)
+ return null;
+ applicable = (ArrayList) member_hash [name];
+
+ if (applicable != null) {
+ for (int i = applicable.Count - 1; i >= 0; i--) {
+ CacheEntry entry = (CacheEntry) applicable [i];
+ if ((entry.EntryType & EntryType.Public) != 0 & entry.Member != ignore_member) {
+ if (ignore_complex_types) {
+ if ((entry.EntryType & EntryType.Method) != 0)
+ continue;
+
+ // Does exist easier way how to detect indexer ?
+ if ((entry.EntryType & EntryType.Property) != 0) {
+ Type[] arg_types = TypeManager.GetArgumentTypes ((PropertyInfo)entry.Member);
+ if (arg_types.Length > 0)
+ continue;
+ }
+ }
+ return entry.Member;
+ }
+ }
+ }
+ return null;
+ }
+
+ Hashtable locase_table;
+
+ /// <summary>
+ /// Builds low-case table for CLS Compliance test
+ /// </summary>
+ public Hashtable GetPublicMembers ()
+ {
+ if (locase_table != null)
+ return locase_table;
+
+ locase_table = new Hashtable ();
+ foreach (DictionaryEntry entry in member_hash) {
+ ArrayList members = (ArrayList)entry.Value;
+ for (int ii = 0; ii < members.Count; ++ii) {
+ CacheEntry member_entry = (CacheEntry) members [ii];
+
+ if ((member_entry.EntryType & EntryType.Public) == 0)
+ continue;
+
+ // TODO: Does anyone know easier way how to detect that member is internal ?
+ switch (member_entry.EntryType & EntryType.MaskType) {
+ case EntryType.Constructor:
+ continue;
+
+ case EntryType.Field:
+ if ((((FieldInfo)member_entry.Member).Attributes & (FieldAttributes.Assembly | FieldAttributes.Public)) == FieldAttributes.Assembly)
+ continue;
+ break;
+
+ case EntryType.Method:
+ if ((((MethodInfo)member_entry.Member).Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly)
+ continue;
+ break;
+
+ case EntryType.Property:
+ PropertyInfo pi = (PropertyInfo)member_entry.Member;
+ if (pi.GetSetMethod () == null && pi.GetGetMethod () == null)
+ continue;
+ break;
+
+ case EntryType.Event:
+ EventInfo ei = (EventInfo)member_entry.Member;
+ MethodInfo mi = ei.GetAddMethod ();
+ if ((mi.Attributes & (MethodAttributes.Assembly | MethodAttributes.Public)) == MethodAttributes.Assembly)
+ continue;
+ break;
+ }
+ string lcase = ((string)entry.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture);
+ locase_table [lcase] = member_entry.Member;
+ break;
+ }
+ }
+ return locase_table;
+ }
+
+ public Hashtable Members {
+ get {
+ return member_hash;
+ }
+ }
+
+ /// <summary>
+ /// Cls compliance check whether methods or constructors parameters differing only in ref or out, or in array rank
+ /// </summary>
+ public void VerifyClsParameterConflict (ArrayList al, MethodCore method, MemberInfo this_builder)
+ {
+ EntryType tested_type = (method is Constructor ? EntryType.Constructor : EntryType.Method) | EntryType.Public;
+
+ for (int i = 0; i < al.Count; ++i) {
+ MemberCache.CacheEntry entry = (MemberCache.CacheEntry) al [i];
+
+ // skip itself
+ if (entry.Member == this_builder)
+ continue;
+
+ if ((entry.EntryType & tested_type) != tested_type)
+ continue;
+
+ MethodBase method_to_compare = (MethodBase)entry.Member;
+ if (AttributeTester.AreOverloadedMethodParamsClsCompliant (method.ParameterTypes, TypeManager.GetArgumentTypes (method_to_compare)))
+ continue;
+
+ IMethodData md = TypeManager.GetMethod (method_to_compare);
+
+ // TODO: now we are ignoring CLSCompliance(false) on method from other assembly which is buggy.
+ // However it is exactly what csc does.
+ if (md != null && !md.IsClsCompliaceRequired (method.Parent))
+ continue;
+
+ Report.SymbolRelatedToPreviousError (entry.Member);
+ Report.Error (3006, method.Location, "Overloaded method '{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ());
+ }
+ }
+ }
+}
--- /dev/null
+//
+// delegate.cs: Delegate Handler
+//
+// Authors:
+// Ravi Pratap (ravi@ximian.com)
+// 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.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+
+namespace Mono.CSharp {
+
+ /// <summary>
+ /// Holds Delegates
+ /// </summary>
+ public class Delegate : DeclSpace {
+ public Expression ReturnType;
+ public Parameters Parameters;
+
+ public ConstructorBuilder ConstructorBuilder;
+ public MethodBuilder InvokeBuilder;
+ public MethodBuilder BeginInvokeBuilder;
+ public MethodBuilder EndInvokeBuilder;
+
+ Type [] param_types;
+ Type ret_type;
+
+ static string[] attribute_targets = new string [] { "type", "return" };
+
+ Expression instance_expr;
+ MethodBase delegate_method;
+ ReturnParameter return_attributes;
+
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.UNSAFE |
+ Modifiers.PRIVATE;
+
+ public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,
+ int mod_flags, MemberName name, Parameters param_list,
+ Attributes attrs, Location l)
+ : base (ns, parent, name, attrs, l)
+
+ {
+ this.ReturnType = type;
+ ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
+ IsTopLevel ? Modifiers.INTERNAL :
+ Modifiers.PRIVATE, l);
+ Parameters = param_list;
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Target == AttributeTargets.ReturnValue) {
+ if (return_attributes == null)
+ return_attributes = new ReturnParameter (InvokeBuilder, Location);
+
+ return_attributes.ApplyAttributeBuilder (a, cb);
+ return;
+ }
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override TypeBuilder DefineType ()
+ {
+ if (TypeBuilder != null)
+ return TypeBuilder;
+
+ ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
+
+ if (IsGeneric) {
+ foreach (TypeParameter type_param in TypeParameters)
+ if (!type_param.Resolve (this))
+ return null;
+ }
+
+ TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) |
+ TypeAttributes.Class | TypeAttributes.Sealed;
+
+ if (IsTopLevel) {
+ if (TypeManager.NamespaceClash (Name, Location))
+ return null;
+
+ ModuleBuilder builder = CodeGen.Module.Builder;
+
+ TypeBuilder = builder.DefineType (
+ Name, attr, TypeManager.multicast_delegate_type);
+ } else {
+ TypeBuilder builder = Parent.TypeBuilder;
+
+ string name = Name.Substring (1 + Name.LastIndexOf ('.'));
+ TypeBuilder = builder.DefineNestedType (
+ name, attr, TypeManager.multicast_delegate_type);
+ }
+
+ TypeManager.AddDelegateType (Name, TypeBuilder, this);
+
+ if (IsGeneric) {
+ string[] param_names = new string [TypeParameters.Length];
+ for (int i = 0; i < TypeParameters.Length; i++)
+ param_names [i] = TypeParameters [i].Name;
+
+ GenericTypeParameterBuilder[] gen_params;
+
+ gen_params = TypeBuilder.DefineGenericParameters (param_names);
+
+ for (int i = 0; i < gen_params.Length; i++)
+ TypeParameters [i].Define (gen_params [i]);
+
+ foreach (TypeParameter type_param in TypeParameters) {
+ if (!type_param.DefineType (ec))
+ return null;
+ }
+
+ TypeExpr current = new ConstructedType (Name, TypeParameters, Location);
+ current = current.ResolveAsTypeTerminal (ec);
+ if (current == null)
+ return null;
+
+ CurrentType = current.Type;
+ }
+
+ return TypeBuilder;
+ }
+
+ public override bool DefineMembers (TypeContainer container)
+ {
+ return true;
+ }
+
+ public override bool Define ()
+ {
+ MethodAttributes mattr;
+ int i;
+ ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
+
+ if (IsGeneric) {
+ foreach (TypeParameter type_param in TypeParameters)
+ type_param.DefineType (ec);
+ }
+
+ // FIXME: POSSIBLY make this static, as it is always constant
+ //
+ Type [] const_arg_types = new Type [2];
+ const_arg_types [0] = TypeManager.object_type;
+ const_arg_types [1] = TypeManager.intptr_type;
+
+ mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
+ MethodAttributes.HideBySig | MethodAttributes.Public;
+
+ ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,
+ CallingConventions.Standard,
+ const_arg_types);
+
+ ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
+ ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
+ //
+ // HACK because System.Reflection.Emit is lame
+ //
+ //
+ // FIXME: POSSIBLY make these static, as they are always the same
+ Parameter [] fixed_pars = new Parameter [2];
+ fixed_pars [0] = new Parameter (TypeManager.system_object_expr, "object",
+ Parameter.Modifier.NONE, null);
+ fixed_pars [1] = new Parameter (TypeManager.system_intptr_expr, "method",
+ Parameter.Modifier.NONE, null);
+ Parameters const_parameters = new Parameters (fixed_pars, null, Location);
+
+ TypeManager.RegisterMethod (
+ ConstructorBuilder,
+ new InternalParameters (const_arg_types, const_parameters),
+ const_arg_types);
+
+
+ ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+ //
+ // Here the various methods like Invoke, BeginInvoke etc are defined
+ //
+ // First, call the `out of band' special method for
+ // defining recursively any types we need:
+
+ if (!Parameters.ComputeAndDefineParameterTypes (ec))
+ return false;
+
+ param_types = Parameters.GetParameterInfo (ec);
+ if (param_types == null)
+ return false;
+
+ //
+ // Invoke method
+ //
+
+ // Check accessibility
+ foreach (Type partype in param_types){
+ if (!Parent.AsAccessible (partype, ModFlags)) {
+ Report.Error (59, Location,
+ "Inconsistent accessibility: parameter type `" +
+ TypeManager.CSharpName (partype) + "` is less " +
+ "accessible than delegate `" + Name + "'");
+ return false;
+ }
+ if (partype.IsPointer && !UnsafeOK (Parent))
+ return false;
+ }
+
+ ReturnType = ReturnType.ResolveAsTypeTerminal (ec);
+ if (ReturnType == null)
+ return false;
+
+ ret_type = ReturnType.Type;
+ if (ret_type == null)
+ return false;
+
+ if (!Parent.AsAccessible (ret_type, ModFlags)) {
+ Report.Error (58, Location,
+ "Inconsistent accessibility: return type `" +
+ TypeManager.CSharpName (ret_type) + "` is less " +
+ "accessible than delegate `" + Name + "'");
+ return false;
+ }
+
+ if (ret_type.IsPointer && !UnsafeOK (Parent))
+ return false;
+
+ //
+ // We don't have to check any others because they are all
+ // guaranteed to be accessible - they are standard types.
+ //
+
+ CallingConventions cc = Parameters.GetCallingConvention ();
+
+ mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
+
+ InvokeBuilder = TypeBuilder.DefineMethod ("Invoke",
+ mattr,
+ cc,
+ ret_type,
+ param_types);
+
+ //
+ // Define parameters, and count out/ref parameters
+ //
+ int out_params = 0;
+ i = 0;
+ if (Parameters.FixedParameters != null){
+ int top = Parameters.FixedParameters.Length;
+ Parameter p;
+
+ for (; i < top; i++) {
+ p = Parameters.FixedParameters [i];
+ p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
+
+ if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
+ out_params++;
+ }
+ }
+ if (Parameters.ArrayParameter != null){
+ Parameter p = Parameters.ArrayParameter;
+ p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
+ }
+
+ InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+ TypeManager.RegisterMethod (InvokeBuilder,
+ new InternalParameters (param_types, Parameters),
+ param_types);
+
+ //
+ // BeginInvoke
+ //
+ int params_num = param_types.Length;
+ Type [] async_param_types = new Type [params_num + 2];
+
+ param_types.CopyTo (async_param_types, 0);
+
+ async_param_types [params_num] = TypeManager.asynccallback_type;
+ async_param_types [params_num + 1] = TypeManager.object_type;
+
+ mattr = MethodAttributes.Public | MethodAttributes.HideBySig |
+ MethodAttributes.Virtual | MethodAttributes.NewSlot;
+
+ BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
+ mattr,
+ cc,
+ TypeManager.iasyncresult_type,
+ async_param_types);
+
+ i = 0;
+ if (Parameters.FixedParameters != null){
+ int top = Parameters.FixedParameters.Length;
+ Parameter p;
+
+ for (i = 0 ; i < top; i++) {
+ p = Parameters.FixedParameters [i];
+
+ p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
+ }
+ }
+ if (Parameters.ArrayParameter != null){
+ Parameter p = Parameters.ArrayParameter;
+ p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
+
+ i++;
+ }
+
+ BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");
+ BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");
+
+ BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+ Parameter [] async_params = new Parameter [params_num + 2];
+ int n = 0;
+ if (Parameters.FixedParameters != null){
+ Parameters.FixedParameters.CopyTo (async_params, 0);
+ n = Parameters.FixedParameters.Length;
+ }
+ if (Parameters.ArrayParameter != null)
+ async_params [n] = Parameters.ArrayParameter;
+
+ async_params [params_num] = new Parameter (
+ TypeManager.system_asynccallback_expr, "callback",
+ Parameter.Modifier.NONE, null);
+ async_params [params_num + 1] = new Parameter (
+ TypeManager.system_object_expr, "object",
+ Parameter.Modifier.NONE, null);
+
+ Parameters async_parameters = new Parameters (async_params, null, Location);
+ async_parameters.ComputeAndDefineParameterTypes (ec);
+
+ TypeManager.RegisterMethod (BeginInvokeBuilder,
+ new InternalParameters (async_param_types, async_parameters),
+ async_param_types);
+
+ //
+ // EndInvoke is a bit more interesting, all the parameters labeled as
+ // out or ref have to be duplicated here.
+ //
+
+ Type [] end_param_types = new Type [out_params + 1];
+ Parameter [] end_params = new Parameter [out_params + 1];
+ int param = 0;
+ if (out_params > 0){
+ int top = Parameters.FixedParameters.Length;
+ for (i = 0; i < top; i++){
+ Parameter p = Parameters.FixedParameters [i];
+ if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
+ continue;
+
+ end_param_types [param] = param_types [i];
+ end_params [param] = p;
+ param++;
+ }
+ }
+ end_param_types [out_params] = TypeManager.iasyncresult_type;
+ end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null);
+
+ //
+ // Create method, define parameters, register parameters with type system
+ //
+ EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);
+ EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+ //
+ // EndInvoke: Label the parameters
+ //
+ EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");
+ for (i = 0; i < end_params.Length-1; i++){
+ EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);
+ }
+
+ Parameters end_parameters = new Parameters (end_params, null, Location);
+ end_parameters.ComputeAndDefineParameterTypes (ec);
+
+ TypeManager.RegisterMethod (
+ EndInvokeBuilder,
+ new InternalParameters (end_param_types, end_parameters),
+ end_param_types);
+
+ return true;
+ }
+
+ public override void Emit ()
+ {
+ if (OptAttributes != null) {
+ Parameters.LabelParameters (ec, InvokeBuilder, Location);
+ OptAttributes.Emit (ec, this);
+ }
+
+ base.Emit ();
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ //TODO: duplicate
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds)) {
+ return false;
+ }
+
+ AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
+
+ if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
+ Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant", GetSignatureForError ());
+ }
+ return true;
+ }
+
+ //
+ // Returns the MethodBase for "Invoke" from a delegate type, this is used
+ // to extract the signature of a delegate.
+ //
+ public static MethodGroupExpr GetInvokeMethod (EmitContext ec, Type delegate_type,
+ Location loc)
+ {
+ Expression ml = Expression.MemberLookup (
+ ec, delegate_type, "Invoke", loc);
+
+ MethodGroupExpr mg = ml as MethodGroupExpr;
+ if (mg == null) {
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+ return null;
+ }
+
+ return mg;
+ }
+
+ /// <summary>
+ /// Verifies whether the method in question is compatible with the delegate
+ /// Returns the method itself if okay and null if not.
+ /// </summary>
+ public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,
+ Location loc)
+ {
+ MethodGroupExpr mg = GetInvokeMethod (ec, delegate_type, loc);
+ if (mg == null)
+ return null;
+
+ MethodBase invoke_mb = mg.Methods [0];
+ ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+ if (!mg.HasTypeArguments &&
+ !TypeManager.InferTypeArguments (ec, invoke_pd, ref mb))
+ return null;
+
+ ParameterData pd = Invocation.GetParameterData (mb);
+ int pd_count = pd.Count;
+
+ if (invoke_pd.Count != pd_count)
+ return null;
+
+ for (int i = pd_count; i > 0; ) {
+ i--;
+
+ Type invoke_pd_type = invoke_pd.ParameterType (i);
+ Type pd_type = pd.ParameterType (i);
+ Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);
+ Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);
+
+ if (invoke_pd_type == pd_type &&
+ invoke_pd_type_mod == pd_type_mod)
+ continue;
+
+ if (invoke_pd_type.IsSubclassOf (pd_type) &&
+ invoke_pd_type_mod == pd_type_mod)
+ if (RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (loc, "contravariance");
+ return null;
+ } else
+ continue;
+
+ return null;
+ }
+
+ Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;
+ Type mb_retval = ((MethodInfo) mb).ReturnType;
+ if (invoke_mb_retval == mb_retval)
+ return mb;
+
+ if (mb_retval.IsSubclassOf (invoke_mb_retval))
+ if (RootContext.Version == LanguageVersion.ISO_1) {
+ Report.FeatureIsNotStandardized (loc, "covariance");
+ return null;
+ }
+ else
+ return mb;
+
+ return null;
+ }
+
+ // <summary>
+ // Verifies whether the invocation arguments are compatible with the
+ // delegate's target method
+ // </summary>
+ public static bool VerifyApplicability (EmitContext ec, Type delegate_type,
+ ArrayList args, Location loc)
+ {
+ int arg_count;
+
+ if (args == null)
+ arg_count = 0;
+ else
+ arg_count = args.Count;
+
+ Expression ml = Expression.MemberLookup (
+ ec, delegate_type, "Invoke", loc);
+
+ if (!(ml is MethodGroupExpr)) {
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);
+ return false;
+ }
+
+ MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
+ ParameterData pd = Invocation.GetParameterData (mb);
+
+ int pd_count = pd.Count;
+
+ bool params_method = (pd_count != 0) &&
+ (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS);
+
+ if (!params_method && pd_count != arg_count) {
+ Report.Error (1593, loc,
+ "Delegate '{0}' does not take {1} arguments",
+ delegate_type.ToString (), arg_count);
+ return false;
+ }
+
+ //
+ // Consider the case:
+ // delegate void FOO(param object[] args);
+ // FOO f = new FOO(...);
+ // f(new object[] {1, 2, 3});
+ //
+ // This should be treated like f(1,2,3). This is done by ignoring the
+ // 'param' modifier for that invocation. If that fails, then the
+ // 'param' modifier is considered.
+ //
+ // One issue is that 'VerifyArgumentsCompat' modifies the elements of
+ // the 'args' array. However, the modifications appear idempotent.
+ // Normal 'Invocation's also have the same behaviour, implicitly.
+ //
+
+ bool ans = false;
+ if (arg_count == pd_count)
+ ans = Invocation.VerifyArgumentsCompat (
+ ec, args, arg_count, mb, false,
+ delegate_type, false, loc);
+ if (!ans && params_method)
+ ans = Invocation.VerifyArgumentsCompat (
+ ec, args, arg_count, mb, true,
+ delegate_type, false, loc);
+ return ans;
+ }
+
+ /// <summary>
+ /// Verifies whether the delegate in question is compatible with this one in
+ /// order to determine if instantiation from the same is possible.
+ /// </summary>
+ public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)
+ {
+ Expression ml = Expression.MemberLookup (
+ ec, delegate_type, "Invoke", loc);
+
+ if (!(ml is MethodGroupExpr)) {
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+ return false;
+ }
+
+ MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
+ ParameterData pd = Invocation.GetParameterData (mb);
+
+ Expression probe_ml = Expression.MemberLookup (
+ ec, delegate_type, "Invoke", loc);
+
+ if (!(probe_ml is MethodGroupExpr)) {
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+ return false;
+ }
+
+ MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
+ ParameterData probe_pd = Invocation.GetParameterData (probe_mb);
+
+ if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
+ return false;
+
+ if (pd.Count != probe_pd.Count)
+ return false;
+
+ for (int i = pd.Count; i > 0; ) {
+ i--;
+
+ if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||
+ pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))
+ return false;
+ }
+
+ return true;
+ }
+
+ public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)
+ {
+ StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));
+
+ sb.Append (" " + del_type.ToString ());
+ sb.Append (" (");
+
+ int length = pd.Count;
+
+ for (int i = length; i > 0; ) {
+ i--;
+
+ sb.Append (pd.ParameterDesc (length - i - 1));
+ if (i != 0)
+ sb.Append (", ");
+ }
+
+ sb.Append (")");
+ return sb.ToString ();
+
+ }
+
+ // 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) {
+ if (ConstructorBuilder != null)
+ if (filter (ConstructorBuilder, criteria))
+ members.Add (ConstructorBuilder);
+
+ if (InvokeBuilder != null)
+ if (filter (InvokeBuilder, criteria))
+ members.Add (InvokeBuilder);
+
+ if (BeginInvokeBuilder != null)
+ if (filter (BeginInvokeBuilder, criteria))
+ members.Add (BeginInvokeBuilder);
+
+ if (EndInvokeBuilder != null)
+ if (filter (EndInvokeBuilder, criteria))
+ members.Add (EndInvokeBuilder);
+ }
+
+ return new MemberList (members);
+ }
+
+ public override MemberCache MemberCache {
+ get {
+ return null;
+ }
+ }
+
+ public Expression InstanceExpression {
+ get {
+ return instance_expr;
+ }
+ set {
+ instance_expr = value;
+ }
+ }
+
+ public MethodBase TargetMethod {
+ get {
+ return delegate_method;
+ }
+ set {
+ delegate_method = value;
+ }
+ }
+
+ public Type TargetReturnType {
+ get {
+ return ret_type;
+ }
+ }
+
+ public Type [] ParameterTypes {
+ get {
+ return param_types;
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Delegate;
+ }
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ CheckUsageOfObsoleteAttribute (ret_type);
+
+ foreach (Type type in param_types) {
+ CheckUsageOfObsoleteAttribute (type);
+ }
+ }
+ }
+
+ //
+ // Base class for `NewDelegate' and `ImplicitDelegateCreation'
+ //
+ public abstract class DelegateCreation : Expression {
+ protected MethodBase constructor_method;
+ protected MethodBase delegate_method;
+ protected MethodGroupExpr method_group;
+ protected Expression delegate_instance_expression;
+
+ public DelegateCreation () {}
+
+ public static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc)
+ {
+ string method_desc;
+
+ MethodBase candidate = mg.Methods [0];
+ if (mg.Methods.Length > 1)
+ method_desc = candidate.Name;
+ else
+ method_desc = Invocation.FullMethodDesc (candidate);
+
+ Expression invoke_method = Expression.MemberLookup (
+ ec, type, "Invoke", MemberTypes.Method,
+ Expression.AllBindingFlags, loc);
+ MethodBase method = ((MethodGroupExpr) invoke_method).Methods [0];
+ ParameterData param = Invocation.GetParameterData (method);
+ string delegate_desc = Delegate.FullDelegateDesc (type, method, param);
+
+ if (!mg.HasTypeArguments &&
+ !TypeManager.InferTypeArguments (ec, param, ref candidate))
+ Report.Error (411, loc, "The type arguments for " +
+ "method `{0}' cannot be infered from " +
+ "the usage. Try specifying the type " +
+ "arguments explicitly.", method_desc);
+ else
+ Report.Error (123, loc, "Method '{0}' does not " +
+ "match delegate '{1}'", method_desc,
+ delegate_desc);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (delegate_instance_expression == null || delegate_method.IsStatic)
+ ec.ig.Emit (OpCodes.Ldnull);
+ else
+ delegate_instance_expression.Emit (ec);
+
+ if (delegate_method.IsVirtual && !method_group.IsBase) {
+ ec.ig.Emit (OpCodes.Dup);
+ ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);
+ } else
+ ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
+ ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);
+ }
+
+ protected bool ResolveConstructorMethod (EmitContext ec)
+ {
+ Expression ml = Expression.MemberLookup (
+ ec, type, ".ctor", loc);
+
+ if (!(ml is MethodGroupExpr)) {
+ Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");
+ return false;
+ }
+
+ constructor_method = ((MethodGroupExpr) ml).Methods [0];
+ return true;
+ }
+
+ protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)
+ {
+ foreach (MethodInfo mi in mg.Methods){
+ delegate_method = Delegate.VerifyMethod (
+ ec, type, mi, loc);
+
+ if (delegate_method != null)
+ break;
+ }
+
+ if (delegate_method == null) {
+ Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
+ return null;
+ }
+
+ //
+ // Check safe/unsafe of the delegate
+ //
+ if (!ec.InUnsafe){
+ ParameterData param = Invocation.GetParameterData (delegate_method);
+ int count = param.Count;
+
+ for (int i = 0; i < count; i++){
+ if (param.ParameterType (i).IsPointer){
+ Expression.UnsafeError (loc);
+ return null;
+ }
+ }
+ }
+
+ //TODO: implement caching when performance will be low
+ IMethodData md = TypeManager.GetMethod (delegate_method);
+ if (md == null) {
+ if (System.Attribute.GetCustomAttribute (delegate_method, TypeManager.conditional_attribute_type) != null) {
+ Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+ }
+ } else {
+ if (md.OptAttributes != null && md.OptAttributes.Search (TypeManager.conditional_attribute_type, ec) != null) {
+ Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+ }
+ }
+
+ if (mg.InstanceExpression != null)
+ delegate_instance_expression = mg.InstanceExpression.Resolve (ec);
+ else if (ec.IsStatic) {
+ if (!delegate_method.IsStatic) {
+ Report.Error (120, loc,
+ "An object reference is required for the non-static method " +
+ delegate_method.Name);
+ return null;
+ }
+ delegate_instance_expression = null;
+ } else
+ delegate_instance_expression = ec.GetThis (loc);
+
+ if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType)
+ delegate_instance_expression = new BoxedCast (mg.InstanceExpression);
+
+ method_group = mg;
+ eclass = ExprClass.Value;
+ return this;
+ }
+ }
+
+ //
+ // Created from the conversion code
+ //
+ public class ImplicitDelegateCreation : DelegateCreation {
+
+ ImplicitDelegateCreation (Type t, Location l)
+ {
+ type = t;
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc)
+ {
+ ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);
+ if (d.ResolveConstructorMethod (ec))
+ return d.ResolveMethodGroupExpr (ec, mge);
+ else
+ return null;
+ }
+ }
+
+ //
+ // A delegate-creation-expression, invoked from the `New' class
+ //
+ public class NewDelegate : DelegateCreation {
+ public ArrayList Arguments;
+
+ //
+ // This constructor is invoked from the `New' expression
+ //
+ public NewDelegate (Type type, ArrayList Arguments, Location loc)
+ {
+ this.type = type;
+ this.Arguments = Arguments;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (Arguments == null || Arguments.Count != 1) {
+ Report.Error (149, loc,
+ "Method name expected");
+ return null;
+ }
+
+ if (!ResolveConstructorMethod (ec))
+ return null;
+
+ Argument a = (Argument) Arguments [0];
+
+ if (!a.ResolveMethodGroup (ec, loc))
+ return null;
+
+ Expression e = a.Expr;
+
+ if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
+ return ((AnonymousMethod) e).Compatible (ec, type, false);
+
+ MethodGroupExpr mg = e as MethodGroupExpr;
+ if (mg != null)
+ return ResolveMethodGroupExpr (ec, mg);
+
+ Type e_type = e.Type;
+
+ if (!TypeManager.IsDelegateType (e_type)) {
+ e.Error_UnexpectedKind ("method", loc);
+ return null;
+ }
+
+ method_group = Expression.MemberLookup (
+ ec, type, "Invoke", MemberTypes.Method,
+ Expression.AllBindingFlags, loc) as MethodGroupExpr;
+
+ if (method_group == null) {
+ Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");
+ return null;
+ }
+
+ // This is what MS' compiler reports. We could always choose
+ // to be more verbose and actually give delegate-level specifics
+ if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {
+ Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +
+ "to type '" + type + "'");
+ return null;
+ }
+
+ delegate_instance_expression = e;
+ delegate_method = method_group.Methods [0];
+
+ eclass = ExprClass.Value;
+ return this;
+ }
+ }
+
+ public class DelegateInvocation : ExpressionStatement {
+
+ public Expression InstanceExpr;
+ public ArrayList Arguments;
+
+ MethodBase method;
+
+ public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
+ {
+ this.InstanceExpr = instance_expr;
+ this.Arguments = args;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (InstanceExpr is EventExpr) {
+
+ EventInfo ei = ((EventExpr) InstanceExpr).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
+ // cannot be accessed directly
+ //
+ // 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.
+ //
+
+ Assign.error70 (ei, loc);
+ return null;
+ }
+ }
+
+
+ Type del_type = InstanceExpr.Type;
+ if (del_type == null)
+ return null;
+
+ if (Arguments != null){
+ foreach (Argument a in Arguments){
+ if (!a.Resolve (ec, loc))
+ return null;
+ }
+ }
+
+ if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
+ return null;
+
+ Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);
+ if (!(lookup is MethodGroupExpr)) {
+ Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+ return null;
+ }
+
+ method = ((MethodGroupExpr) lookup).Methods [0];
+ type = ((MethodInfo) method).ReturnType;
+ eclass = ExprClass.Value;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ //
+ // Invocation on delegates call the virtual Invoke member
+ // so we are always `instance' calls
+ //
+ Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ Emit (ec);
+ //
+ // Pop the return value if there is one
+ //
+ if (method is MethodInfo){
+ if (((MethodInfo) method).ReturnType != TypeManager.void_type)
+ ec.ig.Emit (OpCodes.Pop);
+ }
+ }
+
+ }
+}
--- /dev/null
+//
+// doc.cs: Support for XML documentation comment.
+//
+// Author:
+// Atsushi Enomoto <atsushi@ximian.com>
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2004 Novell, Inc.
+//
+//
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Text;
+using System.Xml;
+
+using Mono.CompilerServices.SymbolWriter;
+
+namespace Mono.CSharp {
+
+ //
+ // Support class for XML documentation.
+ //
+ public static class DocUtil
+ {
+ // TypeContainer
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal static void GenerateTypeDocComment (TypeContainer t,
+ DeclSpace ds)
+ {
+ GenerateDocComment (t, ds);
+
+ if (t.DefaultStaticConstructor != null)
+ t.DefaultStaticConstructor.GenerateDocComment (t);
+
+ if (t.InstanceConstructors != null)
+ foreach (Constructor c in t.InstanceConstructors)
+ c.GenerateDocComment (t);
+
+ if (t.Types != null)
+ foreach (TypeContainer tc in t.Types)
+ tc.GenerateDocComment (t);
+
+ if (t.Parts != null) {
+ IDictionary comments = RootContext.Documentation.PartialComments;
+ foreach (ClassPart cp in t.Parts) {
+ if (cp.DocComment == null)
+ continue;
+ comments [cp] = cp;
+ }
+ }
+
+ if (t.Enums != null)
+ foreach (Enum en in t.Enums)
+ en.GenerateDocComment (t);
+
+ if (t.Constants != null)
+ foreach (Const c in t.Constants)
+ c.GenerateDocComment (t);
+
+ if (t.Fields != null)
+ foreach (Field f in t.Fields)
+ f.GenerateDocComment (t);
+
+ if (t.Events != null)
+ foreach (Event e in t.Events)
+ e.GenerateDocComment (t);
+
+ if (t.Indexers != null)
+ foreach (Indexer ix in t.Indexers)
+ ix.GenerateDocComment (t);
+
+ if (t.Properties != null)
+ foreach (Property p in t.Properties)
+ p.GenerateDocComment (t);
+
+ if (t.Methods != null)
+ foreach (Method m in t.Methods)
+ m.GenerateDocComment (t);
+
+ if (t.Operators != null)
+ foreach (Operator o in t.Operators)
+ o.GenerateDocComment (t);
+ }
+
+ // MemberCore
+ private static readonly string lineHead =
+ Environment.NewLine + " ";
+
+ private static XmlNode GetDocCommentNode (MemberCore mc,
+ string name)
+ {
+ // FIXME: It could be even optimizable as not
+ // to use XmlDocument. But anyways the nodes
+ // are not kept in memory.
+ XmlDocument doc = RootContext.Documentation.XmlDocumentation;
+ try {
+ XmlElement el = doc.CreateElement ("member");
+ el.SetAttribute ("name", name);
+ string normalized = mc.DocComment;
+ el.InnerXml = normalized;
+ // csc keeps lines as written in the sources
+ // and inserts formatting indentation (which
+ // is different from XmlTextWriter.Formatting
+ // one), but when a start tag contains an
+ // endline, it joins the next line. We don't
+ // have to follow such a hacky behavior.
+ string [] split =
+ normalized.Split ('\n');
+ int j = 0;
+ for (int i = 0; i < split.Length; i++) {
+ string s = split [i].TrimEnd ();
+ if (s.Length > 0)
+ split [j++] = s;
+ }
+ el.InnerXml = lineHead + String.Join (
+ lineHead, split, 0, j);
+ return el;
+ } catch (XmlException ex) {
+ Report.Warning (1570, 1, mc.Location, "XML comment on '{0}' has non-well-formed XML ({1}).", name, ex.Message);
+ XmlComment com = doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name));
+ return com;
+ }
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal static void GenerateDocComment (MemberCore mc,
+ DeclSpace ds)
+ {
+ if (mc.DocComment != null) {
+ string name = mc.GetDocCommentName (ds);
+
+ XmlNode n = GetDocCommentNode (mc, name);
+
+ XmlElement el = n as XmlElement;
+ if (el != null) {
+ mc.OnGenerateDocComment (ds, el);
+
+ // FIXME: it could be done with XmlReader
+ foreach (XmlElement inc in n.SelectNodes (".//include"))
+ HandleInclude (mc, inc);
+
+ // FIXME: it could be done with XmlReader
+ DeclSpace dsTarget = mc as DeclSpace;
+ if (dsTarget == null)
+ dsTarget = ds;
+
+ foreach (XmlElement see in n.SelectNodes (".//see"))
+ HandleSee (mc, dsTarget, see);
+ foreach (XmlElement seealso in n.SelectNodes (".//seealso"))
+ HandleSeeAlso (mc, dsTarget, seealso);
+ foreach (XmlElement see in n.SelectNodes (".//exception"))
+ HandleException (mc, dsTarget, see);
+ }
+
+ n.WriteTo (RootContext.Documentation.XmlCommentOutput);
+ }
+ else if (mc.IsExposedFromAssembly (ds) &&
+ // There are no warnings when the container also
+ // misses documentations.
+ (ds == null || ds.DocComment != null))
+ {
+ Report.Warning (1591, 4, mc.Location,
+ "Missing XML comment for publicly visible type or member '{0}'", mc.GetSignatureForError ());
+ }
+ }
+
+ //
+ // Processes "include" element. Check included file and
+ // embed the document content inside this documentation node.
+ //
+ private static void HandleInclude (MemberCore mc, XmlElement el)
+ {
+ string file = el.GetAttribute ("file");
+ string path = el.GetAttribute ("path");
+ if (file == "") {
+ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'file' attribute.");
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
+ }
+ else if (path == "") {
+ Report.Warning (1590, 1, mc.Location, "Invalid XML 'include' element; Missing 'path' attribute.");
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el);
+ }
+ else {
+ XmlDocument doc = RootContext.Documentation.StoredDocuments [file] as XmlDocument;
+ if (doc == null) {
+ try {
+ doc = new XmlDocument ();
+ doc.Load (file);
+ RootContext.Documentation.StoredDocuments.Add (file, doc);
+ } catch (Exception) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file '{0}': cannot be included ", file)), el);
+ Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- '{0}'", file);
+ }
+ }
+ bool keepIncludeNode = false;
+ if (doc != null) {
+ try {
+ XmlNodeList nl = doc.SelectNodes (path);
+ if (nl.Count == 0) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el);
+
+ keepIncludeNode = true;
+ }
+ foreach (XmlNode n in nl)
+ el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el);
+ } catch (Exception ex) {
+ el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el);
+ Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment '{0}' of file {1} -- {2}.", path, file, ex.Message);
+ }
+ }
+ if (!keepIncludeNode)
+ el.ParentNode.RemoveChild (el);
+ }
+ }
+
+ //
+ // Handles <see> elements.
+ //
+ private static void HandleSee (MemberCore mc,
+ DeclSpace ds, XmlElement see)
+ {
+ HandleXrefCommon (mc, ds, see);
+ }
+
+ //
+ // Handles <seealso> elements.
+ //
+ private static void HandleSeeAlso (MemberCore mc,
+ DeclSpace ds, XmlElement seealso)
+ {
+ HandleXrefCommon (mc, ds, seealso);
+ }
+
+ //
+ // Handles <exception> elements.
+ //
+ private static void HandleException (MemberCore mc,
+ DeclSpace ds, XmlElement seealso)
+ {
+ HandleXrefCommon (mc, ds, seealso);
+ }
+
+ static readonly char [] wsChars =
+ new char [] {' ', '\t', '\n', '\r'};
+
+ //
+ // returns a full runtime type name from a name which might
+ // be C# specific type name.
+ //
+ private static Type FindDocumentedType (MemberCore mc,
+ string name, DeclSpace ds, bool allowAlias)
+ {
+ bool isArray = false;
+ string identifier = name;
+ if (name [name.Length - 1] == ']') {
+ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
+ if (tmp [tmp.Length - 1] == '[') {
+ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
+ isArray = true;
+ }
+ }
+ Type t = FindDocumentedTypeNonArray (mc, identifier,
+ ds, allowAlias);
+ if (t != null && isArray)
+ t = Array.CreateInstance (t, 0).GetType ();
+ return t;
+ }
+
+ private static Type FindDocumentedTypeNonArray (MemberCore mc,
+ string identifier, DeclSpace ds, bool allowAlias)
+ {
+ switch (identifier) {
+ case "int":
+ return typeof (int);
+ case "uint":
+ return typeof (uint);
+ case "short":
+ return typeof (short);
+ case "ushort":
+ return typeof (ushort);
+ case "long":
+ return typeof (long);
+ case "ulong":
+ return typeof (ulong);
+ case "float":
+ return typeof (float);
+ case "double":
+ return typeof (double);
+ case "char":
+ return typeof (char);
+ case "decimal":
+ return typeof (decimal);
+ case "byte":
+ return typeof (byte);
+ case "sbyte":
+ return typeof (sbyte);
+ case "object":
+ return typeof (object);
+ case "bool":
+ return typeof (bool);
+ case "string":
+ return typeof (string);
+ case "void":
+ return typeof (void);
+ }
+ if (allowAlias) {
+ IAlias alias = ds.LookupAlias (identifier);
+ if (alias != null)
+ identifier = alias.Name;
+ }
+ Type t = ds.FindType (mc.Location, identifier);
+ if (t == null)
+ t = TypeManager.LookupTypeDirect (identifier);
+ return t;
+ }
+
+ //
+ // Returns a MemberInfo that is referenced in XML documentation
+ // (by "see" or "seealso" elements).
+ //
+ private static MemberInfo FindDocumentedMember (MemberCore mc,
+ Type type, string memberName, Type [] paramList,
+ DeclSpace ds, out int warningType, string cref)
+ {
+ warningType = 0;
+ MethodSignature msig = new MethodSignature (memberName, null, paramList);
+ MemberInfo [] mis = type.FindMembers (
+ MemberTypes.All,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
+ MethodSignature.method_signature_filter,
+ msig);
+ if (mis.Length > 0)
+ return mis [0];
+
+ if (paramList.Length == 0) {
+ // search for fields/events etc.
+ mis = type.FindMembers (
+ MemberTypes.All,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
+ Type.FilterName,
+ memberName);
+ return (mis.Length > 0) ? mis [0] : null;
+ }
+
+ // search for operators (whose parameters exactly
+ // matches with the list) and possibly report CS1581.
+ string oper = null;
+ string returnTypeName = null;
+ if (memberName.StartsWith ("implicit operator ")) {
+ oper = "op_Implicit";
+ returnTypeName = memberName.Substring (18).Trim (wsChars);
+ }
+ else if (memberName.StartsWith ("explicit operator ")) {
+ oper = "op_Explicit";
+ returnTypeName = memberName.Substring (18).Trim (wsChars);
+ }
+ else if (memberName.StartsWith ("operator ")) {
+ oper = memberName.Substring (9).Trim (wsChars);
+ switch (oper) {
+ // either unary or binary
+ case "+":
+ oper = paramList.Length == 2 ?
+ Binary.oper_names [(int) Binary.Operator.Addition] :
+ Unary.oper_names [(int) Unary.Operator.UnaryPlus];
+ break;
+ case "-":
+ oper = paramList.Length == 2 ?
+ Binary.oper_names [(int) Binary.Operator.Subtraction] :
+ Unary.oper_names [(int) Unary.Operator.UnaryNegation];
+ break;
+ // unary
+ case "!":
+ oper = Unary.oper_names [(int) Unary.Operator.LogicalNot]; break;
+ case "~":
+ oper = Unary.oper_names [(int) Unary.Operator.OnesComplement]; break;
+
+ case "++":
+ oper = "op_Increment"; break;
+ case "--":
+ oper = "op_Decrement"; break;
+ case "true":
+ oper = "op_True"; break;
+ case "false":
+ oper = "op_False"; break;
+ // binary
+ case "*":
+ oper = Binary.oper_names [(int) Binary.Operator.Multiply]; break;
+ case "/":
+ oper = Binary.oper_names [(int) Binary.Operator.Division]; break;
+ case "%":
+ oper = Binary.oper_names [(int) Binary.Operator.Modulus]; break;
+ case "&":
+ oper = Binary.oper_names [(int) Binary.Operator.BitwiseAnd]; break;
+ case "|":
+ oper = Binary.oper_names [(int) Binary.Operator.BitwiseOr]; break;
+ case "^":
+ oper = Binary.oper_names [(int) Binary.Operator.ExclusiveOr]; break;
+ case "<<":
+ oper = Binary.oper_names [(int) Binary.Operator.LeftShift]; break;
+ case ">>":
+ oper = Binary.oper_names [(int) Binary.Operator.RightShift]; break;
+ case "==":
+ oper = Binary.oper_names [(int) Binary.Operator.Equality]; break;
+ case "!=":
+ oper = Binary.oper_names [(int) Binary.Operator.Inequality]; break;
+ case "<":
+ oper = Binary.oper_names [(int) Binary.Operator.LessThan]; break;
+ case ">":
+ oper = Binary.oper_names [(int) Binary.Operator.GreaterThan]; break;
+ case "<=":
+ oper = Binary.oper_names [(int) Binary.Operator.LessThanOrEqual]; break;
+ case ">=":
+ oper = Binary.oper_names [(int) Binary.Operator.GreaterThanOrEqual]; break;
+ default:
+ warningType = 1584;
+ Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", paramList.Length == 2 ? "binary" : "unary");
+ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
+ return null;
+ }
+ }
+ // here we still does not consider return type (to
+ // detect CS1581 or CS1002+CS1584).
+ msig = new MethodSignature (oper, null, paramList);
+ mis = type.FindMembers (
+ MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static,
+ MethodSignature.method_signature_filter,
+ msig);
+ if (mis.Length == 0)
+ return null; // CS1574
+ MemberInfo mi = mis [0];
+ Type expected = mi is MethodInfo ?
+ ((MethodInfo) mi).ReturnType :
+ mi is PropertyInfo ?
+ ((PropertyInfo) mi).PropertyType :
+ null;
+ if (returnTypeName != null) {
+ Type returnType = FindDocumentedType (mc, returnTypeName, ds, true);
+ if (returnType == null || returnType != expected) {
+ warningType = 1581;
+ Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute '{0}'", cref);
+ return null;
+ }
+ }
+ return mis [0];
+ }
+
+ private static Type [] emptyParamList = new Type [0];
+
+ //
+ // Processes "see" or "seealso" elements.
+ // Checks cref attribute.
+ //
+ private static void HandleXrefCommon (MemberCore mc,
+ DeclSpace ds, XmlElement xref)
+ {
+ string cref = xref.GetAttribute ("cref").Trim (wsChars);
+ // when, XmlReader, "if (cref == null)"
+ if (!xref.HasAttribute ("cref"))
+ return;
+ if (cref.Length == 0)
+ Report.Warning (1001, 1, mc.Location, "Identifier expected");
+ // ... and continue until CS1584.
+
+ string signature; // "x:" are stripped
+ string name; // method invokation "(...)" are removed
+ string identifiers; // array indexer "[]" are removed
+ string parameters; // method parameter list
+
+ // strip 'T:' 'M:' 'F:' 'P:' 'E:' etc.
+ // Here, MS ignores its member kind. No idea why.
+ if (cref.Length > 2 && cref [1] == ':')
+ signature = cref.Substring (2).Trim (wsChars);
+ else
+ signature = cref;
+
+ int parensPos = signature.IndexOf ('(');
+ if (parensPos > 0 && signature [signature.Length - 1] == ')') {
+ name = signature.Substring (0, parensPos).Trim (wsChars);
+ parameters = signature.Substring (parensPos + 1, signature.Length - parensPos - 2);
+ }
+ else {
+ name = signature;
+ parameters = String.Empty;
+ }
+
+ string identifier = name;
+
+ if (name.Length > 0 && name [name.Length - 1] == ']') {
+ string tmp = name.Substring (0, name.Length - 1).Trim (wsChars);
+ if (tmp [tmp.Length - 1] == '[')
+ identifier = tmp.Substring (0, tmp.Length - 1).Trim (wsChars);
+ }
+
+ // Check if identifier is valid.
+ // This check is not necessary to mark as error, but
+ // csc specially reports CS1584 for wrong identifiers.
+ foreach (string nameElem in identifier.Split ('.')) {
+ if (!Tokenizer.IsValidIdentifier (nameElem)
+ && nameElem.IndexOf ("operator") < 0) {
+ if (nameElem.EndsWith ("[]") &&
+ Tokenizer.IsValidIdentifier (
+ nameElem.Substring (
+ 0, nameElem.Length - 2)))
+ continue;
+
+ Report.Warning (1584, 1, mc.Location, "XML comment on '{0}' has syntactically incorrect attribute '{1}'", mc.GetSignatureForError (), cref);
+ xref.SetAttribute ("cref", "!:" + signature);
+ return;
+ }
+ }
+
+ // check if parameters are valid
+ Type [] parameterTypes = emptyParamList;
+ if (parameters.Length > 0) {
+ string [] paramList = parameters.Split (',');
+ ArrayList plist = new ArrayList ();
+ for (int i = 0; i < paramList.Length; i++) {
+ string paramTypeName = paramList [i].Trim (wsChars);
+ Type paramType = FindDocumentedType (mc, paramTypeName, ds, true);
+ if (paramType == null) {
+ Report.Warning (1580, 1, mc.Location, "Invalid type for parameter '{0}' in XML comment cref attribute '{1}'", i + 1, cref);
+ return;
+ }
+ plist.Add (paramType);
+ }
+ parameterTypes = plist.ToArray (typeof (Type)) as Type [];
+ StringBuilder sb = new StringBuilder ();
+ sb.Append ('(');
+ for (int i = 0; i < parameterTypes.Length; i++) {
+ Type t = parameterTypes [i];
+ if (sb.Length > 1)
+ sb.Append (',');
+ sb.Append (t.FullName.Replace ('+', '.'));
+ }
+ sb.Append (')');
+ parameters = sb.ToString ();
+ }
+
+ Type type = FindDocumentedType (mc, name, ds, true);
+ if (type != null) {
+ xref.SetAttribute ("cref", "T:" + type.FullName.Replace ("+", "."));
+ return; // a type
+ }
+
+ // don't use identifier here. System[] is not alloed.
+ if (Namespace.IsNamespace (name)) {
+ xref.SetAttribute ("cref", "N:" + name);
+ return; // a namespace
+ }
+
+ int period = name.LastIndexOf ('.');
+ if (period > 0) {
+ string typeName = name.Substring (0, period);
+ string memberName = name.Substring (period + 1);
+ type = FindDocumentedType (mc, typeName, ds, false);
+ int warnResult;
+ if (type != null) {
+ MemberInfo mi = FindDocumentedMember (mc, type, memberName, parameterTypes, ds, out warnResult, cref);
+ if (warnResult > 0)
+ return;
+ if (mi != null) {
+ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + type.FullName.Replace ("+", ".") + "." + memberName + parameters);
+ return; // a member of a type
+ }
+ }
+ }
+ else {
+ int warnResult;
+ MemberInfo mi = FindDocumentedMember (mc, ds.TypeBuilder, name, parameterTypes, ds, out warnResult, cref);
+ if (warnResult > 0)
+ return;
+ if (mi != null) {
+ xref.SetAttribute ("cref", GetMemberDocHead (mi.MemberType) + ds.TypeBuilder.FullName.Replace ("+", ".") + "." + name);
+ return; // local member name
+ }
+ }
+
+ Report.Warning (1574, 1, mc.Location, "XML comment on '{0}' has cref attribute '{1}' that could not be resolved in '{2}'.", mc.GetSignatureForError (), cref, ds.GetSignatureForError ());
+
+ xref.SetAttribute ("cref", "!:" + name);
+ }
+
+ //
+ // Get a prefix from member type for XML documentation (used
+ // to formalize cref target name).
+ //
+ static string GetMemberDocHead (MemberTypes type)
+ {
+ switch (type) {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ return "M:";
+ case MemberTypes.Event:
+ return "E:";
+ case MemberTypes.Field:
+ return "F:";
+ case MemberTypes.NestedType:
+ case MemberTypes.TypeInfo:
+ return "T:";
+ case MemberTypes.Property:
+ return "P:";
+ }
+ return "!:";
+ }
+
+ // MethodCore
+
+ //
+ // Returns a string that represents the signature for this
+ // member which should be used in XML documentation.
+ //
+ public static string GetMethodDocCommentName (MethodCore mc, DeclSpace ds)
+ {
+ Parameter [] plist = mc.Parameters.FixedParameters;
+ Parameter parr = mc.Parameters.ArrayParameter;
+ string paramSpec = String.Empty;
+ if (plist != null) {
+ StringBuilder psb = new StringBuilder ();
+ foreach (Parameter p in plist) {
+ psb.Append (psb.Length != 0 ? "," : "(");
+ psb.Append (p.ParameterType.FullName.Replace ("+", "."));
+ }
+ paramSpec = psb.ToString ();
+ }
+ if (parr != null)
+ paramSpec += String.Concat (
+ paramSpec == String.Empty ? "(" : ",",
+ parr.ParameterType.FullName.Replace ("+", "."));
+
+ if (paramSpec.Length > 0)
+ paramSpec += ")";
+
+ string name = mc is Constructor ? "#ctor" : mc.Name;
+ return String.Concat (mc.DocCommentHeader, ds.Name, ".", name, paramSpec);
+ }
+
+ //
+ // Raised (and passed an XmlElement that contains the comment)
+ // when GenerateDocComment is writing documentation expectedly.
+ //
+ // FIXME: with a few effort, it could be done with XmlReader,
+ // that means removal of DOM use.
+ //
+ internal static void OnMethodGenerateDocComment (
+ MethodCore mc, DeclSpace ds, XmlElement el)
+ {
+ Hashtable paramTags = new Hashtable ();
+ foreach (XmlElement pelem in el.SelectNodes ("param")) {
+ int i;
+ string xname = pelem.GetAttribute ("name");
+ if (xname == "")
+ continue; // really? but MS looks doing so
+ if (xname != "" && mc.Parameters.GetParameterByName (xname, out i) == null)
+ Report.Warning (1572, 2, mc.Location, "XML comment on '{0}' has a 'param' tag for '{1}', but there is no such parameter.", mc.Name, xname);
+ else if (paramTags [xname] != null)
+ Report.Warning (1571, 2, mc.Location, "XML comment on '{0}' has a duplicate param tag for '{1}'", mc.Name, xname);
+ paramTags [xname] = xname;
+ }
+ Parameter [] plist = mc.Parameters.FixedParameters;
+ Parameter parr = mc.Parameters.ArrayParameter;
+ if (plist != null) {
+ foreach (Parameter p in plist) {
+ if (paramTags.Count > 0 && paramTags [p.Name] == null)
+ Report.Warning (1573, 4, mc.Location, "Parameter '{0}' has no matching param tag in the XML comment for '{1}' (but other parameters do)", mc.Name, p.Name);
+ }
+ }
+ }
+
+ // Enum
+ public static void GenerateEnumDocComment (Enum e, DeclSpace ds)
+ {
+ GenerateDocComment (e, ds);
+ foreach (string name in e.ordered_enums) {
+ MemberCore mc = e.GetDefinition (name);
+ GenerateDocComment (mc, e);
+ }
+ }
+ }
+
+ //
+ // Implements XML documentation generation.
+ //
+ public class Documentation
+ {
+ public Documentation (string xml_output_filename)
+ {
+ docfilename = xml_output_filename;
+ XmlDocumentation = new XmlDocument ();
+ XmlDocumentation.PreserveWhitespace = false;
+ }
+
+ private string docfilename;
+
+ //
+ // Used to create element which helps well-formedness checking.
+ //
+ public XmlDocument XmlDocumentation;
+
+ //
+ // The output for XML documentation.
+ //
+ public XmlWriter XmlCommentOutput;
+
+ //
+ // Stores XmlDocuments that are included in XML documentation.
+ // Keys are included filenames, values are XmlDocuments.
+ //
+ public Hashtable StoredDocuments = new Hashtable ();
+
+ //
+ // Stores comments on partial types (should handle uniquely).
+ // Keys are PartialContainers, values are comment strings
+ // (didn't use StringBuilder; usually we have just 2 or more).
+ //
+ public IDictionary PartialComments = new ListDictionary ();
+
+ //
+ // Outputs XML documentation comment from tokenized comments.
+ //
+ public bool OutputDocComment (string asmfilename)
+ {
+ XmlTextWriter w = null;
+ try {
+ w = new XmlTextWriter (docfilename, null);
+ w.Indentation = 4;
+ w.Formatting = Formatting.Indented;
+ w.WriteStartDocument ();
+ w.WriteStartElement ("doc");
+ w.WriteStartElement ("assembly");
+ w.WriteStartElement ("name");
+ w.WriteString (Path.ChangeExtension (asmfilename, null));
+ w.WriteEndElement (); // name
+ w.WriteEndElement (); // assembly
+ w.WriteStartElement ("members");
+ XmlCommentOutput = w;
+ GenerateDocComment ();
+ w.WriteFullEndElement (); // members
+ w.WriteEndElement ();
+ w.WriteWhitespace (Environment.NewLine);
+ w.WriteEndDocument ();
+ return true;
+ } catch (Exception ex) {
+ Report.Error (1569, "Error generating XML documentation file '{0}' ('{1}')", docfilename, ex.Message);
+ return false;
+ } finally {
+ if (w != null)
+ w.Close ();
+ }
+ }
+
+ //
+ // Fixes full type name of each documented types/members up.
+ //
+ public void GenerateDocComment ()
+ {
+ TypeContainer root = RootContext.Tree.Types;
+ if (root.Interfaces != null)
+ foreach (Interface i in root.Interfaces)
+ DocUtil.GenerateTypeDocComment (i, null);
+
+ if (root.Types != null)
+ foreach (TypeContainer tc in root.Types)
+ DocUtil.GenerateTypeDocComment (tc, null);
+
+ if (root.Parts != null) {
+ IDictionary comments = PartialComments;
+ foreach (ClassPart cp in root.Parts) {
+ if (cp.DocComment == null)
+ continue;
+ comments [cp] = cp;
+ }
+ }
+
+ if (root.Delegates != null)
+ foreach (Delegate d in root.Delegates)
+ DocUtil.GenerateDocComment (d, null);
+
+ if (root.Enums != null)
+ foreach (Enum e in root.Enums)
+ DocUtil.GenerateEnumDocComment (e, null);
+
+ IDictionary table = new ListDictionary ();
+ foreach (ClassPart cp in PartialComments.Keys) {
+ table [cp.PartialContainer] += cp.DocComment;
+ }
+ foreach (PartialContainer pc in table.Keys) {
+ pc.DocComment = table [pc] as string;
+ DocUtil.GenerateDocComment (pc, null);
+ }
+ }
+ }
+}
--- /dev/null
+//
+// 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)
+// (C) 2004 Novell, Inc
+//
+
+namespace Mono.CSharp
+{
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using System.Globalization;
+ using System.Xml;
+ using System.Diagnostics;
+
+ public 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;
+
+ //
+ // Modules to be linked
+ //
+ static ArrayList modules;
+
+ // Lookup paths
+ static ArrayList link_paths;
+
+ // Whether we want to only run the tokenizer
+ static bool tokenize = false;
+
+ static string first_source;
+
+ static bool want_debugging_support = false;
+
+ static bool parse_only = false;
+ static bool timestamps = false;
+ static bool pause = false;
+ static bool show_counters = false;
+ public static bool parser_verbose = 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;
+ static string win32ResourceFile;
+ static string win32IconFile;
+
+ //
+ // 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);
+ }
+
+ 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){
+ SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
+ Tokenizer lexer = new Tokenizer (reader, file, defines);
+ int token, tokens = 0, errors = 0;
+
+ while ((token = lexer.token ()) != Token.EOF){
+ 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;
+ }
+
+ SeekableStreamReader reader = new SeekableStreamReader (input, encoding, using_default_encoder);
+
+ parser = new CSharpParser (reader, file, defines);
+ try {
+ parser.parse ();
+ } catch (Exception ex) {
+ Report.Error(666, "Compilation aborted: " + ex);
+ } finally {
+ input.Close ();
+ }
+ }
+
+ static void OtherFlags ()
+ {
+ Console.WriteLine (
+ "Other flags in the compiler\n" +
+ " --fatal Makes errors fatal\n" +
+ " --parse Only parses the source file\n" +
+ " --stacktrace Shows stack trace at error location\n" +
+ " --timestamp Displays time stamps of various compiler events\n" +
+ " -2 Enables experimental C# features\n" +
+ " -v Verbose parsing (for debugging the parser)\n" +
+ " --mcs-debug X Sets MCS debugging level to X\n");
+ }
+
+ 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" +
+ " -addmodule:MODULE Adds the module to the generated assembly\n" +
+ " -checked[+|-] Set default context to checked\n" +
+ " -codepage:ID Sets code page to the one in ID\n" +
+ " (number, `utf8' or `reset')\n" +
+ " -clscheck[+|-] Disables CLS Compliance verifications" + Environment.NewLine +
+ " -define:S1[;S2] Defines one or more symbols (short: /d:)\n" +
+ " -debug[+|-] Generate debugging information\n" +
+ " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" +
+ " -doc:FILE XML Documentation file to generate\n" +
+ " -g Generate debugging information\n" +
+ " -keycontainer:NAME The key pair container used to strongname the assembly\n" +
+ " -keyfile:FILE The strongname key file used to strongname the assembly\n" +
+ " -langversion:TEXT Specifies language version modes: ISO-1 or Default" + Environment.NewLine +
+ " -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" +
+ " -doc:XMLFILE Generates xml documentation into specified file\n" +
+ " -pkg:P1[,Pn] References packages P1..Pn\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" +
+ " -target:KIND Specifies the target (KIND is one of: exe, winexe,\n" +
+ " library, module), (short: /t:)\n" +
+ " -unsafe[+|-] Allows unsafe code\n" +
+ " -warnaserror[+|-] Treat warnings as errors\n" +
+ " -warn:LEVEL Sets warning level (the highest is 4, the default is 2)\n" +
+ " -help2 Show other help flags\n" +
+ "\n" +
+ "Resources:\n" +
+ " -linkresource:FILE[,ID] Links FILE as a resource\n" +
+ " -resource:FILE[,ID] Embed FILE as a resource\n" +
+ " -win32res:FILE Specifies Win32 resource file (.res)\n" +
+ " -win32icon:FILE Use this icon for the output\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, Martin Baulig and Marek Safar");
+ Environment.Exit (0);
+ }
+
+ public static int counter1, counter2;
+
+ public static int Main (string[] args)
+ {
+ RootContext.Version = LanguageVersion.Default;
+ 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);
+ }
+ if (pause)
+ Console.ReadLine ();
+ 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 {
+ string ass = assembly;
+ if (ass.EndsWith (".dll"))
+ ass = assembly.Substring (0, assembly.Length - 4);
+ a = Assembly.Load (ass);
+ }
+ 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)");
+ }
+ }
+
+ static public void LoadModule (MethodInfo adder_method, string module)
+ {
+ Module m;
+ string total_log = "";
+
+ try {
+ try {
+ m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { module });
+ }
+ catch (TargetInvocationException ex) {
+ throw ex.InnerException;
+ }
+ TypeManager.AddModule (m);
+
+ }
+ catch (FileNotFoundException){
+ foreach (string dir in link_paths){
+ string full_path = Path.Combine (dir, module);
+ if (!module.EndsWith (".netmodule"))
+ full_path += ".netmodule";
+
+ try {
+ try {
+ m = (Module)adder_method.Invoke (CodeGen.Assembly.Builder, new object [] { full_path });
+ }
+ catch (TargetInvocationException ex) {
+ throw ex.InnerException;
+ }
+ TypeManager.AddModule (m);
+ return;
+ } catch (FileNotFoundException ff) {
+ total_log += ff.FusionLog;
+ continue;
+ }
+ }
+ Report.Error (6, "Cannot find module `" + module + "'" );
+ Console.WriteLine ("Log: \n" + total_log);
+ } catch (BadImageFormatException f) {
+ Report.Error(6, "Cannot load module (bad file format)" + f.FusionLog);
+ } catch (FileLoadException f){
+ Report.Error(6, "Cannot load module " + f.FusionLog);
+ } catch (ArgumentNullException){
+ Report.Error(6, "Cannot load module (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;
+ string fn = System.IO.Path.GetFileName (codebase);
+ if (fn == "corlib.dll" || fn == "mscorlib.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",
+ "Microsoft.VisualBasic",
+#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 a 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);
+ }
+ RootContext.WarningLevel = level;
+ TestWarningConflict ();
+ }
+
+ static void TestWarningConflict ()
+ {
+ if (RootContext.WarningLevel == 0 && Report.WarningsAreErrors) {
+ Report.Error (1901, "Conflicting options specified: Warning level 0; Treat warnings as errors");
+ Environment.Exit (1);
+ }
+ }
+
+ static void SetupV2 ()
+ {
+ RootContext.Version = LanguageVersion.Default;
+ 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":
+ CSharpParser.yacc_verbose_flag++;
+ 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":
+ RootContext.Target = Target.Library;
+ RootContext.TargetExt = ".dll";
+ break;
+
+ case "exe":
+ RootContext.Target = Target.Exe;
+ break;
+
+ case "winexe":
+ RootContext.Target = Target.WinExe;
+ break;
+
+ case "module":
+ RootContext.Target = Target.Module;
+ RootContext.TargetExt = ".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;
+ TestWarningConflict();
+ 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 a 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":
+ RootContext.Target = Target.Exe;
+ break;
+
+ case "winexe":
+ RootContext.Target = Target.WinExe;
+ break;
+
+ case "library":
+ RootContext.Target = Target.Library;
+ RootContext.TargetExt = ".dll";
+ break;
+
+ case "module":
+ RootContext.Target = Target.Module;
+ RootContext.TargetExt = ".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 "/pkg": {
+ string packages;
+
+ if (value == ""){
+ Usage ();
+ Environment.Exit (1);
+ }
+ packages = String.Join (" ", value.Split (new Char [] { ';', ',', '\n', '\r'}));
+
+ ProcessStartInfo pi = new ProcessStartInfo ();
+ pi.FileName = "pkg-config";
+ pi.RedirectStandardOutput = true;
+ pi.UseShellExecute = false;
+ pi.Arguments = "--libs " + packages;
+ Process p = null;
+ try {
+ p = Process.Start (pi);
+ } catch (Exception e) {
+ Report.Error (-27, "Couldn't run pkg-config: " + e.Message);
+ Environment.Exit (1);
+ }
+
+ if (p.StandardOutput == null){
+ Report.Warning (-27, "Specified package did not return any information");
+ return true;
+ }
+ string pkgout = p.StandardOutput.ReadToEnd ();
+ p.WaitForExit ();
+ if (p.ExitCode != 0) {
+ Report.Error (-27, "Error running pkg-config. Check the above output.");
+ Environment.Exit (1);
+ }
+
+ if (pkgout != null){
+ string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}).
+ Split (new Char [] { ' ', '\t'});
+ args = AddArgs (args, xargs);
+ }
+
+ p.Close ();
+ return true;
+ }
+
+ case "/res":
+ case "/resource":
+ if (value == ""){
+ Report.Error (5, "-resource requires an argument");
+ Environment.Exit (1);
+ }
+ if (embedded_resources == null)
+ embedded_resources = new ArrayList ();
+
+ if (embedded_resources.Contains (value)) {
+ Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
+ }
+ else if (value.IndexOf (',') != -1 && embedded_resources.Contains (value.Split (',')[1])) {
+ Report.Error (1508, String.Format ("The resource identifier '{0}' has already been used in this assembly.", value));
+ }
+ else {
+ 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, "-reference requires an argument");
+ Environment.Exit (1);
+ }
+
+ string [] refs = value.Split (new char [] { ';', ',' });
+ foreach (string r in refs){
+ references.Add (r);
+ }
+ return true;
+ }
+ case "/addmodule": {
+ if (value == ""){
+ Report.Error (5, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+
+ string [] refs = value.Split (new char [] { ';', ',' });
+ foreach (string r in refs){
+ modules.Add (r);
+ }
+ return true;
+ }
+ case "/win32res": {
+ if (value == "") {
+ Report.Error (5, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+
+ win32ResourceFile = value;
+ return true;
+ }
+ case "/win32icon": {
+ if (value == "") {
+ Report.Error (5, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+
+ win32IconFile = value;
+ return true;
+ }
+ case "/doc": {
+ if (value == ""){
+ Report.Error (2006, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+ RootContext.Documentation = new Documentation (value);
+ 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-":
+ want_debugging_support = false;
+ 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 "/clscheck":
+ case "/clscheck+":
+ return true;
+
+ case "/clscheck-":
+ RootContext.VerifyClsCompliance = 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;
+ TestWarningConflict();
+ 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){
+ try {
+ int warn = Int32.Parse (wc);
+ if (warn < 1) {
+ throw new ArgumentOutOfRangeException("warn");
+ }
+ Report.SetIgnoreWarning (warn);
+ } catch {
+ Report.Error (1904, String.Format("'{0}' is not a valid warning number", wc));
+ Environment.Exit (1);
+ }
+ }
+ return true;
+ }
+
+ case "/noconfig-":
+ load_default_config = true;
+ return true;
+
+ case "/noconfig":
+ case "/noconfig+":
+ load_default_config = false;
+ return true;
+
+ case "/help2":
+ OtherFlags ();
+ Environment.Exit(0);
+ 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 "/keyfile":
+ if (value == String.Empty) {
+ Report.Error (5, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+ RootContext.StrongNameKeyFile = value;
+ return true;
+ case "/keycontainer":
+ if (value == String.Empty) {
+ Report.Error (5, arg + " requires an argument");
+ Environment.Exit (1);
+ }
+ RootContext.StrongNameKeyContainer = value;
+ return true;
+ case "/delaysign+":
+ RootContext.StrongNameDelaySign = true;
+ return true;
+ case "/delaysign-":
+ RootContext.StrongNameDelaySign = false;
+ return true;
+
+ case "/v2":
+ case "/2":
+ Console.WriteLine ("The compiler option -2 is obsolete. Please use /langversion instead");
+ SetupV2 ();
+ return true;
+
+ case "/langversion":
+ switch (value.ToLower (CultureInfo.InvariantCulture)) {
+ case "iso-1":
+ RootContext.Version = LanguageVersion.ISO_1;
+ return true;
+
+ case "default":
+ SetupV2 ();
+ return true;
+ }
+ Report.Error (1617, "Invalid option '{0}' for /langversion; must be ISO-1 or Default", value);
+ Environment.Exit (1);
+ return false;
+
+ 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);
+ encoding = Encoding.GetEncoding (cp);
+ using_default_encoder = false;
+ } catch {
+ Report.Error (2016, String.Format("Code page '{0}' is invalid or not installed", cp));
+ Environment.Exit (1);
+ }
+ return true;
+ }
+ //Report.Error (2007, String.Format ("Unrecognized command-line option: '{0}'", option));
+ //Environment.Exit (1);
+ return false;
+ }
+
+ static string [] AddArgs (string [] args, string [] extra_args)
+ {
+ string [] new_args;
+
+ new_args = new string [extra_args.Length + args.Length];
+ args.CopyTo (new_args, 0);
+ extra_args.CopyTo (new_args, args.Length);
+
+ return new_args;
+ }
+
+ /// <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")]
+ internal 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 ();
+ modules = new ArrayList ();
+ link_paths = new ArrayList ();
+
+ SetupDefaultDefines ();
+
+ //
+ // Setup defaults
+ //
+ // This is not required because Assembly.Load knows about this
+ // path.
+ //
+
+ for (i = 0; i < args.Length; i++){
+ string arg = args [i];
+ if (arg == "")
+ continue;
+
+ if (arg.StartsWith ("@")){
+ string [] 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;
+ }
+
+ args = AddArgs (args, extra_args);
+ 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 we are an exe, require a source file for the entry point
+ //
+ if (RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe){
+ if (first_source == null){
+ Report.Error (2008, "No files to compile were specified");
+ return false;
+ }
+
+ }
+
+ //
+ // If there is nothing to put in the assembly, and we are not a library
+ //
+ if (first_source == null && embedded_resources == null && resources == null){
+ Report.Error (2008, "No files to compile were specified");
+ return false;
+ }
+
+ if (Report.Errors > 0)
+ return false;
+
+ if (parse_only)
+ return true;
+
+ Tokenizer.Cleanup ();
+
+ //
+ // 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 ());
+ link_paths.Add (Directory.GetCurrentDirectory ());
+ 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) + RootContext.TargetExt;
+ else
+ output_file = first_source + RootContext.TargetExt;
+ }
+
+ CodeGen.Init (output_file, output_file, want_debugging_support);
+
+ if (RootContext.Target == Target.Module) {
+ PropertyInfo module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+ if (module_only == null) {
+ Report.Error (0, new Location (-1), "Cannot use /target:module on this runtime: try the Mono runtime instead.");
+ Environment.Exit (1);
+ }
+
+ MethodInfo set_method = module_only.GetSetMethod (true);
+ set_method.Invoke (CodeGen.Assembly.Builder, BindingFlags.Default, null, new object[]{true}, null);
+ }
+
+ TypeManager.AddModule (CodeGen.Module.Builder);
+
+ if (modules.Count > 0) {
+ MethodInfo adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance|BindingFlags.NonPublic);
+ if (adder_method == null) {
+ Report.Error (0, new Location (-1), "Cannot use /addmodule on this runtime: Try the Mono runtime instead.");
+ Environment.Exit (1);
+ }
+
+ foreach (string module in modules)
+ LoadModule (adder_method, module);
+ }
+
+ TypeManager.ComputeNamespaces ();
+
+ //
+ // 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 (Report.Errors > 0)
+ return false;
+ if (timestamps)
+ ShowTime ("Populate tree");
+ if (!RootContext.StdLib)
+ RootContext.BootCorlib_PopulateCoreTypes ();
+ RootContext.PopulateTypes ();
+ RootContext.DefineTypes ();
+
+ if (RootContext.Documentation != null &&
+ !RootContext.Documentation.OutputDocComment (
+ output_file))
+ return false;
+
+ TypeManager.InitCodeHelpers ();
+
+ //
+ // Verify using aliases now
+ //
+ Namespace.VerifyUsing ();
+
+ if (Report.Errors > 0){
+ return false;
+ }
+
+ if (RootContext.VerifyClsCompliance) {
+ CodeGen.Assembly.ResolveClsCompliance ();
+ if (CodeGen.Assembly.IsClsCompliant) {
+ AttributeTester.VerifyModulesClsCompliance ();
+ TypeManager.LoadAllImportedTypes ();
+ AttributeTester.VerifyTopLevelNameClsCompliance ();
+ }
+ }
+
+ //
+ // 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;
+
+ switch (RootContext.Target) {
+ case Target.Library:
+ case Target.Module:
+ k = PEFileKinds.Dll; break;
+ case Target.Exe:
+ k = PEFileKinds.ConsoleApplication; break;
+ case Target.WinExe:
+ k = PEFileKinds.WindowApplication; break;
+ }
+
+ if (RootContext.NeedsEntryPoint) {
+ MethodInfo ep = RootContext.EntryPoint;
+
+ if (ep == null) {
+ if (RootContext.MainClass != null) {
+ object main_cont = RootContext.Tree.Decls [RootContext.MainClass];
+ if (main_cont == null) {
+ Report.Error (1555, output_file, "Could not find '{0}' specified for Main method", RootContext.MainClass);
+ return false;
+ }
+
+ if (!(main_cont is ClassOrStruct)) {
+ Report.Error (1556, output_file, "'{0}' specified for Main method must be a valid class or struct", RootContext.MainClass);
+ return false;
+ }
+ }
+
+ if (Report.Errors == 0)
+ Report.Error (5001, "Program " + output_file +
+ " does not have an entry point defined");
+ return false;
+ }
+
+ CodeGen.Assembly.Builder.SetEntryPoint (ep, k);
+ } else if (RootContext.MainClass != null) {
+ Report.Error (2017, "Can not specify -main: when building module or library");
+ }
+
+ //
+ // 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.Assembly.Builder.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", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic,
+ null, CallingConventions.Any, argst, null);
+
+ 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 [1] = spec;
+ margs [0] = Path.GetFileName (spec);
+ }
+
+ if (File.Exists ((string) margs [1]))
+ embed_res.Invoke (CodeGen.Assembly.Builder, margs);
+ else {
+ Report.Error (1566, "Can not find the resource " + margs [1]);
+ }
+ }
+ }
+ }
+
+ //
+ // Add Win32 resources
+ //
+
+ CodeGen.Assembly.Builder.DefineVersionInfoResource ();
+
+ if (win32ResourceFile != null) {
+ try {
+ CodeGen.Assembly.Builder.DefineUnmanagedResource (win32ResourceFile);
+ }
+ catch (ArgumentException) {
+ Report.Warning (0, new Location (-1), "Cannot embed win32 resources on this runtime: try the Mono runtime instead.");
+ }
+ }
+
+ if (win32IconFile != null) {
+ MethodInfo define_icon = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
+ if (define_icon == null) {
+ Report.Warning (0, new Location (-1), "Cannot embed icon resource on this runtime: try the Mono runtime instead.");
+ }
+ define_icon.Invoke (CodeGen.Assembly.Builder, new object [] { win32IconFile });
+ }
+
+ if (Report.Errors > 0)
+ return false;
+
+ CodeGen.Save (output_file);
+ if (timestamps) {
+ ShowTime ("Saved output");
+ ShowTotalTime ("Total");
+ }
+
+ Timer.ShowTimers ();
+
+ if (Report.ExpectedError != 0){
+ if (Report.Errors == 0) {
+ Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+ "No other errors reported.");
+
+ Environment.Exit (2);
+ } else {
+ Console.WriteLine ("Failed to report expected error " + Report.ExpectedError + ".\n" +
+ "However, other errors were reported.");
+
+ 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);
+ }
+ }
+
+ //
+ // This is the only public entry point
+ //
+ public class CompilerCallableEntryPoint : MarshalByRefObject {
+ static bool used = false;
+
+ public bool InvokeCompiler (string [] args)
+ {
+ if (used)
+ Reset ();
+ bool ok = Driver.MainDriver (args);
+ return ok && Report.Errors == 0;
+ }
+
+ public void Reset ()
+ {
+ }
+ }
+}
--- /dev/null
+//
+// 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,
+
+ // Set if this is resolving the first part of a MemberAccess.
+ Intermediate = 32
+ }
+
+ //
+ // 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>
+ /// We are either a namespace or a type.
+ /// If we're a type, `IsType' is true and we may use `Type' to get
+ /// a TypeExpr representing that type.
+ /// </summary>
+ public interface IAlias {
+ bool IsType {
+ get;
+ }
+
+ string Name {
+ get;
+ }
+
+ TypeExpr ResolveAsType (EmitContext ec);
+ }
+
+ /// <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 code, string format, params object[] args)
+ {
+ Report.Warning (code, loc, format, args);
+ }
+
+ // Not nice but we have broken hierarchy
+ public virtual void CheckMarshallByRefAccess (Type container) {}
+
+ /// <summary>
+ /// Tests presence of ObsoleteAttribute and report proper error
+ /// </summary>
+ protected void CheckObsoleteAttribute (Type type)
+ {
+ ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
+ if (obsolete_attr == null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
+ }
+
+ public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
+ {
+ MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+ must_do_cs1540_check = false; // by default we do not check for this
+
+ //
+ // If only accessible to the current class or children
+ //
+ if (ma == MethodAttributes.Private) {
+ Type declaring_type = mi.DeclaringType;
+
+ if (invocation_type != declaring_type)
+ return TypeManager.IsNestedFamilyAccessible (invocation_type, declaring_type);
+
+ return true;
+ }
+ //
+ // FamAndAssem requires that we not only derivate, but we are on the
+ // same assembly.
+ //
+ if (ma == MethodAttributes.FamANDAssem){
+ return (mi.DeclaringType.Assembly != invocation_type.Assembly);
+ }
+
+ // 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)
+ 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) || (ma == MethodAttributes.FamORAssem)){
+ if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
+ return false;
+
+ if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
+ must_do_cs1540_check = true;
+
+ return true;
+ }
+
+ return true;
+ }
+
+ /// <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 virtual TypeExpr ResolveAsTypeTerminal (EmitContext ec)
+ {
+ int errors = Report.Errors;
+
+ TypeExpr te = ResolveAsTypeStep (ec) as TypeExpr;
+
+ if ((te == null) || (te.eclass != ExprClass.Type) || (te.Type == null)) {
+ if (errors == Report.Errors)
+ Report.Error (246, Location, "Cannot find type '{0}'", ToString ());
+ return null;
+ }
+
+ if (!te.CheckAccessLevel (ec.DeclSpace)) {
+ Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", te.Name);
+ return null;
+ }
+
+ return te;
+ }
+
+ /// <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;
+ bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
+ if (this is SimpleName)
+ e = ((SimpleName) this).DoResolveAllowStatic (ec, intermediate);
+
+ 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, loc);
+ return null;
+ }
+
+ return e;
+ }
+
+ switch (e.eclass) {
+ case ExprClass.Type:
+ if ((flags & ResolveFlags.VariableOrValue) == 0) {
+ e.Error_UnexpectedKind (flags, loc);
+ return null;
+ }
+ break;
+
+ case ExprClass.MethodGroup:
+ if (RootContext.Version == LanguageVersion.ISO_1){
+ 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, loc);
+ 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) && !(e is ConstructedType))
+ 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);
+
+ public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ Emit (ec);
+ ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ }
+
+ /// <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 (t == TypeManager.decimal_type)
+ return new DecimalConstant ((decimal) v);
+ else if (TypeManager.IsEnumType (t)){
+ Type real_type = TypeManager.TypeToCoreType (v.GetType ());
+ if (real_type == t)
+ real_type = System.Enum.GetUnderlyingType (real_type);
+
+ Constant e = Constantify (v, real_type);
+
+ return new EnumConstant (e, t);
+ } else if (v == null && !TypeManager.IsValueType (t))
+ return NullLiteral.Null;
+ 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 TypeExpression ((System.Type) mi, loc);
+ }
+
+ return null;
+ }
+
+
+ private static ArrayList almostMatchedMembers = new ArrayList (4);
+
+ //
+ // 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)
+ {
+ almostMatchedMembers.Clear ();
+
+ MemberInfo [] mi = TypeManager.MemberLookup (
+ container_type, qualifier_type,queried_type, mt, bf, name,
+ almostMatchedMembers);
+
+ 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 && errors == Report.Errors)
+ // No errors were reported by MemberLookup, but there was an error.
+ MemberLookupFailed (ec, qualifier_type, queried_type, name,
+ null, loc);
+
+ return e;
+ }
+
+ public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
+ Type queried_type, string name,
+ string class_name, Location loc)
+ {
+ if (almostMatchedMembers.Count != 0) {
+ if (qualifier_type == null) {
+ foreach (MemberInfo m in almostMatchedMembers)
+ Report.Error (38, loc,
+ "Cannot access non-static member `{0}' via nested type `{1}'",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+
+
+ if (qualifier_type != ec.ContainerType) {
+ // 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.
+ foreach (MemberInfo m in almostMatchedMembers)
+ Report.Error (1540, loc,
+ "Cannot access protected member `{0}' via a qualifier of type `{1}';"
+ + " the qualifier must be of type `{2}' (or derived from it)",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (qualifier_type),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+ almostMatchedMembers.Clear ();
+ }
+
+ MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type,
+ AllMemberTypes, AllBindingFlags |
+ BindingFlags.NonPublic, name, null);
+
+ if (mi == 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 (TypeManager.MemberLookup (queried_type, null, queried_type,
+ AllMemberTypes, AllBindingFlags |
+ BindingFlags.NonPublic, name, null) == null) {
+ if ((mi.Length == 1) && (mi [0] is Type)) {
+ Type t = (Type) mi [0];
+
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (t),
+ TypeManager.GetNumberOfTypeArguments (t));
+ return;
+ }
+ }
+
+
+
+ if (qualifier_type != null)
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", TypeManager.CSharpName (qualifier_type) + "." + name);
+ else if (name == ".ctor") {
+ Report.Error (143, loc, String.Format ("The type {0} has no constructors defined",
+ TypeManager.CSharpName (queried_type)));
+ } else {
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", name);
+ }
+ }
+
+ 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, false, 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;
+
+ if (e.Type == TypeManager.bool_type)
+ return e;
+
+ Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, new Location (-1));
+
+ if (converted != null)
+ return converted;
+
+ //
+ // If no implicit conversion to bool exists, try using `operator true'
+ //
+ 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;
+ }
+ return operator_true;
+ }
+
+ 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, Location loc)
+ {
+ string kind = "Unknown";
+
+ kind = ExprClassName (eclass);
+
+ Report.Error (118, loc, "Expression denotes a `" + kind +
+ "' where a `" + expected + "' was expected");
+ }
+
+ public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
+ {
+ 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 public 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 (Convert.ConstantEC, 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 || t.IsGenericParameter)
+ 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 || type.IsGenericParameter)
+ 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;
+ }
+
+ public static void Error_NegativeArrayIndex (Location loc)
+ {
+ Report.Error (248, loc, "Cannot create an 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 Expression Child {
+ get {
+ return 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);
+ }
+
+ public override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+ }
+
+
+ /// <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 ();
+ }
+
+ public object GetValueAsEnumType ()
+ {
+ return System.Enum.ToObject (type, 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 ();
+ }
+
+ public override bool IsZeroInteger {
+ get { return Child.IsZeroInteger; }
+ }
+
+ public override bool IsNegative {
+ get {
+ return Child.IsNegative;
+ }
+ }
+ }
+
+ /// <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)
+ {
+ eclass = ExprClass.Value;
+ }
+
+ public BoxedCast (Expression expr, Type target_type)
+ : base (expr, target_type)
+ {
+ eclass = ExprClass.Value;
+ }
+
+ 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);
+ if (t.IsGenericParameter)
+ ig.Emit (OpCodes.Unbox_Any, t);
+ else {
+ 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);
+
+ if (child.Type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Box, child.Type);
+
+ if (type.IsGenericParameter)
+ ec.ig.Emit (OpCodes.Unbox_Any, type);
+ else
+ 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;
+ public readonly TypeArguments Arguments;
+
+ //
+ // 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 SimpleName (string name, TypeArguments args, Location l)
+ {
+ Name = name;
+ Arguments = args;
+ 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, false);
+ }
+
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return SimpleNameResolve (ec, right_side, false, false);
+ }
+
+
+ public Expression DoResolveAllowStatic (EmitContext ec, bool intermediate)
+ {
+ return SimpleNameResolve (ec, null, true, intermediate);
+ }
+
+ public override Expression ResolveAsTypeStep (EmitContext ec)
+ {
+ DeclSpace ds = ec.DeclSpace;
+ NamespaceEntry ns = ds.NamespaceEntry;
+ Type t;
+ IAlias 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;
+
+ TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc);
+ if (generic_type != null)
+ return generic_type.ResolveAsTypeTerminal (ec);
+
+ if (ec.ResolvingTypeTree){
+ int errors = Report.Errors;
+ Type dt = ds.FindType (loc, Name);
+
+ if (Report.Errors != errors)
+ return null;
+
+ if (dt != null)
+ return new TypeExpression (dt, loc);
+
+ if (alias_value != null){
+ if (alias_value.IsType)
+ return alias_value.ResolveAsType (ec);
+ if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+ return new TypeExpression (t, loc);
+ }
+ }
+
+ if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
+ return new TypeExpression (t, loc);
+
+ if (alias_value != null) {
+ if (alias_value.IsType)
+ return alias_value.ResolveAsType (ec);
+ if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null)
+ return new TypeExpression (t, loc);
+
+ // we have alias value, but it isn't Type, so try if it's namespace
+ return new SimpleName (alias_value.Name, loc);
+ }
+
+ // No match, maybe our parent can compose us
+ // into something meaningful.
+ return this;
+ }
+
+ Expression SimpleNameResolve (EmitContext ec, Expression right_side,
+ bool allow_static, bool intermediate)
+ {
+ Expression e = DoSimpleNameResolve (ec, right_side, allow_static, intermediate);
+ if (e == null)
+ return null;
+
+ Block current_block = ec.CurrentBlock;
+ if (current_block != null){
+ //LocalInfo vi = current_block.GetLocalInfo (Name);
+ if (is_base &&
+ current_block.IsVariableNameUsedInChildBlock(Name)) {
+ Report.Error (135, Location,
+ "'{0}' has a different meaning in a " +
+ "child block", Name);
+ return null;
+ }
+ }
+
+ if (e.Type != null && e.Type.IsPointer && !ec.InUnsafe) {
+ UnsafeError (loc);
+ return null;
+ }
+
+ return e;
+ }
+
+ /// <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 DoSimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static, bool intermediate)
+ {
+ Expression e = null;
+
+ //
+ // 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);
+ }
+
+ ParameterReference pref = current_block.GetParameterReference (Name, loc);
+ if (pref != null) {
+ if (right_side != null)
+ return pref.ResolveLValue (ec, right_side);
+ else
+ return pref.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) {
+ //
+ // 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.NamespaceEntry;
+ if (is_base && ns != null){
+ IAlias alias_value = ns.LookupAlias (Name);
+ if (alias_value != null){
+ if (alias_value.IsType)
+ return alias_value.ResolveAsType (ec);
+
+ Name = alias_value.Name;
+ Type t;
+
+ if ((t = TypeManager.LookupType (Name)) != null)
+ return new TypeExpression (t, loc);
+
+ // No match, maybe our parent can compose us
+ // into something meaningful.
+ return this;
+ }
+ }
+
+ 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;
+
+ if (Arguments != null) {
+ MethodGroupExpr mg = me as MethodGroupExpr;
+ if (mg == null)
+ return null;
+
+ return mg.ResolveGeneric (ec, Arguments);
+ }
+
+ // 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.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
+ me.InstanceExpression.Type != me.DeclaringType &&
+ !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
+ (!intermediate || !MemberAccess.IdenticalNameAndTypeName (ec, this, e, loc))) {
+ Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
+ "outer type `" + me.DeclaringType + "' via nested type `" +
+ me.InstanceExpression.Type + "'");
+ return null;
+ }
+
+ return (right_side != null)
+ ? e.DoResolveLValue (ec, right_side)
+ : e.DoResolve (ec);
+ }
+
+ 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 abstract class TypeExpr : Expression, IAlias {
+ override public Expression ResolveAsTypeStep (EmitContext ec)
+ {
+ TypeExpr t = DoResolveAsTypeStep (ec);
+ if (t == null)
+ return null;
+
+ eclass = ExprClass.Type;
+ return t;
+ }
+
+ override public Expression DoResolve (EmitContext ec)
+ {
+ return ResolveAsTypeTerminal (ec);
+ }
+
+ override public void Emit (EmitContext ec)
+ {
+ throw new Exception ("Should never be called");
+ }
+
+ public virtual bool CheckAccessLevel (DeclSpace ds)
+ {
+ return ds.CheckAccessLevel (Type);
+ }
+
+ public virtual bool AsAccessible (DeclSpace ds, int flags)
+ {
+ return ds.AsAccessible (Type, flags);
+ }
+
+ public virtual bool IsClass {
+ get { return Type.IsClass; }
+ }
+
+ public virtual bool IsValueType {
+ get { return Type.IsValueType; }
+ }
+
+ public virtual bool IsInterface {
+ get { return Type.IsInterface; }
+ }
+
+ public virtual bool IsSealed {
+ get { return Type.IsSealed; }
+ }
+
+ public virtual bool CanInheritFrom ()
+ {
+ if (Type == TypeManager.enum_type ||
+ (Type == TypeManager.value_type && RootContext.StdLib) ||
+ Type == TypeManager.multicast_delegate_type ||
+ Type == TypeManager.delegate_type ||
+ Type == TypeManager.array_type)
+ return false;
+
+ return true;
+ }
+
+ public virtual bool IsAttribute {
+ get {
+ return Type == TypeManager.attribute_type ||
+ Type.IsSubclassOf (TypeManager.attribute_type);
+ }
+ }
+
+ protected abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
+
+ public abstract string Name {
+ get;
+ }
+
+ public override bool Equals (object obj)
+ {
+ TypeExpr tobj = obj as TypeExpr;
+ if (tobj == null)
+ return false;
+
+ return Type == tobj.Type;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Type.GetHashCode ();
+ }
+
+ public override string ToString ()
+ {
+ return Name;
+ }
+
+ bool IAlias.IsType {
+ get { return true; }
+ }
+
+ TypeExpr IAlias.ResolveAsType (EmitContext ec)
+ {
+ return ResolveAsTypeTerminal (ec);
+ }
+ }
+
+ public class TypeExpression : TypeExpr, IAlias {
+ public TypeExpression (Type t, Location l)
+ {
+ Type = t;
+ eclass = ExprClass.Type;
+ loc = l;
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override string Name {
+ get {
+ return Type.ToString ();
+ }
+ }
+
+ string IAlias.Name {
+ get {
+ return Type.FullName != null ? Type.FullName : Type.Name;
+ }
+ }
+ }
+
+ /// <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)
+ {
+ this.name = name;
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ if (type == null) {
+ type = RootContext.LookupType (
+ ec.DeclSpace, name, false, Location.Null);
+ if (type == null)
+ return null;
+ }
+
+ return this;
+ }
+
+ public override string Name {
+ get {
+ return name;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents an "unbound generic type", ie. typeof (Foo<>).
+ /// See 14.5.11.
+ /// </summary>
+ public class UnboundTypeExpression : TypeLookupExpression {
+ public UnboundTypeExpression (string name)
+ : base (name)
+ { }
+ }
+
+ public class TypeAliasExpression : TypeExpr, IAlias {
+ IAlias alias;
+ TypeExpr texpr;
+ TypeArguments args;
+ string name;
+
+ public TypeAliasExpression (IAlias alias, TypeArguments args, Location l)
+ {
+ this.alias = alias;
+ this.args = args;
+ loc = l;
+
+ eclass = ExprClass.Type;
+ if (args != null)
+ name = alias.Name + "<" + args.ToString () + ">";
+ else
+ name = alias.Name;
+ }
+
+ public override string Name {
+ get { return name; }
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ texpr = alias.ResolveAsType (ec);
+ if (texpr == null)
+ return null;
+
+ Type type = texpr.Type;
+ int num_args = TypeManager.GetNumberOfTypeArguments (type);
+
+ if (args != null) {
+ if (num_args == 0) {
+ Report.Error (308, loc,
+ "The non-generic type `{0}' cannot " +
+ "be used with type arguments.",
+ TypeManager.CSharpName (type));
+ return null;
+ }
+
+ ConstructedType ctype = new ConstructedType (type, args, loc);
+ return ctype.ResolveAsTypeTerminal (ec);
+ } else if (num_args > 0) {
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (type), num_args);
+ return null;
+ }
+
+ return new TypeExpression (type, loc);
+ }
+
+ public override bool CheckAccessLevel (DeclSpace ds)
+ {
+ return texpr.CheckAccessLevel (ds);
+ }
+
+ public override bool AsAccessible (DeclSpace ds, int flags)
+ {
+ return texpr.AsAccessible (ds, flags);
+ }
+
+ public override bool IsClass {
+ get { return texpr.IsClass; }
+ }
+
+ public override bool IsValueType {
+ get { return texpr.IsValueType; }
+ }
+
+ public override bool IsInterface {
+ get { return texpr.IsInterface; }
+ }
+
+ public override bool IsSealed {
+ get { return texpr.IsSealed; }
+ }
+
+ public override bool IsAttribute {
+ get { return texpr.IsAttribute; }
+ }
+ }
+
+ /// <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;
+ bool has_type_arguments = false;
+ bool identical_type_name = false;
+ bool is_base;
+
+ 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 bool HasTypeArguments {
+ get {
+ return has_type_arguments;
+ }
+
+ set {
+ has_type_arguments = value;
+ }
+ }
+
+ public bool IdenticalTypeName {
+ get {
+ return identical_type_name;
+ }
+
+ set {
+ identical_type_name = value;
+ }
+ }
+
+ public bool IsBase {
+ get {
+ return is_base;
+ }
+ set {
+ is_base = 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);
+ }
+
+ public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
+ {
+ if (args.Resolve (ec) == false)
+ return null;
+
+ Type[] atypes = args.Arguments;
+
+ int first_count = 0;
+ MethodInfo first = null;
+
+ ArrayList list = new ArrayList ();
+ foreach (MethodBase mb in Methods) {
+ MethodInfo mi = mb as MethodInfo;
+ if ((mi == null) || !mi.HasGenericParameters)
+ continue;
+
+ Type[] gen_params = mi.GetGenericArguments ();
+
+ if (first == null) {
+ first = mi;
+ first_count = gen_params.Length;
+ }
+
+ if (gen_params.Length != atypes.Length)
+ continue;
+
+ list.Add (mi.BindGenericParameters (atypes));
+ }
+
+ if (list.Count > 0) {
+ MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
+ new_mg.InstanceExpression = InstanceExpression;
+ new_mg.HasTypeArguments = true;
+ return new_mg;
+ }
+
+ if (first != null)
+ Report.Error (
+ 305, loc, "Using the generic method `{0}' " +
+ "requires {1} type arguments", Name,
+ first_count);
+ else
+ Report.Error (
+ 308, loc, "The non-generic method `{0}' " +
+ "cannot be used with type arguments", Name);
+
+ return null;
+ }
+ }
+
+ /// <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;
+
+ LocalTemporary temp;
+ bool prepared;
+ bool is_field_initializer;
+
+ public FieldExpr (FieldInfo fi, Location l)
+ {
+ FieldInfo = fi;
+ eclass = ExprClass.Variable;
+ type = TypeManager.TypeToCoreType (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 bool IsFieldInitializer {
+ get {
+ return is_field_initializer;
+ }
+
+ set {
+ is_field_initializer = 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;
+ }
+
+ ObsoleteAttribute oa;
+ FieldBase f = TypeManager.GetField (FieldInfo);
+ if (f != null) {
+ oa = f.GetObsoleteAttribute (f.Parent);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
+ // To be sure that type is external because we do not register generated fields
+ } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
+ oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
+ }
+
+ if (ec.CurrentAnonymousMethod != null){
+ if (!FieldInfo.IsStatic){
+ if (ec.TypeContainer is Struct){
+ Report.Error (1673, loc, "Can not reference instance variables in anonymous methods hosted in structs");
+ return null;
+ }
+ ec.CaptureField (this);
+ }
+ }
+
+ // 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;
+
+ FieldBase fb = TypeManager.GetField (FieldInfo);
+ if (fb != null)
+ fb.SetAssigned ();
+
+ //
+ // InitOnly fields can only be assigned in constructors
+ //
+
+ if (ec.IsConstructor){
+ if (IsStatic && !ec.IsStatic)
+ Report_AssignToReadonly (false);
+
+ Type ctype;
+ if (!is_field_initializer &&
+ (ec.TypeContainer.CurrentType != null))
+ ctype = ec.TypeContainer.CurrentType;
+ else
+ ctype = ec.ContainerType;
+
+ if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
+ return this;
+ }
+
+ Report_AssignToReadonly (!IsStatic);
+
+ return null;
+ }
+
+ public override void CheckMarshallByRefAccess (Type container)
+ {
+ if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
+ Report.SymbolRelatedToPreviousError (DeclaringType);
+ Report.Error (1690, loc, "Cannot call '{0}' method, property, or indexer because it is a value type member of a marshal-by-reference class", Name);
+ }
+ }
+
+ public bool VerifyFixed (bool is_expression)
+ {
+ IVariable variable = instance_expr as IVariable;
+ if ((variable == null) || !variable.VerifyFixed (true))
+ return false;
+
+ return true;
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ ILGenerator ig = ec.ig;
+ bool is_volatile = false;
+
+ if (FieldInfo is FieldBuilder){
+ FieldBase f = TypeManager.GetField (FieldInfo);
+ if (f != null){
+ 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);
+ } else {
+ if (!prepared)
+ EmitInstance (ec);
+
+ if (is_volatile)
+ ig.Emit (OpCodes.Volatile);
+
+ ig.Emit (OpCodes.Ldfld, FieldInfo);
+ }
+
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ if (!FieldInfo.IsStatic) {
+ temp = new LocalTemporary (ec, this.Type);
+ temp.Store (ec);
+ }
+ }
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ FieldAttributes fa = FieldInfo.Attributes;
+ bool is_static = (fa & FieldAttributes.Static) != 0;
+ bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
+ ILGenerator ig = ec.ig;
+ prepared = prepare_for_load;
+
+ if (is_readonly && !ec.IsConstructor){
+ Report_AssignToReadonly (!is_static);
+ return;
+ }
+
+ if (!is_static) {
+ EmitInstance (ec);
+ if (prepare_for_load)
+ ig.Emit (OpCodes.Dup);
+ }
+
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ if (!FieldInfo.IsStatic) {
+ temp = new LocalTemporary (ec, this.Type);
+ temp.Store (ec);
+ }
+ }
+
+ if (FieldInfo is FieldBuilder){
+ FieldBase f = TypeManager.GetField (FieldInfo);
+ if (f != null){
+ 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);
+
+ if (temp != null)
+ temp.Emit (ec);
+ }
+
+ void EmitInstance (EmitContext ec)
+ {
+ if (instance_expr.Type.IsValueType) {
+ if (instance_expr is IMemoryLocation) {
+ ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+ } else {
+ LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
+ instance_expr.Emit (ec);
+ t.Store (ec);
+ t.AddressOf (ec, AddressOp.Store);
+ }
+ } else
+ instance_expr.Emit (ec);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (FieldInfo is FieldBuilder){
+ FieldBase f = TypeManager.GetField (FieldInfo);
+ if (f != null){
+ 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.
+ //
+ bool need_copy;
+ if (FieldInfo.IsInitOnly){
+ need_copy = true;
+ if (ec.IsConstructor){
+ if (FieldInfo.IsStatic){
+ if (ec.IsStatic)
+ need_copy = false;
+ } else
+ need_copy = false;
+ }
+ } else
+ need_copy = false;
+
+ if (need_copy){
+ 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 {
+ EmitInstance (ec);
+ ig.Emit (OpCodes.Ldflda, FieldInfo);
+ }
+ }
+ }
+
+ //
+ // A FieldExpr whose address can not be taken
+ //
+ public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
+ public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
+ {
+ }
+
+ public new void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
+ }
+ }
+
+ /// <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;
+
+ Expression instance_expr;
+ LocalTemporary temp;
+ bool prepared;
+
+ 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;
+ }
+
+ void FindAccessors (Type invocation_type)
+ {
+ BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly;
+
+ Type current = PropertyInfo.DeclaringType;
+ for (; current != null; current = current.BaseType) {
+ MemberInfo[] group = TypeManager.MemberLookup (
+ invocation_type, invocation_type, current,
+ MemberTypes.Property, flags, PropertyInfo.Name, null);
+
+ if (group == null)
+ continue;
+
+ if (group.Length != 1)
+ // Oooops, can this ever happen ?
+ return;
+
+ PropertyInfo pi = (PropertyInfo) group [0];
+
+ if (getter == null)
+ getter = pi.GetGetMethod (true);;
+
+ if (setter == null)
+ setter = pi.GetSetMethod (true);;
+
+ MethodInfo accessor = getter != null ? getter : setter;
+
+ if (!accessor.IsVirtual)
+ return;
+ }
+ }
+
+ //
+ // 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)
+ {
+ FindAccessors (ec.ContainerType);
+
+ is_static = getter != null ? getter.IsStatic : setter.IsStatic;
+ }
+
+ bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
+ {
+ 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;
+
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+ }
+
+ 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){
+ if (TypeManager.GetArgumentTypes (getter).Length != 0){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+ }
+
+ 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;
+ }
+
+ bool must_do_cs1540_check;
+ if (!IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
+ Report.Error (122, loc, "'{0}.get' is inaccessible due to its protection level", PropertyInfo.Name);
+ return null;
+ }
+
+ if (!InstanceResolve (ec, must_do_cs1540_check))
+ 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 (TypeManager.GetArgumentTypes (setter).Length != 1){
+ Report.Error (
+ 117, loc, "`{0}' does not contain a " +
+ "definition for `{1}'.", getter.DeclaringType,
+ Name);
+ return null;
+ }
+
+ bool must_do_cs1540_check;
+ if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
+ Report.Error (122, loc, "'{0}.set' is inaccessible due to its protection level", PropertyInfo.Name);
+ return null;
+ }
+
+ if (!InstanceResolve (ec, must_do_cs1540_check))
+ 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;
+ }
+
+ //
+ // Check that we are not making changes to a temporary memory location
+ //
+ if (instance_expr != null && 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;
+ }
+
+ return this;
+ }
+
+
+
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+ }
+
+ void EmitInstance (EmitContext ec)
+ {
+ if (is_static)
+ return;
+
+ if (instance_expr.Type.IsValueType) {
+ if (instance_expr is IMemoryLocation) {
+ ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore);
+ } else {
+ LocalTemporary t = new LocalTemporary (ec, instance_expr.Type);
+ instance_expr.Emit (ec);
+ t.Store (ec);
+ t.AddressOf (ec, AddressOp.Store);
+ }
+ } else
+ instance_expr.Emit (ec);
+
+ if (prepared)
+ ec.ig.Emit (OpCodes.Dup);
+ }
+
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ if (!prepared)
+ EmitInstance (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)) {
+ ec.ig.Emit (OpCodes.Ldlen);
+ ec.ig.Emit (OpCodes.Conv_I4);
+ return;
+ }
+ }
+
+ Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), getter, null, loc);
+
+ if (!leave_copy)
+ return;
+
+ ec.ig.Emit (OpCodes.Dup);
+ if (!is_static) {
+ temp = new LocalTemporary (ec, this.Type);
+ temp.Store (ec);
+ }
+ }
+
+ //
+ // Implements the IAssignMethod interface for assignments
+ //
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ prepared = prepare_for_load;
+
+ EmitInstance (ec);
+
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ if (!is_static) {
+ temp = new LocalTemporary (ec, this.Type);
+ temp.Store (ec);
+ }
+ }
+
+ ArrayList args = new ArrayList (1);
+ args.Add (new Argument (new EmptyAddressOf (), Argument.AType.Expression));
+
+ Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), setter, args, loc);
+
+ if (temp != null)
+ temp.Emit (ec);
+ }
+
+ 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;
+ 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;
+ }
+ }
+
+ bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
+ {
+ if ((instance_expr == null) && ec.IsStatic && !is_static) {
+ SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
+ return false;
+ }
+
+ if (instance_expr != null) {
+ instance_expr = instance_expr.DoResolve (ec);
+ if (instance_expr == null)
+ return false;
+ }
+
+ //
+ // This is using the same mechanism as the CS1540 check in PropertyExpr.
+ // However, in the Event case, we reported a CS0122 instead.
+ //
+ if (must_do_cs1540_check && (instance_expr != null)) {
+ if ((instance_expr.Type != ec.ContainerType) &&
+ ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+ DeclaringType.Name + "." + EventInfo.Name);
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (instance_expr != null) {
+ instance_expr = instance_expr.DoResolve (ec);
+ if (instance_expr == null)
+ return null;
+ }
+
+ bool must_do_cs1540_check;
+ if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check)
+ && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
+
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level",
+ DeclaringType.Name + "." + EventInfo.Name);
+ return null;
+ }
+
+ if (!InstanceResolve (ec, must_do_cs1540_check))
+ return null;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (instance_expr is This)
+ Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=, try calling the actual delegate");
+ else
+ Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
+ "(except on the defining type)", Name);
+ }
+
+ public void EmitAddOrRemove (EmitContext ec, Expression source)
+ {
+ BinaryDelegate source_del = (BinaryDelegate) source;
+ Expression handler = source_del.Right;
+
+ Argument arg = new Argument (handler, Argument.AType.Expression);
+ ArrayList args = new ArrayList ();
+
+ args.Add (arg);
+
+ if (source_del.IsAddition)
+ Invocation.EmitCall (
+ ec, false, IsStatic, instance_expr, add_accessor, args, loc);
+ else
+ Invocation.EmitCall (
+ ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
+ }
+ }
+}
--- /dev/null
+//
+// 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;
+using System.Globalization;
+using System.Xml;
+
+namespace Mono.CSharp {
+
+ class EnumMember: MemberCore {
+ static string[] attribute_targets = new string [] { "field" };
+
+ Enum parent_enum;
+ public FieldBuilder builder;
+ internal readonly Expression Type;
+
+ public EnumMember (Enum parent_enum, Expression expr, string name,
+ Location loc, Attributes attrs):
+ base (null, new MemberName (name), attrs, loc)
+ {
+ this.parent_enum = parent_enum;
+ this.ModFlags = parent_enum.ModFlags;
+ this.Type = expr;
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.marshal_as_attr_type) {
+ UnmanagedMarshal marshal = a.GetMarshal (this);
+ if (marshal != null) {
+ builder.SetMarshal (marshal);
+ }
+ return;
+ }
+
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
+ a.Error_InvalidSecurityParent ();
+ return;
+ }
+
+ builder.SetCustomAttribute (cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Field;
+ }
+ }
+
+ public void DefineMember (TypeBuilder tb)
+ {
+ FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
+ | FieldAttributes.Literal;
+
+ builder = tb.DefineField (Name, tb, attr);
+ }
+
+ public override bool Define ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Emit (EmitContext ec)
+ {
+ if (OptAttributes != null)
+ OptAttributes.Emit (ec, this);
+
+ Emit ();
+ }
+
+ public override string GetSignatureForError()
+ {
+ return String.Concat (parent_enum.GetSignatureForError (), '.', base.GetSignatureForError ());
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ protected override bool VerifyClsCompliance(DeclSpace ds)
+ {
+ // Because parent is TypeContainer and we have only DeclSpace parent.
+ // Parameter replacing is required
+ return base.VerifyClsCompliance (parent_enum);
+ }
+
+ // There is no base type
+ protected override void VerifyObsoleteAttribute()
+ {
+ }
+
+ public override string DocCommentHeader {
+ get { return "F:"; }
+ }
+ }
+
+ /// <summary>
+ /// Enumeration container
+ /// </summary>
+ public class Enum : DeclSpace {
+ public ArrayList ordered_enums;
+
+ public Expression BaseType;
+
+ public Type UnderlyingType;
+
+ Hashtable member_to_location;
+
+ //
+ // 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 (NamespaceEntry ns, TypeContainer parent, Expression type,
+ int mod_flags, MemberName name, Attributes attrs, Location l)
+ : base (ns, parent, name, attrs, l)
+ {
+ this.BaseType = type;
+ ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
+ IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, l);
+
+ 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 void AddEnumMember (string name, Expression expr, Location loc, Attributes opt_attrs, string documentation)
+ {
+ if (name == "value__") {
+ Report.Error (76, loc, "An item in an enumeration can't have an identifier `value__'");
+ return;
+ }
+
+ EnumMember em = new EnumMember (this, expr, name, loc, opt_attrs);
+ em.DocComment = documentation;
+ if (!AddToContainer (em, false, name, ""))
+ return;
+
+
+ // TODO: can be almost deleted
+ ordered_enums.Add (name);
+ member_to_location.Add (name, loc);
+ }
+
+ //
+ // 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);
+
+ ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
+
+ attr |= TypeAttributes.Class | TypeAttributes.Sealed;
+
+ if (!(BaseType is TypeLookupExpression)) {
+ Report.Error (1008, Location,
+ "Type byte, sbyte, short, ushort, int, uint, " +
+ "long, or ulong expected (got: `{0}')", BaseType);
+ return null;
+ }
+
+ TypeExpr texpr = ResolveTypeExpr (BaseType, Location);
+ if (texpr == null)
+ return null;
+
+ UnderlyingType = texpr.Type;
+
+ 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.sbyte_type) {
+ Report.Error (1008, Location,
+ "Type byte, sbyte, short, 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.Module.Builder;
+
+ 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;
+ }
+ }
+ }
+
+ EnumMember em = (EnumMember) defined_names [name];
+ em.DefineMember (TypeBuilder);
+
+ bool fail;
+ default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail);
+ if (fail){
+ Error_ConstantValueCannotBeConverted (c, loc);
+ return null;
+ }
+
+ em.builder.SetConstant (default_value);
+ field_builders.Add (em.builder);
+ member_to_value [name] = default_value;
+
+ if (!TypeManager.RegisterFieldValue (em.builder, default_value))
+ return null;
+
+ return default_value;
+ }
+
+ public override bool DefineMembers (TypeContainer parent)
+ {
+ return true;
+ }
+
+ public override bool Define ()
+ {
+ //
+ // If there was an error during DefineEnum, return
+ //
+ if (TypeBuilder == null)
+ return false;
+
+ ec = new EmitContext (this, this, Location, null, UnderlyingType, ModFlags, false);
+
+ object default_value = 0;
+
+
+ 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;
+ }
+
+ EnumMember em = (EnumMember) defined_names [name];
+
+ em.DefineMember (TypeBuilder);
+ FieldBuilder fb = em.builder;
+
+ 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;
+ }
+
+ default_value = GetNextDefaultValue (default_value);
+ }
+
+ return true;
+ }
+
+ public override void Emit ()
+ {
+ if (OptAttributes != null) {
+ OptAttributes.Emit (ec, this);
+ }
+
+ foreach (EnumMember em in defined_names.Values) {
+ em.Emit (ec);
+ }
+
+ base.Emit ();
+ }
+
+ void VerifyClsName ()
+ {
+ Hashtable ht = new Hashtable ();
+ foreach (string name in ordered_enums) {
+ string locase = name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+ if (!ht.Contains (locase)) {
+ ht.Add (locase, defined_names [name]);
+ continue;
+ }
+
+ MemberCore conflict = (MemberCore)ht [locase];
+ Report.SymbolRelatedToPreviousError (conflict);
+ conflict = GetDefinition (name);
+ Report.Error (3005, conflict.Location, "Identifier '{0}' differing only in case is not CLS-compliant", conflict.GetSignatureForError ());
+ }
+ }
+
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds))
+ return false;
+
+ VerifyClsName ();
+
+ if (!AttributeTester.IsClsCompliant (UnderlyingType)) {
+ Report.Error (3009, Location, "'{0}': base type '{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (UnderlyingType));
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Returns full enum name.
+ /// </summary>
+ string GetEnumeratorName (string valueName)
+ {
+ return String.Concat (Name, ".", valueName);
+ }
+
+ //
+ // 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 ((EnumMember) defined_names [name]).Type;
+ }
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Enum;
+ }
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ // UnderlyingType is never obsolete
+ }
+
+ //
+ // Generates xml doc comments (if any), and if required,
+ // handle warning report.
+ //
+ internal override void GenerateDocComment (DeclSpace ds)
+ {
+ DocUtil.GenerateEnumDocComment (this, ds);
+ }
+
+ //
+ // Represents header string for documentation comment.
+ //
+ public override string DocCommentHeader {
+ get { return "T:"; }
+ }
+ }
+}
--- /dev/null
+//
+// expression.cs: Expression representation for the IL tree.
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, 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, false, null);
+
+ ec.ig.Emit (OpCodes.Call, mi);
+ return;
+ }
+
+ static public StaticCallExpr 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, false, 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);
+ }
+
+ public MethodInfo Method {
+ get { return mi; }
+ }
+ }
+
+ public class ParenthesizedExpression : Expression
+ {
+ public Expression Expr;
+
+ public ParenthesizedExpression (Expression expr, Location loc)
+ {
+ this.Expr = expr;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ Expr = Expr.Resolve (ec);
+ return Expr;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new Exception ("Should not happen");
+ }
+ }
+
+ /// <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);
+ else if (expr is SByteConstant)
+ e = new IntConstant (-((SByteConstant) expr).Value);
+ else if (expr is ByteConstant)
+ e = new IntConstant (-((ByteConstant) 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 result != null;
+
+ 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 TypeExpression (TypeManager.int32_type, loc), e, loc);
+ result = result.Resolve (ec);
+ } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
+ result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
+ result = result.Resolve (ec);
+ } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
+ result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
+ result = result.Resolve (ec);
+ } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
+ result = new Cast (new TypeExpression (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)
+ {
+ //
+ // Step 1: 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;
+ }
+
+ //
+ // Step 2: Perform Operator Overload location
+ //
+ Type expr_type = Expr.Type;
+ 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;
+
+ 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;
+ }
+
+ if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ Error (213, "You can not fix an already fixed expression");
+ return null;
+ }
+
+ LocalVariableReference lr = Expr as LocalVariableReference;
+ if (lr != null){
+ if (lr.local_info.IsCaptured){
+ AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
+ return null;
+ }
+ lr.local_info.AddressTaken = true;
+ lr.local_info.Used = true;
+ }
+
+ // 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 Expression DoResolveLValue (EmitContext ec, Expression right)
+ {
+ if (Oper == Operator.Indirection)
+ return base.DoResolveLValue (ec, right);
+
+ Error (131, "The left-hand side of an assignment must be a " +
+ "variable, property or indexer");
+ return null;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ switch (Oper) {
+ case Operator.UnaryPlus:
+ throw new Exception ("This should be caught by Resolve");
+
+ case Operator.UnaryNegation:
+ if (ec.CheckState) {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ if (type == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_U8);
+ Expr.Emit (ec);
+ ig.Emit (OpCodes.Sub_Ovf);
+ } else {
+ 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 ());
+ }
+ }
+
+ public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ if (Oper == Operator.LogicalNot)
+ Expr.EmitBranchable (ec, target, !onTrue);
+ else
+ base.EmitBranchable (ec, target, onTrue);
+ }
+
+ 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 prepared;
+
+ 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)
+ {
+ if (!prepared)
+ expr.Emit (ec);
+
+ LoadFromPtr (ec.ig, Type);
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temporary = new LocalTemporary (ec, expr.Type);
+ temporary.Store (ec);
+ }
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ prepared = prepare_for_load;
+
+ expr.Emit (ec);
+
+ if (prepare_for_load)
+ ec.ig.Emit (OpCodes.Dup);
+
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temporary = new LocalTemporary (ec, expr.Type);
+ temporary.Store (ec);
+ }
+
+ StoreFromPtr (ec.ig, type);
+
+ if (temporary != null)
+ temporary.Emit (ec);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp Mode)
+ {
+ expr.Emit (ec);
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // Born fully resolved
+ //
+ return this;
+ }
+
+ 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;
+ bool is_expr = false;
+ bool recurse = false;
+
+ Expression expr;
+
+ //
+ // This is expensive for the simplest case.
+ //
+ StaticCallExpr 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){
+ LocalVariableReference var = expr as LocalVariableReference;
+ if ((var != null) && var.IsReadOnly)
+ Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
+ if (IsIncrementableNumber (expr_type) ||
+ expr_type == TypeManager.decimal_type){
+ return this;
+ }
+ } else if (expr.eclass == ExprClass.IndexerAccess){
+ IndexerAccess ia = (IndexerAccess) expr;
+
+ expr = ia.ResolveLValue (ec, this);
+ 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", loc);
+ 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);
+ }
+
+ }
+
+ void EmitCode (EmitContext ec, bool is_expr)
+ {
+ recurse = true;
+ this.is_expr = is_expr;
+ ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true);
+ }
+
+
+ public override void Emit (EmitContext ec)
+ {
+ //
+ // We use recurse to allow ourselfs to be the source
+ // of an assignment. This little hack prevents us from
+ // having to allocate another expression
+ //
+ if (recurse) {
+ ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
+ if (method == null)
+ LoadOneAndEmitOp (ec, expr.Type);
+ else
+ ec.ig.Emit (OpCodes.Call, method.Method);
+ recurse = false;
+ return;
+ }
+
+ 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 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)
+ {
+ TypeExpr texpr = ProbeType.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+ probe_type = texpr.Type;
+
+ CheckObsoleteAttribute (probe_type);
+
+ expr = expr.Resolve (ec);
+ if (expr == null)
+ return null;
+
+ if (expr.Type.IsPointer) {
+ Report.Error (244, loc, "\"is\" or \"as\" are not valid on pointer types");
+ return null;
+ }
+ 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 void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ ILGenerator ig = ec.ig;
+
+ switch (action){
+ case Action.AlwaysFalse:
+ if (! onTrue)
+ ig.Emit (OpCodes.Br, target);
+
+ return;
+ case Action.AlwaysTrue:
+ if (onTrue)
+ ig.Emit (OpCodes.Br, target);
+
+ return;
+ case Action.LeaveOnStack:
+ // the `e != null' rule.
+ expr.Emit (ec);
+ ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ return;
+ case Action.Probe:
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Isinst, probe_type);
+ ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ 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)){
+ if (etype.IsGenericParameter)
+ expr = new BoxedCast (expr, etype);
+
+ //
+ // 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 (warning_always_matches)
+ Warning (183, "The given expression is always of the provided ('{0}') type", TypeManager.CSharpName (probe_type));
+ else if (warning_never_matches){
+ if (!(probe_type.IsInterface || expr.Type.IsInterface))
+ Warning (184, "The given expression is never of the provided ('{0}') 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)){
+ if (etype.IsGenericParameter)
+ expr = new BoxedCast (expr, etype);
+
+ 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;
+
+ TypeExpr target = target_type.ResolveAsTypeTerminal (ec);
+ if (target == null)
+ return null;
+
+ type = target.Type;
+
+ CheckObsoleteAttribute (type);
+
+ if (type.IsAbstract && type.IsSealed) {
+ Report.Error (716, loc, "Cannot convert to static type '{0}'", TypeManager.CSharpName (type));
+ return null;
+ }
+
+ eclass = ExprClass.Value;
+
+ if (expr is Constant){
+ Expression e = TryReduce (ec, type);
+
+ if (e != null)
+ return e;
+ }
+
+ if (type.IsPointer && !ec.InUnsafe) {
+ UnsafeError (loc);
+ return null;
+ }
+ 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;
+
+ // 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);
+ else {
+ left = ForceConversion (ec, left, TypeManager.uint64_type);
+ right = ForceConversion (ec, right, TypeManager.uint64_type);
+ }
+ 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 (unless we have an int constant).
+ //
+ 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_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 Make32or64 (EmitContext ec, Expression e)
+ {
+ Type t= e.Type;
+
+ if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+ t == TypeManager.int64_type || t == TypeManager.uint64_type)
+ return e;
+ Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
+ if (ee != null)
+ return ee;
+ return null;
+ }
+
+ Expression CheckShiftArguments (EmitContext ec)
+ {
+ Expression e;
+
+ 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;
+
+ if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
+ right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
+ right = right.DoResolve (ec);
+ } else {
+ right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
+ right = right.DoResolve (ec);
+ }
+
+ return this;
+ }
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ Expression ResolveOperator (EmitContext ec)
+ {
+ Type l = left.Type;
+ Type r = right.Type;
+
+ //
+ // Special cases: string or type parameter comapred to null
+ //
+ if (oper == Operator.Equality || oper == Operator.Inequality){
+ if ((!TypeManager.IsValueType (l) && r == TypeManager.null_type) ||
+ (!TypeManager.IsValueType (r) && l == TypeManager.null_type)) {
+ Type = TypeManager.bool_type;
+
+ return this;
+ }
+
+ if (l.IsGenericParameter && (right is NullLiteral)) {
+ if (l.BaseType == TypeManager.value_type) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ left = new BoxedCast (left);
+ Type = TypeManager.bool_type;
+ return this;
+ }
+
+ if (r.IsGenericParameter && (left is NullLiteral)) {
+ if (r.BaseType == TypeManager.value_type) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ right = new BoxedCast (right);
+ Type = TypeManager.bool_type;
+ return this;
+ }
+
+ // IntPtr equality
+ if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {
+ 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) {
+ ArrayList args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
+
+ MethodBase method = Invocation.OverloadResolve (
+ ec, union, args, true, Location.Null);
+
+ if (method != null) {
+ MethodInfo mi = (MethodInfo) method;
+
+ return new BinaryMethod (mi.ReturnType, method, args);
+ }
+ }
+ }
+
+ //
+ // 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
+ //
+
+ // Simple constant folding
+ if (left is StringConstant && right is StringConstant)
+ return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+
+ if (l == TypeManager.string_type || r == TypeManager.string_type) {
+
+ if (r == TypeManager.void_type || l == TypeManager.void_type) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ // try to fold it in on the left
+ if (left is StringConcat) {
+
+ //
+ // We have to test here for not-null, since we can be doubly-resolved
+ // take care of not appending twice
+ //
+ if (type == null){
+ type = TypeManager.string_type;
+ ((StringConcat) left).Append (ec, right);
+ return left.Resolve (ec);
+ } else {
+ return left;
+ }
+ }
+
+ // Otherwise, start a new concat expression
+ return new StringConcat (ec, loc, left, right).Resolve (ec);
+ }
+
+ //
+ // 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 (ec, left, r) ||
+ Convert.ImplicitStandardConversionExists (ec, 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 (TypeManager.IsDelegateType (l)){
+ if (((right.eclass == ExprClass.MethodGroup) ||
+ (r == TypeManager.anonymous_method_type))){
+ if ((RootContext.Version != LanguageVersion.ISO_1)){
+ Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+ if (tmp == null)
+ return null;
+ right = tmp;
+ r = right.Type;
+ }
+ }
+
+ if (TypeManager.IsDelegateType (r)){
+ MethodInfo method;
+ ArrayList args = new ArrayList (2);
+
+ args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.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;
+ }
+
+ return new BinaryDelegate (l, method, args);
+ }
+ }
+
+ //
+ // 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).Resolve (ec);
+ } else {
+ Expression t = Make32or64 (ec, right);
+ if (t != null)
+ return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc).Resolve (ec);
+ }
+ } else if (r.IsPointer && oper == Operator.Addition){
+ Expression t = Make32or64 (ec, left);
+ if (t != null)
+ return new PointerArithmetic (true, right, t, r, loc).Resolve (ec);
+ }
+ }
+
+ //
+ // 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){
+ if (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){
+ temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+ if (temp != null){
+ if (lie)
+ right = temp;
+ else
+ left = temp;
+ type = enum_type;
+ return this;
+ }
+
+ 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;
+ }
+ }
+
+ //
+ // 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;
+ }
+ } 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)
+ {
+ if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
+ left = ((ParenthesizedExpression) left).Expr;
+ left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+ if (left == null)
+ return null;
+
+ if (left.eclass == ExprClass.Type) {
+ Error (75, "Casting a negative value needs to have the value in parentheses.");
+ return null;
+ }
+ } else
+ left = left.Resolve (ec);
+
+ if (left == null)
+ return null;
+
+ Constant lc = left as Constant;
+ if (lc != null && lc.Type == TypeManager.bool_type &&
+ ((oper == Operator.LogicalAnd && (bool)lc.GetValue () == false) ||
+ (oper == Operator.LogicalOr && (bool)lc.GetValue () == true))) {
+
+ // TODO: make a sence to resolve unreachable expression as we do for statement
+ Report.Warning (429, 4, loc, "Unreachable expression code detected");
+ return left;
+ }
+
+ right = right.Resolve (ec);
+ if (right == null)
+ return null;
+
+ eclass = ExprClass.Value;
+
+ Constant rc = right 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 override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ 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) && (left is Constant || right is Constant)) {
+ bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
+
+ //
+ // put the constant on the rhs, for simplicity
+ //
+ if (left is Constant) {
+ Expression swap = right;
+ right = left;
+ left = swap;
+ }
+
+ if (((Constant) right).IsZeroInteger) {
+ left.Emit (ec);
+ if (my_on_true)
+ ig.Emit (OpCodes.Brtrue, target);
+ else
+ ig.Emit (OpCodes.Brfalse, target);
+
+ return;
+ } 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;
+ }
+
+ } else if (oper == Operator.LogicalAnd) {
+
+ if (onTrue) {
+ Label tests_end = ig.DefineLabel ();
+
+ left.EmitBranchable (ec, tests_end, false);
+ right.EmitBranchable (ec, target, true);
+ ig.MarkLabel (tests_end);
+ } else {
+ left.EmitBranchable (ec, target, false);
+ right.EmitBranchable (ec, target, false);
+ }
+
+ return;
+
+ } else if (oper == Operator.LogicalOr){
+ if (onTrue) {
+ left.EmitBranchable (ec, target, true);
+ right.EmitBranchable (ec, target, true);
+
+ } else {
+ Label tests_end = ig.DefineLabel ();
+ left.EmitBranchable (ec, tests_end, true);
+ right.EmitBranchable (ec, target, false);
+ ig.MarkLabel (tests_end);
+ }
+
+ return;
+
+ } else if (!(oper == Operator.LessThan || oper == Operator.GreaterThan ||
+ oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+ oper == Operator.Equality || oper == Operator.Inequality)) {
+ base.EmitBranchable (ec, target, onTrue);
+ return;
+ }
+
+ left.Emit (ec);
+ right.Emit (ec);
+
+ Type t = left.Type;
+ bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+
+ 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 (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 (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:
+ Console.WriteLine (oper);
+ throw new Exception ("what is THAT");
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ Type l = left.Type;
+ OpCode opcode;
+
+ //
+ // Handle short-circuit operators differently
+ // than the rest
+ //
+ if (oper == Operator.LogicalAnd) {
+ Label load_zero = ig.DefineLabel ();
+ Label end = ig.DefineLabel ();
+
+ left.EmitBranchable (ec, load_zero, false);
+ 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 ();
+
+ left.EmitBranchable (ec, load_one, true);
+ 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_0);
+
+ opcode = OpCodes.Ceq;
+ 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);
+ }
+ }
+
+ //
+ // Object created by Binary when the binary operator uses an method instead of being
+ // a binary operation that maps to a CIL binary operation.
+ //
+ public class BinaryMethod : Expression {
+ public MethodBase method;
+ public ArrayList Arguments;
+
+ public BinaryMethod (Type t, MethodBase m, ArrayList args)
+ {
+ method = m;
+ Arguments = args;
+ type = t;
+ eclass = ExprClass.Value;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (Arguments != null)
+ Invocation.EmitArguments (ec, method, Arguments, false, null);
+
+ if (method is MethodInfo)
+ ig.Emit (OpCodes.Call, (MethodInfo) method);
+ else
+ ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+ }
+ }
+
+ //
+ // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+ // b, c, d... may be strings or objects.
+ //
+ public class StringConcat : Expression {
+ ArrayList operands;
+ bool invalid = false;
+ bool emit_conv_done = false;
+ //
+ // Are we also concating objects?
+ //
+ bool is_strings_only = true;
+
+ public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+ {
+ this.loc = loc;
+ type = TypeManager.string_type;
+ eclass = ExprClass.Value;
+
+ operands = new ArrayList (2);
+ Append (ec, left);
+ Append (ec, right);
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (invalid)
+ return null;
+
+ return this;
+ }
+
+ public void Append (EmitContext ec, Expression operand)
+ {
+ //
+ // Constant folding
+ //
+ if (operand is StringConstant && operands.Count != 0) {
+ StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+ if (last_operand != null) {
+ operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+ return;
+ }
+ }
+
+ //
+ // Conversion to object
+ //
+ if (operand.Type != TypeManager.string_type) {
+ Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+
+ if (no == null) {
+ Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+ invalid = true;
+ }
+ operand = no;
+ }
+
+ operands.Add (operand);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ MethodInfo concat_method = null;
+
+ //
+ // Do conversion to arguments; check for strings only
+ //
+
+ // This can get called multiple times, so we have to deal with that.
+ if (!emit_conv_done) {
+ emit_conv_done = true;
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+ is_strings_only &= e.Type == TypeManager.string_type;
+ }
+
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+
+ if (! is_strings_only && e.Type == TypeManager.string_type) {
+ // need to make sure this is an object, because the EmitParams
+ // method might look at the type of this expression, see it is a
+ // string and emit a string [] when we want an object [];
+
+ e = new EmptyCast (e, TypeManager.object_type);
+ }
+ operands [i] = new Argument (e, Argument.AType.Expression);
+ }
+ }
+
+ //
+ // Find the right method
+ //
+ switch (operands.Count) {
+ case 1:
+ //
+ // This should not be possible, because simple constant folding
+ // is taken care of in the Binary code.
+ //
+ throw new Exception ("how did you get here?");
+
+ case 2:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string :
+ TypeManager.string_concat_object_object ;
+ break;
+ case 3:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string_string :
+ TypeManager.string_concat_object_object_object ;
+ break;
+ case 4:
+ //
+ // There is not a 4 param overlaod for object (the one that there is
+ // is actually a varargs methods, and is only in corlib because it was
+ // introduced there before.).
+ //
+ if (!is_strings_only)
+ goto default;
+
+ concat_method = TypeManager.string_concat_string_string_string_string;
+ break;
+ default:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_dot_dot_dot :
+ TypeManager.string_concat_object_dot_dot_dot ;
+ break;
+ }
+
+ Invocation.EmitArguments (ec, concat_method, operands, false, null);
+ ec.ig.Emit (OpCodes.Call, concat_method);
+ }
+ }
+
+ //
+ // Object created with +/= on delegates
+ //
+ public class BinaryDelegate : Expression {
+ MethodInfo method;
+ ArrayList args;
+
+ public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+ {
+ method = mi;
+ this.args = args;
+ type = t;
+ eclass = ExprClass.Value;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Invocation.EmitArguments (ec, method, args, false, null);
+
+ ig.Emit (OpCodes.Call, (MethodInfo) method);
+ ig.Emit (OpCodes.Castclass, type);
+ }
+
+ public Expression Right {
+ get {
+ Argument arg = (Argument) args [1];
+ return arg.Expr;
+ }
+ }
+
+ public bool IsAddition {
+ get {
+ return method == TypeManager.delegate_combine_delegate_delegate;
+ }
+ }
+ }
+
+ //
+ // 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;
+ LocalTemporary left_temp;
+
+ 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;
+ }
+
+ left_temp = new LocalTemporary (ec, type);
+
+ ArrayList arguments = new ArrayList ();
+ arguments.Add (new Argument (left_temp, Argument.AType.Expression));
+ arguments.Add (new Argument (right, Argument.AType.Expression));
+ method = Invocation.OverloadResolve (
+ ec, (MethodGroupExpr) operator_group, arguments, false, loc)
+ as MethodInfo;
+ if ((method == null) || (method.ReturnType != type)) {
+ Error19 ();
+ return null;
+ }
+
+ op = new StaticCallExpr (method, arguments, loc);
+
+ op_true = GetOperatorTrue (ec, left_temp, loc);
+ op_false = GetOperatorFalse (ec, left_temp, 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 ();
+
+ left.Emit (ec);
+ left_temp.Store (ec);
+
+ (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+ left_temp.Emit (ec);
+ ig.Emit (OpCodes.Br, end_target);
+ ig.MarkLabel (false_target);
+ op.Emit (ec);
+ ig.MarkLabel (end_target);
+ }
+ }
+
+ 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;
+ this.loc = loc;
+ left = l;
+ right = r;
+ is_add = is_addition;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+
+ if (left.Type == TypeManager.void_ptr_type) {
+ Error (242, "The operation in question is undefined on void pointers");
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ Type op_type = left.Type;
+ ILGenerator ig = ec.ig;
+ Type element = TypeManager.GetElementType (op_type);
+ int size = GetTypeSize (element);
+ 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, element);
+ 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, element);
+ 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);
+ }
+
+ if (rtype == TypeManager.int64_type || rtype == TypeManager.uint64_type)
+ 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;
+
+ //
+ // 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 ();
+
+ expr.EmitBranchable (ec, 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;
+ public LocalInfo local_info;
+ bool is_readonly;
+ bool prepared;
+ LocalTemporary temp;
+
+ 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 local_info.VariableInfo;
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return is_readonly;
+ }
+ }
+
+ protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side)
+ {
+ if (local_info == null) {
+ local_info = Block.GetLocalInfo (Name);
+
+ // is out param
+ if (lvalue_right_side == EmptyExpression.Null)
+ local_info.Used = true;
+
+ is_readonly = local_info.ReadOnly;
+ }
+
+ type = local_info.VariableType;
+
+ VariableInfo variable_info = local_info.VariableInfo;
+ if (lvalue_right_side != null){
+ if (is_readonly){
+ Error (1604, "cannot assign to `" + Name + "' because it is readonly");
+ return null;
+ }
+
+ if (variable_info != null)
+ variable_info.SetAssigned (ec);
+ }
+
+ Expression e = Block.GetConstantExpression (Name);
+ if (e != null) {
+ local_info.Used = true;
+ eclass = ExprClass.Value;
+ return e.Resolve (ec);
+ }
+
+ if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
+ return null;
+
+ if (lvalue_right_side == null)
+ local_info.Used = true;
+
+ if (ec.CurrentAnonymousMethod != null){
+ //
+ // If we are referencing a variable from the external block
+ // flag it for capturing
+ //
+ if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel){
+ if (local_info.AddressTaken){
+ AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
+ return null;
+ }
+ ec.CaptureVariable (local_info);
+ }
+ }
+
+ return this;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return DoResolveBase (ec, null);
+ }
+
+ override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ Expression ret = DoResolveBase (ec, right_side);
+ if (ret != null)
+ CheckObsoleteAttribute (ret.Type);
+
+ return ret;
+ }
+
+ 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.FieldBuilder == null){
+ //
+ // A local variable on the local CLR stack
+ //
+ ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+ } else {
+ //
+ // A local variable captured by anonymous methods.
+ //
+ if (!prepared)
+ ec.EmitCapturedVariableInstance (local_info);
+
+ ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
+ }
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ Emit (ec);
+ if (leave_copy){
+ ec.ig.Emit (OpCodes.Dup);
+ if (local_info.FieldBuilder != null){
+ temp = new LocalTemporary (ec, Type);
+ temp.Store (ec);
+ }
+ }
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ ILGenerator ig = ec.ig;
+ prepared = prepare_for_load;
+
+ if (local_info.FieldBuilder == null){
+ //
+ // A local variable on the local CLR stack
+ //
+ if (local_info.LocalBuilder == null)
+ throw new Exception ("This should not happen: both Field and Local are null");
+
+ source.Emit (ec);
+ if (leave_copy)
+ ec.ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+ } else {
+ //
+ // A local variable captured by anonymous methods or itereators.
+ //
+ ec.EmitCapturedVariableInstance (local_info);
+
+ if (prepare_for_load)
+ ig.Emit (OpCodes.Dup);
+ source.Emit (ec);
+ if (leave_copy){
+ ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, Type);
+ temp.Store (ec);
+ }
+ ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
+ if (temp != null)
+ temp.Emit (ec);
+ }
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (local_info.FieldBuilder == null){
+ //
+ // A local variable on the local CLR stack
+ //
+ ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+ } else {
+ //
+ // A local variable captured by anonymous methods or iterators
+ //
+ ec.EmitCapturedVariableInstance (local_info);
+ ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
+ }
+ }
+
+ 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, prepared;
+
+ public bool IsOut {
+ get {
+ return is_out;
+ }
+ }
+
+ public bool IsRef {
+ get {
+ return is_ref;
+ }
+ }
+
+ LocalTemporary temp;
+
+ 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 || TypeManager.IsValueType (type);
+ }
+
+ 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, 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];
+
+ if (ec.CurrentAnonymousMethod != null){
+ if (is_ref){
+ Report.Error (1628, Location,
+ "Can not reference a ref or out parameter in an anonymous method");
+ return;
+ }
+
+ //
+ // If we are referencing the parameter from the external block
+ // flag it for capturing
+ //
+ //Console.WriteLine ("Is parameter `{0}' local? {1}", name, block.IsLocalParameter (name));
+ if (!block.IsLocalParameter (name)){
+ ec.CaptureParameter (name, type, 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;
+
+ if (ec.RemapToProxy)
+ return ec.RemapParameter (idx);
+
+ return this;
+ }
+
+ override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ DoResolveBase (ec);
+
+ SetAssigned (ec);
+
+ if (ec.RemapToProxy)
+ return ec.RemapParameterLValue (idx, right_side);
+
+ 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);
+
+ //
+ // FIXME: Review for anonymous methods
+ //
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+ ec.EmitParameter (name);
+ return;
+ }
+
+ Emit (ec, false);
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ ILGenerator ig = ec.ig;
+ int arg_idx = idx;
+
+ if (!ec.IsStatic)
+ arg_idx++;
+
+ EmitLdArg (ig, arg_idx);
+
+ if (is_ref) {
+ if (prepared)
+ ec.ig.Emit (OpCodes.Dup);
+
+ //
+ // If we are a reference, we loaded on the stack a pointer
+ // Now lets load the real value
+ //
+ LoadFromPtr (ig, type);
+ }
+
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+
+ if (is_ref) {
+ temp = new LocalTemporary (ec, type);
+ temp.Store (ec);
+ }
+ }
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+ ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load);
+ return;
+ }
+
+ ILGenerator ig = ec.ig;
+ int arg_idx = idx;
+
+ prepared = prepare_for_load;
+
+ if (!ec.IsStatic)
+ arg_idx++;
+
+ if (is_ref && !prepared)
+ EmitLdArg (ig, arg_idx);
+
+ source.Emit (ec);
+
+ if (leave_copy)
+ ec.ig.Emit (OpCodes.Dup);
+
+ if (is_ref) {
+ if (leave_copy) {
+ temp = new LocalTemporary (ec, type);
+ temp.Store (ec);
+ }
+
+ StoreFromPtr (ig, type);
+
+ if (temp != null)
+ temp.Emit (ec);
+ } 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.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+ ec.EmitAddressOfParameter (name);
+ 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,
+ ArgList,
+ //FIXME: These two are mbas specific and the
+ // related changes need to be propagated
+ NoArg,
+ AddressOf
+ };
+
+ public readonly AType ArgType;
+ public Expression Expr;
+
+ public Argument (Expression expr, AType type)
+ {
+ this.Expr = expr;
+ this.ArgType = type;
+ }
+
+ public Argument (Expression expr)
+ {
+ this.Expr = expr;
+ this.ArgType = AType.Expression;
+ }
+
+ 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)
+ {
+ if (a.ArgType == AType.ArgList)
+ return "__arglist";
+
+ return (a.ArgType == AType.Ref ? "ref " :
+ (a.ArgType == AType.Out ? "out " : "")) +
+ TypeManager.CSharpName (a.Expr.Type);
+ }
+
+ public bool ResolveMethodGroup (EmitContext ec, Location loc)
+ {
+ ConstructedType ctype = Expr as ConstructedType;
+ if (ctype != null)
+ Expr = ctype.GetSimpleName (ec);
+
+ // 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;
+
+ if (!ec.IsConstructor) {
+ FieldExpr fe = Expr as FieldExpr;
+ if (fe != null && fe.FieldInfo.IsInitOnly) {
+ if (fe.FieldInfo.IsStatic)
+ Report.Error (199, loc, "A static readonly field cannot be passed ref or out (except in a static constructor)");
+ else
+ Report.Error (192, loc, "A readonly field cannot be passed ref or out (except in a constructor)");
+ return false;
+ }
+ }
+ Expr = Expr.ResolveLValue (ec, Expr);
+ } else if (ArgType == AType.Out)
+ Expr = Expr.ResolveLValue (ec, EmptyExpression.Null);
+ else
+ Expr = Expr.Resolve (ec);
+
+ if (Expr == null)
+ return false;
+
+ if (ArgType == AType.Expression)
+ return true;
+ else {
+ //
+ // Catch errors where fields of a MarshalByRefObject are passed as ref or out
+ // This is only allowed for `this'
+ //
+ FieldExpr fe = Expr as FieldExpr;
+ if (fe != null && !fe.IsStatic){
+ Expression instance = fe.InstanceExpression;
+
+ if (instance.GetType () != typeof (This)){
+ if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
+ Report.SymbolRelatedToPreviousError (fe.InstanceExpression.Type);
+ Report.Error (197, loc, "Cannot pass '{0}' as ref or out or take its address because it is a member of a marshal-by-reference class",
+ fe.Name);
+ return false;
+ }
+ }
+ }
+ }
+
+ 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.IsRef)
+ 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;
+
+ public Expression expr;
+ MethodBase method = null;
+
+ 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 {
+ ReflectionParameters rp = new ReflectionParameters (mb);
+ method_parameter_cache [mb] = rp;
+
+ return (ParameterData) rp;
+ }
+ }
+
+ /// <summary>
+ /// Determines "better conversion" as specified in 7.4.2.3
+ ///
+ /// Returns : p if a->p is better,
+ /// q if a->q is better,
+ /// null if neither is better
+ /// </summary>
+ static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
+ {
+ Type argument_type = TypeManager.TypeToCoreType (a.Type);
+ Expression argument_expr = a.Expr;
+
+ // p = TypeManager.TypeToCoreType (p);
+ // q = TypeManager.TypeToCoreType (q);
+
+ if (argument_type == null)
+ throw new Exception ("Expression of type " + a.Expr +
+ " does not resolve its type");
+
+ if (p == null || q == null)
+ throw new InternalErrorException ("BetterConversion Got a null conversion");
+
+ if (p == q)
+ return null;
+
+ if (argument_expr is NullLiteral) {
+ //
+ // If the argument is null and one of the types to compare is 'object' and
+ // the other is a reference type, we prefer the other.
+ //
+ // This follows from the usual rules:
+ // * There is an implicit conversion from 'null' to type 'object'
+ // * There is an implicit conversion from 'null' to any reference type
+ // * There is an implicit conversion from any reference type to type 'object'
+ // * There is no implicit conversion from type 'object' to other reference types
+ // => Conversion of 'null' to a reference type is better than conversion to 'object'
+ //
+ // FIXME: This probably isn't necessary, since the type of a NullLiteral is the
+ // null type. I think it used to be 'object' and thus needed a special
+ // case to avoid the immediately following two checks.
+ //
+ if (!p.IsValueType && q == TypeManager.object_type)
+ return p;
+ if (!q.IsValueType && p == TypeManager.object_type)
+ return q;
+ }
+
+ if (argument_type == p)
+ return p;
+
+ if (argument_type == q)
+ return q;
+
+ Expression p_tmp = new EmptyExpression (p);
+ Expression q_tmp = new EmptyExpression (q);
+
+ bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
+ bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
+
+ if (p_to_q && !q_to_p)
+ return p;
+
+ if (q_to_p && !p_to_q)
+ return q;
+
+ if (p == TypeManager.sbyte_type)
+ if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+ q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.sbyte_type)
+ if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+ p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.short_type)
+ if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+ q == TypeManager.uint64_type)
+ return p;
+
+ if (q == TypeManager.short_type)
+ if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+ p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.int32_type)
+ if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+ return p;
+
+ if (q == TypeManager.int32_type)
+ if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.int64_type)
+ if (q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.int64_type)
+ if (p == TypeManager.uint64_type)
+ return q;
+
+ return null;
+ }
+
+ /// <summary>
+ /// Determines "Better function" between candidate
+ /// and the current best match
+ /// </summary>
+ /// <remarks>
+ /// Returns a boolean indicating :
+ /// false if candidate ain't better
+ /// true if candidate is better than the current best match
+ /// </remarks>
+ static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
+ MethodBase candidate, bool candidate_params,
+ MethodBase best, bool best_params, Location loc)
+ {
+ ParameterData candidate_pd = GetParameterData (candidate);
+ ParameterData best_pd = GetParameterData (best);
+
+ int cand_count = candidate_pd.Count;
+
+ //
+ // If there is no best method, than this one
+ // is better, however, if we already found a
+ // best method, we cant tell. This happens
+ // if we have:
+ //
+ // interface IFoo {
+ // void DoIt ();
+ // }
+ //
+ // interface IBar {
+ // void DoIt ();
+ // }
+ //
+ // interface IFooBar : IFoo, IBar {}
+ //
+ // We cant tell if IFoo.DoIt is better than IBar.DoIt
+ //
+ // However, we have to consider that
+ // Trim (); is better than Trim (params char[] chars);
+ //
+ if (cand_count == 0 && argument_count == 0)
+ return !candidate_params && best_params;
+
+ if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
+ (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
+ if (cand_count != argument_count)
+ return false;
+
+ bool better_at_least_one = false;
+ bool is_equal = true;
+
+ for (int j = 0; j < argument_count; ++j) {
+ Argument a = (Argument) args [j];
+
+ Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (j));
+ Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (j));
+
+ if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+ if (candidate_params)
+ ct = TypeManager.GetElementType (ct);
+
+ if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+ if (best_params)
+ bt = TypeManager.GetElementType (bt);
+
+ if (!ct.Equals (bt))
+ is_equal = false;
+
+ Type better = BetterConversion (ec, a, ct, bt, loc);
+ // for each argument, the conversion to 'ct' should be no worse than
+ // the conversion to 'bt'.
+ if (better == bt)
+ return false;
+
+ // for at least one argument, the conversion to 'ct' should be better than
+ // the conversion to 'bt'.
+ if (better == ct)
+ better_at_least_one = true;
+ }
+
+ //
+ // If a method (in the normal form) with the
+ // same signature as the expanded form of the
+ // current best params method already exists,
+ // the expanded form is not applicable so we
+ // force it to select the candidate
+ //
+ if (!candidate_params && best_params && cand_count == argument_count)
+ return true;
+
+ //
+ // If two methods have equal parameter types, but
+ // only one of them is generic, the non-generic one wins.
+ //
+ if (is_equal) {
+ if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
+ return true;
+ else if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
+ return false;
+ }
+
+ return better_at_least_one;
+ }
+
+ public static string FullMethodDesc (MethodBase mb)
+ {
+ string ret_type = "";
+
+ if (mb == null)
+ return "";
+
+ 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 r in right_set.Methods){
+ if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
+ common.Add (r);
+ }
+
+ miset = new MemberInfo [length1 + length2 - common.Count];
+ left_set.Methods.CopyTo (miset, 0);
+
+ int k = length1;
+
+ foreach (MethodBase r in right_set.Methods) {
+ if (!common.Contains (r))
+ miset [k++] = r;
+ }
+
+ union = new MethodGroupExpr (miset, loc);
+
+ return union;
+ }
+
+ static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
+ ArrayList arguments, int arg_count,
+ ref MethodBase candidate)
+ {
+ return IsParamsMethodApplicable (
+ ec, me, arguments, arg_count, false, ref candidate) ||
+ IsParamsMethodApplicable (
+ ec, me, arguments, arg_count, true, ref candidate);
+
+
+ }
+
+ static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
+ ArrayList arguments, int arg_count,
+ bool do_varargs, ref MethodBase candidate)
+ {
+ if (!me.HasTypeArguments &&
+ !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
+ return false;
+
+ return IsParamsMethodApplicable (
+ ec, arguments, arg_count, candidate, do_varargs);
+ }
+
+ /// <summary>
+ /// Determines if 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,
+ int arg_count, MethodBase candidate,
+ bool do_varargs)
+ {
+ ParameterData pd = GetParameterData (candidate);
+
+ int pd_count = pd.Count;
+
+ if (pd_count == 0)
+ return false;
+
+ int count = pd_count - 1;
+ if (do_varargs) {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
+ return false;
+ if (pd_count != arg_count)
+ return false;
+ } else {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
+ return false;
+ }
+
+ if (count > 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 < count; ++i) {
+
+ Argument a = (Argument) arguments [i];
+
+ Parameter.Modifier a_mod = a.GetParameterModifier () &
+ (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)));
+ Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+ (unchecked (~(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;
+
+ }
+
+ if (do_varargs) {
+ Argument a = (Argument) arguments [count];
+ if (!(a.Expr is Arglist))
+ return false;
+
+ return true;
+ }
+
+ 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.ImplicitConversionExists (ec, a.Expr, element_type))
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool IsApplicable (EmitContext ec, MethodGroupExpr me,
+ ArrayList arguments, int arg_count,
+ ref MethodBase candidate)
+ {
+ if (!me.HasTypeArguments &&
+ !TypeManager.InferTypeArguments (ec, arguments, ref candidate))
+ return false;
+
+ return IsApplicable (ec, arguments, arg_count, candidate);
+ }
+
+ /// <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, int arg_count,
+ MethodBase candidate)
+ {
+ ParameterData pd = GetParameterData (candidate);
+
+ 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 () &
+ unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
+ Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+ unchecked (~(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;
+ }
+
+ static private bool IsAncestralType (Type first_type, Type second_type)
+ {
+ return first_type != second_type &&
+ (second_type.IsSubclassOf (first_type) ||
+ TypeManager.ImplementsInterface (second_type, first_type));
+ }
+
+ /// <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, bool may_fail,
+ Location loc)
+ {
+ MethodBase method = null;
+ bool method_params = false;
+ Type applicable_type = null;
+ int arg_count = 0;
+ ArrayList candidates = new ArrayList ();
+
+ //
+ // Used to keep a map between the candidate
+ // and whether it is being considered in its
+ // normal or expanded form
+ //
+ // false is normal form, true is expanded form
+ //
+ Hashtable candidate_to_form = null;
+
+ if (Arguments != null)
+ arg_count = Arguments.Count;
+
+#if REVIEW_IFDEF
+ if ((me.Name == "Invoke") &&
+ TypeManager.IsDelegateType (me.DeclaringType)) {
+ Error_InvokeOnDelegate (loc);
+ return null;
+ }
+#endif
+
+ MethodBase[] methods = me.Methods;
+
+ //
+ // First we construct the set of applicable methods
+ //
+ bool is_sorted = true;
+ for (int i = 0; i < methods.Length; i++){
+ Type decl_type = methods [i].DeclaringType;
+
+ //
+ // If we have already found an applicable method
+ // we eliminate all base types (Section 14.5.5.1)
+ //
+ if ((applicable_type != null) &&
+ IsAncestralType (decl_type, applicable_type))
+ continue;
+
+ //
+ // Check if candidate is applicable (section 14.4.2.1)
+ // Is candidate applicable in normal form?
+ //
+ bool is_applicable = IsApplicable (
+ ec, me, Arguments, arg_count, ref methods [i]);
+
+ if (!is_applicable &&
+ (IsParamsMethodApplicable (
+ ec, me, Arguments, arg_count, ref methods [i]))) {
+ MethodBase candidate = methods [i];
+ if (candidate_to_form == null)
+ candidate_to_form = new PtrHashtable ();
+ candidate_to_form [candidate] = candidate;
+ // Candidate is applicable in expanded form
+ is_applicable = true;
+ }
+
+ if (!is_applicable)
+ continue;
+
+ candidates.Add (methods [i]);
+
+ if (applicable_type == null)
+ applicable_type = decl_type;
+ else if (applicable_type != decl_type) {
+ is_sorted = false;
+ if (IsAncestralType (applicable_type, decl_type))
+ applicable_type = decl_type;
+ }
+ }
+
+ int candidate_top = candidates.Count;
+
+ if (candidate_top == 0) {
+ //
+ // Okay so we have failed to find anything so we
+ // return by providing info about the closest match
+ //
+ for (int i = 0; i < methods.Length; ++i) {
+ MethodBase c = (MethodBase) methods [i];
+ ParameterData pd = GetParameterData (c);
+
+ if (pd.Count != arg_count)
+ continue;
+
+ if (!TypeManager.InferTypeArguments (ec, Arguments, ref c))
+ continue;
+
+ VerifyArgumentsCompat (ec, Arguments, arg_count,
+ c, false, null, may_fail, loc);
+ break;
+ }
+
+ if (!may_fail) {
+ string report_name = me.Name;
+ if (report_name == ".ctor")
+ report_name = me.DeclaringType.ToString ();
+
+ for (int i = 0; i < methods.Length; ++i) {
+ MethodBase c = methods [i];
+ ParameterData pd = GetParameterData (c);
+
+ if (pd.Count != arg_count)
+ continue;
+
+ if (TypeManager.InferTypeArguments (ec, Arguments, ref c))
+ continue;
+
+ Report.Error (
+ 411, loc, "The type arguments for " +
+ "method `{0}' cannot be infered from " +
+ "the usage. Try specifying the type " +
+ "arguments explicitly.", report_name);
+ return null;
+ }
+
+ Error_WrongNumArguments (
+ loc, report_name, arg_count);
+ return null;
+ }
+
+ return null;
+ }
+
+ if (!is_sorted) {
+ //
+ // At this point, applicable_type is _one_ of the most derived types
+ // in the set of types containing the methods in this MethodGroup.
+ // Filter the candidates so that they only contain methods from the
+ // most derived types.
+ //
+
+ int finalized = 0; // Number of finalized candidates
+
+ do {
+ // Invariant: applicable_type is a most derived type
+
+ // We'll try to complete Section 14.5.5.1 for 'applicable_type' by
+ // eliminating all it's base types. At the same time, we'll also move
+ // every unrelated type to the end of the array, and pick the next
+ // 'applicable_type'.
+
+ Type next_applicable_type = null;
+ int j = finalized; // where to put the next finalized candidate
+ int k = finalized; // where to put the next undiscarded candidate
+ for (int i = finalized; i < candidate_top; ++i) {
+ Type decl_type = ((MethodBase) candidates[i]).DeclaringType;
+
+ if (decl_type == applicable_type) {
+ candidates[k++] = candidates[j];
+ candidates[j++] = candidates[i];
+ continue;
+ }
+
+ if (IsAncestralType (decl_type, applicable_type))
+ continue;
+
+ if (next_applicable_type != null &&
+ IsAncestralType (decl_type, next_applicable_type))
+ continue;
+
+ candidates[k++] = candidates[i];
+
+ if (next_applicable_type == null ||
+ IsAncestralType (next_applicable_type, decl_type))
+ next_applicable_type = decl_type;
+ }
+
+ applicable_type = next_applicable_type;
+ finalized = j;
+ candidate_top = k;
+ } while (applicable_type != null);
+ }
+
+ //
+ // Now we actually find the best method
+ //
+
+ method = (MethodBase) candidates[0];
+ method_params = candidate_to_form != null && candidate_to_form.Contains (method);
+ for (int ix = 1; ix < candidate_top; ix++){
+ MethodBase candidate = (MethodBase) candidates [ix];
+ bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+
+ if (BetterFunction (ec, Arguments, arg_count,
+ candidate, cand_params,
+ method, method_params, loc)) {
+ method = candidate;
+ method_params = cand_params;
+ }
+ }
+
+ //
+ // Now check that there are no ambiguities i.e the selected method
+ // should be better than all the others
+ //
+ bool ambiguous = false;
+ for (int ix = 0; ix < candidate_top; ix++){
+ MethodBase candidate = (MethodBase) candidates [ix];
+
+ if (candidate == method)
+ continue;
+
+ bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+ if (!BetterFunction (ec, Arguments, arg_count,
+ method, method_params,
+ candidate, cand_params,
+ loc)) {
+ Report.SymbolRelatedToPreviousError (candidate);
+ ambiguous = true;
+ }
+ }
+
+ if (ambiguous) {
+ Report.SymbolRelatedToPreviousError (method);
+ 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, arg_count, method,
+ method_params, null, may_fail, 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_InvokeOnDelegate (Location loc)
+ {
+ Report.Error (1533, loc,
+ "Invoke cannot be called directly on a delegate");
+ }
+
+ 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 arg_count, MethodBase method,
+ bool chose_params_expanded,
+ Type delegate_type, bool may_fail,
+ Location loc)
+ {
+ ParameterData pd = GetParameterData (method);
+ int pd_count = pd.Count;
+
+ for (int j = 0; j < arg_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){
+ if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
+ if (!may_fail)
+ 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 if (pm == Parameter.Modifier.ARGLIST){
+ continue;
+ } else {
+ //
+ // Check modifiers
+ //
+ if (pd.ParameterModifier (j) != a.GetParameterModifier ()){
+ if (!may_fail)
+ Error_InvalidArguments (
+ loc, j, method, delegate_type,
+ Argument.FullDesc (a), pd.ParameterDesc (j));
+ return false;
+ }
+ }
+
+ //
+ // Check Type
+ //
+ if (!TypeManager.IsEqual (a.Type, parameter_type)){
+ Expression conv;
+
+ conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
+
+ if (conv == null) {
+ if (!may_fail)
+ 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;
+ }
+
+ if (parameter_type.IsPointer){
+ if (!ec.InUnsafe){
+ UnsafeError (loc);
+ return false;
+ }
+ }
+
+ Parameter.Modifier a_mod = a.GetParameterModifier () &
+ unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
+ Parameter.Modifier p_mod = pd.ParameterModifier (j) &
+ unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF));
+
+ if (a_mod != p_mod &&
+ pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
+ if (!may_fail) {
+ 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 ConstructedType)
+ expr = ((ConstructedType) expr).GetSimpleName (ec);
+
+ 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, loc);
+ 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, false, loc);
+
+ if (method == null)
+ 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);
+ return null;
+ }
+
+ Expression iexpr = mg.InstanceExpression;
+ if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
+ if (mg.IdenticalTypeName)
+ mg.InstanceExpression = null;
+ else {
+ MemberAccess.error176 (loc, mi.Name);
+ return null;
+ }
+ }
+ }
+
+ if (type.IsPointer){
+ if (!ec.InUnsafe){
+ UnsafeError (loc);
+ return null;
+ }
+ }
+
+ //
+ // Only base will allow this invocation to happen.
+ //
+ if (mg.IsBase && method.IsAbstract){
+ Report.Error (205, loc, "Cannot call an abstract base member: " +
+ FullMethodDesc (method));
+ return null;
+ }
+
+ if (method.Name == "Finalize" && Arguments == null) {
+ if (mg.IsBase)
+ Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
+ else
+ Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
+ return null;
+ }
+
+ if ((method.Attributes & MethodAttributes.SpecialName) != 0){
+ if (TypeManager.LookupDeclSpace (method.DeclaringType) != null || TypeManager.IsSpecialMethod (method)) {
+ Report.Error (571, loc, TypeManager.CSharpSignature (method) + ": can not call operator or accessor");
+ return null;
+ }
+ }
+
+ if (mg.InstanceExpression != null)
+ mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
+
+ 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;
+
+ IntConstant.EmitInt (ig, count);
+ ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
+
+ int top = arguments.Count;
+ for (int j = idx; j < top; j++){
+ a = (Argument) arguments [j];
+
+ ig.Emit (OpCodes.Dup);
+ IntConstant.EmitInt (ig, j - idx);
+
+ bool is_stobj, has_type_arg;
+ OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj, out has_type_arg);
+ if (is_stobj)
+ ig.Emit (OpCodes.Ldelema, t);
+
+ a.Emit (ec);
+
+ if (has_type_arg)
+ ig.Emit (op, t);
+ else
+ ig.Emit (op);
+ }
+ }
+
+ /// <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)
+ ///
+ /// if `dup_args' is true, a copy of the arguments will be left
+ /// on the stack. If `dup_args' is true, you can specify `this_arg'
+ /// which will be duplicated before any other args. Only EmitCall
+ /// should be using this interface.
+ /// </summary>
+ public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments, bool dup_args, LocalTemporary this_arg)
+ {
+ ParameterData pd;
+ if (mb != null)
+ pd = GetParameterData (mb);
+ else
+ pd = null;
+
+ LocalTemporary [] temps = null;
+
+ if (dup_args)
+ temps = new LocalTemporary [arguments.Count];
+
+ //
+ // 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 (dup_args) {
+ ec.ig.Emit (OpCodes.Dup);
+ (temps [i] = new LocalTemporary (ec, a.Type)).Store (ec);
+ }
+ }
+
+ if (dup_args) {
+ if (this_arg != null)
+ this_arg.Emit (ec);
+
+ for (int i = 0; i < top; i ++)
+ temps [i].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)));
+ }
+ }
+
+ static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
+ ArrayList arguments)
+ {
+ ParameterData pd = GetParameterData (mb);
+
+ if (arguments == null)
+ return new Type [0];
+
+ Argument a = (Argument) arguments [pd.Count - 1];
+ Arglist list = (Arglist) a.Expr;
+
+ return list.ArgumentTypes;
+ }
+
+ /// <summary>
+ /// This checks the ConditionalAttribute on the method
+ /// </summary>
+ static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+ {
+ if (method.IsConstructor)
+ return false;
+
+ IMethodData md = TypeManager.GetMethod (method);
+ if (md != null)
+ return md.IsExcluded (ec);
+
+ // For some methods (generated by delegate class) GetMethod returns null
+ // because they are not included in builder_to_method table
+ if (method.DeclaringType is TypeBuilder)
+ return false;
+
+ return AttributeTester.IsConditionalMethodExcluded (method);
+ }
+
+ /// <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)
+ {
+ EmitCall (ec, is_base, is_static, instance_expr, method, Arguments, loc, false, false);
+ }
+
+ // `dup_args' leaves an extra copy of the arguments on the stack
+ // `omit_args' does not leave any arguments at all.
+ // So, basically, you could make one call with `dup_args' set to true,
+ // and then another with `omit_args' set to true, and the two calls
+ // would have the same set of arguments. However, each argument would
+ // only have been evaluated once.
+ public static void EmitCall (EmitContext ec, bool is_base,
+ bool is_static, Expression instance_expr,
+ MethodBase method, ArrayList Arguments, Location loc,
+ bool dup_args, bool omit_args)
+ {
+ ILGenerator ig = ec.ig;
+ bool struct_call = false;
+ bool this_call = false;
+ LocalTemporary this_arg = null;
+
+ 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;
+ }
+
+ if (ec.TestObsoleteMethodUsage) {
+ //
+ // This checks ObsoleteAttribute on the method and on the declaring type
+ //
+ ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
+
+ oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+ }
+ }
+
+ if (IsMethodExcluded (method, ec))
+ return;
+
+ if (!is_static){
+ this_call = instance_expr == null;
+ if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType))
+ struct_call = true;
+
+ //
+ // If this is ourselves, push "this"
+ //
+ if (!omit_args) {
+ Type t = null;
+ if (this_call) {
+ ig.Emit (OpCodes.Ldarg_0);
+ t = decl_type;
+ } else {
+ Type iexpr_type = instance_expr.Type;
+
+ //
+ // Push the instance expression
+ //
+ if (TypeManager.IsValueType (iexpr_type)) {
+ //
+ // Special case: calls to a function declared in a
+ // reference-type with a value-type argument need
+ // to have their value boxed.
+ if (decl_type.IsValueType ||
+ iexpr_type.IsGenericParameter) {
+ //
+ // 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 {
+ LocalTemporary temp = new LocalTemporary (ec, iexpr_type);
+ instance_expr.Emit (ec);
+ temp.Store (ec);
+ temp.AddressOf (ec, AddressOp.Load);
+ }
+
+ // avoid the overhead of doing this all the time.
+ if (dup_args)
+ t = TypeManager.GetReferenceType (iexpr_type);
+ } else {
+ instance_expr.Emit (ec);
+ ig.Emit (OpCodes.Box, instance_expr.Type);
+ t = TypeManager.object_type;
+ }
+ } else {
+ instance_expr.Emit (ec);
+ t = instance_expr.Type;
+ }
+ }
+
+ if (dup_args) {
+ this_arg = new LocalTemporary (ec, t);
+ ig.Emit (OpCodes.Dup);
+ this_arg.Store (ec);
+ }
+ }
+ }
+
+ if (!omit_args)
+ EmitArguments (ec, method, Arguments, dup_args, this_arg);
+
+ if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
+ ig.Emit (OpCodes.Constrained, instance_expr.Type);
+
+ OpCode call_op;
+ if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
+ call_op = OpCodes.Call;
+ else
+ call_op = OpCodes.Callvirt;
+
+ if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
+ Type[] varargs_types = GetVarargsTypes (ec, method, Arguments);
+ ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
+ return;
+ }
+
+ //
+ // If you have:
+ // this.DoFoo ();
+ // and DoFoo is not virtual, you can omit the callvirt,
+ // because you don't need the null checking behavior.
+ //
+ if (method is MethodInfo)
+ ig.Emit (call_op, (MethodInfo) method);
+ else
+ ig.Emit (call_op, (ConstructorInfo) method);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+
+ EmitCall (ec, mg.IsBase, 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.
+ //
+ TypeExpr te = expr.ResolveAsTypeStep (ec) as TypeExpr;
+ if ((te != null) && (te.eclass == ExprClass.Type)) {
+ Cast cast = new Cast (te, 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 TypeExpression (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.
+ //
+ TypeExpr te = expr.ResolveAsTypeStep (ec) as TypeExpr;
+ if ((te != null) && (te.eclass == ExprClass.Type)) {
+ 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;
+
+ //
+ // During bootstrap, it contains the RequestedType,
+ // but if `type' is not null, it *might* contain a NewDelegate
+ // (because of field multi-initialization)
+ //
+ public 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;
+ bool is_type_parameter = 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", loc);
+ 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){
+ if (RequestedType is NewDelegate)
+ return RequestedType;
+ return this;
+ }
+
+ TypeExpr texpr = RequestedType.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ type = texpr.Type;
+ if (type == null)
+ return null;
+
+ CheckObsoleteAttribute (type);
+
+ bool IsDelegate = TypeManager.IsDelegateType (type);
+
+ if (IsDelegate){
+ RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+ if (RequestedType != null)
+ if (!(RequestedType is DelegateCreation))
+ throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
+ return RequestedType;
+ }
+
+ if (type.IsGenericParameter) {
+ if (!TypeManager.HasConstructorConstraint (type)) {
+ Error (304, String.Format (
+ "Cannot create an instance of the " +
+ "variable type '{0}' because it " +
+ "doesn't have the new() constraint",
+ type));
+ return null;
+ }
+
+ if ((Arguments != null) && (Arguments.Count != 0)) {
+ Error (417, String.Format (
+ "`{0}': cannot provide arguments " +
+ "when creating an instance of a " +
+ "variable type.", type));
+ return null;
+ }
+
+ is_type_parameter = true;
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ if (type.IsInterface || type.IsAbstract){
+ Error (144, "It is not possible to create instances of interfaces or abstract classes");
+ return null;
+ }
+
+ if (type.IsAbstract && type.IsSealed) {
+ Report.Error (712, loc, "Cannot create an instance of the static class '{0}'", TypeManager.CSharpName (type));
+ 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, type, type, ".ctor",
+ // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
+ MemberTypes.Constructor,
+ AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+ if (ml == null)
+ return null;
+
+ if (! (ml is MethodGroupExpr)){
+ if (!is_struct){
+ ml.Error_UnexpectedKind ("method group", loc);
+ 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, false, 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;
+ }
+
+ bool DoEmitTypeParameter (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ ig.Emit (OpCodes.Ldtoken, type);
+ ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+ ig.Emit (OpCodes.Call, TypeManager.activator_create_instance);
+ ig.Emit (OpCodes.Unbox_Any, type);
+
+ return true;
+ }
+
+ //
+ // 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 = TypeManager.IsValueType (type);
+ 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, false, null);
+
+ 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)
+ {
+ if (is_type_parameter)
+ DoEmitTypeParameter (ec);
+ else
+ DoEmit (ec, true);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ if (is_type_parameter)
+ throw new InvalidOperationException ();
+
+ if (DoEmit (ec, false))
+ ec.ig.Emit (OpCodes.Pop);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp Mode)
+ {
+ if (is_type_parameter)
+ throw new InvalidOperationException ();
+
+ 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, false, null);
+
+ 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 : Expression {
+ 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)
+ return false;
+
+ // 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 || conv is DecimalConstant || conv is NullCast) {
+ // These are subclasses of Constant that can appear as elements of an
+ // array that cannot be statically initialized (with num_automatic_initializers
+ // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
+ array_data.Add (conv);
+ } else if (conv is Constant) {
+ // These are the types of Constant that can appear in arrays that can be
+ // statically allocated.
+ 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;
+ }
+ }
+
+ //
+ // 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){
+ Expression.Error_NegativeArrayIndex (loc);
+ return null;
+ }
+ }
+
+ if (target is LongConstant){
+ if (((LongConstant) target).Value < 0){
+ Expression.Error_NegativeArrayIndex (loc);
+ 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
+ //
+ TypeExpr array_type_expr;
+ array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
+ array_type_expr = array_type_expr.ResolveAsTypeTerminal (ec);
+ if (array_type_expr == null)
+ return false;
+
+ type = array_type_expr.Type;
+
+ if (!type.IsArray) {
+ Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
+ return false;
+ }
+ underlying_type = TypeManager.GetElementType (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 (array_element_type.IsAbstract && array_element_type.IsSealed) {
+ Report.Error (719, loc, "'{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type));
+ return null;
+ }
+
+ 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", loc);
+ 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, false, 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.Module.Builder;
+ 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)
+ {
+ //
+ // First, the static data
+ //
+ FieldBuilder fb;
+ ILGenerator ig = ec.ig;
+
+ byte [] data = MakeByteBlob (array_data, underlying_type, loc);
+
+ fb = RootContext.MakeStaticData (data);
+
+ 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)
+ {
+ ILGenerator ig = ec.ig;
+ int dims = bounds.Count;
+ int [] current_pos = new int [dims];
+ int top = array_data.Count;
+
+ MethodInfo set = null;
+
+ if (dims != 1){
+ Type [] args;
+ ModuleBuilder mb = null;
+ mb = CodeGen.Module.Builder;
+ 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.Dup);
+
+ 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.IsBuiltinOrEnum (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) {
+ bool is_stobj, has_type_arg;
+ OpCode op = ArrayAccess.GetStoreOpcode (
+ etype, out is_stobj,
+ out has_type_arg);
+ if (is_stobj)
+ ig.Emit (OpCodes.Stobj, etype);
+ else if (has_type_arg)
+ ig.Emit (op, etype);
+ else
+ ig.Emit (op);
+ } 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;
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ 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;
+
+ // This will never be true for array types that cannot be statically
+ // initialized. num_automatic_initializers will always be zero. See
+ // CheckIndices.
+ if (num_automatic_initializers > max_automatic_initializers)
+ EmitStaticInitializers (ec);
+
+ if (dynamic_initializers)
+ EmitDynamicInitializers (ec);
+ }
+ }
+
+ 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, array_element_type, 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)
+ {
+ if ((variable_info == null) || (variable_info.LocalInfo == null))
+ return false;
+ else
+ return variable_info.LocalInfo.IsFixed;
+ }
+
+ public bool ResolveBase (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+
+ if (ec.TypeContainer.CurrentType != null)
+ type = ec.TypeContainer.CurrentType;
+ else
+ 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.ThisVariable.VariableInfo;
+
+ 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 void Emit (EmitContext ec, bool leave_copy)
+ {
+ Emit (ec);
+ if (leave_copy)
+ ec.ig.Emit (OpCodes.Dup);
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (ec.TypeContainer is Struct){
+ ec.EmitThis ();
+ source.Emit (ec);
+ if (leave_copy)
+ ec.ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Stobj, type);
+ } else {
+ throw new Exception ("how did you get here");
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ ec.EmitThis ();
+ if (ec.TypeContainer is Struct)
+ ig.Emit (OpCodes.Ldobj, type);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ ec.EmitThis ();
+
+ // 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>
+ /// Represents the `__arglist' construct
+ /// </summary>
+ public class ArglistAccess : Expression
+ {
+ public ArglistAccess (Location loc)
+ {
+ this.loc = loc;
+ }
+
+ public bool ResolveBase (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+ type = TypeManager.runtime_argument_handle_type;
+ return true;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (!ResolveBase (ec))
+ return null;
+
+ if (ec.IsFieldInitializer || !ec.CurrentBlock.HasVarargs) {
+ Error (190, "The __arglist construct is valid only within " +
+ "a variable argument method.");
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Arglist);
+ }
+ }
+
+ /// <summary>
+ /// Represents the `__arglist (....)' construct
+ /// </summary>
+ public class Arglist : Expression
+ {
+ public readonly Argument[] Arguments;
+
+ public Arglist (Argument[] args, Location l)
+ {
+ Arguments = args;
+ loc = l;
+ }
+
+ public Type[] ArgumentTypes {
+ get {
+ Type[] retval = new Type [Arguments.Length];
+ for (int i = 0; i < Arguments.Length; i++)
+ retval [i] = Arguments [i].Type;
+ return retval;
+ }
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+ type = TypeManager.runtime_argument_handle_type;
+
+ foreach (Argument arg in Arguments) {
+ if (!arg.Resolve (ec, loc))
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ foreach (Argument arg in Arguments)
+ arg.Emit (ec);
+ }
+ }
+
+ //
+ // This produces the value that renders an instance, used by the iterators code
+ //
+ public class ProxyInstance : Expression, IMemoryLocation {
+ public override Expression DoResolve (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+ type = ec.ContainerType;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Ldarg_0);
+
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ ec.ig.Emit (OpCodes.Ldarg_0);
+ }
+ }
+
+ /// <summary>
+ /// Implements the typeof operator
+ /// </summary>
+ public class TypeOf : Expression {
+ public Expression QueriedType;
+ protected Type typearg;
+
+ public TypeOf (Expression queried_type, Location l)
+ {
+ QueriedType = queried_type;
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ typearg = texpr.Type;
+
+ 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;
+ }
+
+ if (typearg.IsPointer && !ec.InUnsafe){
+ UnsafeError (loc);
+ return null;
+ }
+ CheckObsoleteAttribute (typearg);
+
+ 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 : TypeOf {
+ public TypeOfVoid (Location l) : base (null, l)
+ {
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ type = TypeManager.type_type;
+ typearg = TypeManager.void_type;
+ eclass = ExprClass.Type;
+ return this;
+ }
+ }
+
+ /// <summary>
+ /// Implements the sizeof expression
+ /// </summary>
+ public class SizeOf : Expression {
+ public 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;
+ }
+
+ TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ if (texpr is TypeParameterExpr){
+ ((TypeParameterExpr)texpr).Error_CannotUseAsUnmanagedType (loc);
+ return null;
+ }
+
+ type_queried = texpr.Type;
+
+ CheckObsoleteAttribute (type_queried);
+
+ 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 string Identifier;
+ protected Expression expr;
+ protected TypeArguments args;
+
+ public MemberAccess (Expression expr, string id, Location l)
+ {
+ this.expr = expr;
+ Identifier = id;
+ loc = l;
+ }
+
+ public MemberAccess (Expression expr, string id, TypeArguments args,
+ Location l)
+ : this (expr, id, l)
+ {
+ this.args = args;
+ }
+
+ public Expression Expr {
+ get {
+ return expr;
+ }
+ }
+
+ public 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");
+ }
+
+ public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
+ {
+ SimpleName sn = left_original as SimpleName;
+ if (sn == null || left == null || left.Type.Name != sn.Name)
+ return false;
+
+ return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
+ }
+
+ // TODO: possible optimalization
+ // Cache resolved constant result in FieldBuilder <-> expresion map
+ 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.Mono_GetGenericFieldDefinition ();
+ Type decl_type = fi.DeclaringType;
+
+ bool is_emitted = fi is FieldBuilder;
+ Type t = fi.FieldType;
+
+ if (is_emitted) {
+ Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
+
+ if (c != null) {
+ object o;
+ if (!c.LookupConstantValue (out o))
+ return null;
+
+ object real_value = ((Constant) c.Expr).GetValue ();
+
+ return Constantify (real_value, t);
+ }
+ }
+
+ // IsInitOnly is because of MS compatibility, I don't know why but they emit decimal constant as InitOnly
+ if (fi.IsInitOnly && !is_emitted && t == TypeManager.decimal_type) {
+ object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+ if (attrs.Length == 1)
+ return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+ }
+
+ if (fi.IsLiteral) {
+ object o;
+
+ if (is_emitted)
+ 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, member_lookup, 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 (t.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 ||
+ TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
+ 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.
+ //
+ ee.InstanceExpression = left;
+ 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;
+
+ ee.InstanceExpression = left;
+
+ return ResolveMemberAccess (ec, ml, left, loc, left_original);
+ }
+ }
+
+ if (member_lookup is IMemberExpr) {
+ IMemberExpr me = (IMemberExpr) member_lookup;
+ MethodGroupExpr mg = me as MethodGroupExpr;
+
+ if (left_is_type){
+ 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, member_lookup, loc))
+ return member_lookup;
+
+ SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+ return null;
+ }
+
+ } else {
+ if (!me.IsInstance){
+ if (IdenticalNameAndTypeName (ec, left_original, left, 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;
+ }
+ }
+
+ if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc))
+ mg.IdenticalTypeName = true;
+
+ 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 (1);
+ return null;
+ }
+
+ public virtual 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.Intermediate | ResolveFlags.DisableFlowAnalysis);
+ if (expr == null)
+ return null;
+
+ if (expr is SimpleName){
+ SimpleName child_expr = (SimpleName) expr;
+ string fqname = DeclSpace.MakeFQN (child_expr.Name, Identifier);
+
+ Expression new_expr;
+ if (args != null)
+ new_expr = new ConstructedType (fqname, args, loc);
+ else
+ new_expr = new SimpleName (fqname, 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
+ //
+
+ Type expr_type;
+ if (expr is TypeExpr){
+ expr_type = expr.Type;
+
+ if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
+ Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", expr_type);
+ 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){
+ MemberCore mc = en.GetDefinition (Identifier);
+ ObsoleteAttribute oa = mc.GetObsoleteAttribute (en);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, mc.GetSignatureForError (), Location);
+ }
+ oa = en.GetObsoleteAttribute (en);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location);
+ }
+
+ Constant c = Constantify (value, en.UnderlyingType);
+ return new EnumConstant (c, expr_type);
+ }
+ } else {
+ CheckObsoleteAttribute (expr_type);
+
+ FieldInfo fi = expr_type.GetField (Identifier);
+ if (fi != null) {
+ ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location);
+ }
+ }
+ }
+ } else
+ expr_type = expr.Type;
+
+ if (expr_type.IsPointer){
+ Error (23, "The `.' operator can not be applied to pointer operands (" +
+ TypeManager.CSharpName (expr_type) + ")");
+ return null;
+ }
+
+ int errors = Report.Errors;
+
+ Expression member_lookup;
+ member_lookup = MemberLookup (
+ ec, expr_type, expr_type, Identifier, loc);
+ if ((member_lookup == null) && (args != null)) {
+ string lookup_id = MemberName.MakeName (Identifier, args);
+ member_lookup = MemberLookup (
+ ec, expr_type, expr_type, lookup_id, loc);
+ }
+ if (member_lookup == null) {
+ MemberLookupFailed (
+ ec, expr_type, expr_type, Identifier, null, loc);
+ 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;
+ }
+
+ if (args != null) {
+ string full_name = expr_type + "." + Identifier;
+
+ if (member_lookup is FieldExpr) {
+ Report.Error (307, loc, "The field `{0}' cannot " +
+ "be used with type arguments", full_name);
+ return null;
+ } else if (member_lookup is EventExpr) {
+ Report.Error (307, loc, "The event `{0}' cannot " +
+ "be used with type arguments", full_name);
+ return null;
+ } else if (member_lookup is PropertyExpr) {
+ Report.Error (307, loc, "The property `{0}' cannot " +
+ "be used with type arguments", full_name);
+ return null;
+ }
+ }
+
+ member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+ if (member_lookup == null)
+ return null;
+
+ if (args != null) {
+ MethodGroupExpr mg = member_lookup as MethodGroupExpr;
+ if (mg == null)
+ throw new InternalErrorException ();
+
+ return mg.ResolveGeneric (ec, args);
+ }
+
+ // 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;
+
+ fname = MemberName.MakeName (fname, args);
+
+ 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) {
+ if (args == null)
+ return new TypeExpression (fully_qualified, loc);
+
+ ConstructedType ctype = new ConstructedType (fully_qualified, args, loc);
+ return ctype.ResolveAsTypeStep (ec);
+ }
+ }
+
+ 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;
+ string fqname = DeclSpace.MakeFQN (child_expr.Name, Identifier);
+
+ if (args != null)
+ new_expr = new ConstructedType (fqname, args, loc);
+ else
+ new_expr = new SimpleName (fqname, loc);
+
+ return new_expr.ResolveAsTypeStep (ec);
+ }
+
+ TypeExpr tnew_expr = new_expr.ResolveAsTypeTerminal (ec);
+ if (tnew_expr == null)
+ return null;
+
+ Type expr_type = tnew_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;
+ string lookup_id;
+ lookup_id = MemberName.MakeName (Identifier, args);
+ member_lookup = MemberLookupFinal (
+ ec, expr_type, expr_type, lookup_id, loc);
+ if (member_lookup == null)
+ return null;
+
+ TypeExpr texpr = member_lookup as TypeExpr;
+ if (texpr == null)
+ return null;
+
+ texpr = texpr.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ TypeArguments the_args = args;
+ if (TypeManager.HasGenericArguments (expr_type)) {
+ Type[] decl_args = TypeManager.GetTypeArguments (expr_type);
+
+ TypeArguments new_args = new TypeArguments (loc);
+ foreach (Type decl in decl_args)
+ new_args.Add (new TypeExpression (decl, loc));
+
+ if (args != null)
+ new_args.Add (args);
+
+ the_args = new_args;
+ }
+
+ if (the_args != null) {
+ ConstructedType ctype = new ConstructedType (texpr.Type, the_args, loc);
+ return ctype.ResolveAsTypeStep (ec);
+ }
+
+ return texpr;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new Exception ("Should not happen");
+ }
+
+ public override string ToString ()
+ {
+ return expr + "." + MemberName.MakeName (Identifier, args);
+ }
+ }
+
+ /// <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 (EmitContext ec)
+ {
+ 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).Resolve (ec);
+ if (p == null)
+ return null;
+ return new Indirection (p, loc).Resolve (ec);
+ }
+
+ 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 (ec);
+ 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 (ec);
+ 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 temp;
+ bool prepared;
+
+ public ArrayAccess (ElementAccess ea_data, Location l)
+ {
+ ea = ea_data;
+ eclass = ExprClass.Variable;
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+#if false
+ ExprClass eclass = ea.Expr.eclass;
+
+ // 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) {
+ Constant c = a.Expr as Constant;
+ if (c != null && c.IsNegative) {
+ Report.Warning (251, 2, a.Expr.Location, "Indexing an array with a negative index (array indices always start at zero)");
+ }
+ 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 (TypeManager.IsEnumType (type)){
+ EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+ } else if (type.IsValueType){
+ ig.Emit (OpCodes.Ldelema, type);
+ ig.Emit (OpCodes.Ldobj, type);
+ } else if (type.IsGenericParameter)
+ ig.Emit (OpCodes.Ldelem_Any, type);
+ else
+ ig.Emit (OpCodes.Ldelem_Ref);
+ }
+
+ /// <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, out bool has_type_arg)
+ {
+ //Console.WriteLine (new System.Diagnostics.StackTrace ());
+ has_type_arg = false; is_stobj = false;
+ t = TypeManager.TypeToCoreType (t);
+ if (TypeManager.IsEnumType (t))
+ 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) {
+ has_type_arg = true;
+ is_stobj = true;
+ return OpCodes.Stobj;
+ } else if (t.IsValueType) {
+ has_type_arg = true;
+ is_stobj = true;
+ return OpCodes.Stobj;
+ } else if (t.IsGenericParameter) {
+ has_type_arg = true;
+ return OpCodes.Stelem_Any;
+ } else
+ return OpCodes.Stelem_Ref;
+ }
+
+ MethodInfo FetchGetMethod ()
+ {
+ ModuleBuilder mb = CodeGen.Module.Builder;
+ 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.Module.Builder;
+ 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;
+
+ 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);
+ }
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ int rank = ea.Expr.Type.GetArrayRank ();
+ ILGenerator ig = ec.ig;
+
+ if (!prepared) {
+ LoadArrayAndArguments (ec);
+
+ if (rank == 1)
+ EmitLoadOpcode (ig, type);
+ else {
+ MethodInfo method;
+
+ method = FetchGetMethod ();
+ ig.Emit (OpCodes.Call, method);
+ }
+ } else
+ LoadFromPtr (ec.ig, this.type);
+
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, this.type);
+ temp.Store (ec);
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
+ {
+ int rank = ea.Expr.Type.GetArrayRank ();
+ ILGenerator ig = ec.ig;
+ Type t = source.Type;
+ prepared = prepare_for_load;
+
+ if (prepare_for_load) {
+ AddressOf (ec, AddressOp.LoadStore);
+ ec.ig.Emit (OpCodes.Dup);
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, this.type);
+ temp.Store (ec);
+ }
+ StoreFromPtr (ec.ig, t);
+
+ if (temp != null)
+ temp.Emit (ec);
+
+ return;
+ }
+
+ LoadArrayAndArguments (ec);
+
+ if (rank == 1) {
+ bool is_stobj, has_type_arg;
+ OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
+
+ //
+ // The stobj opcode used by value types will need
+ // an address on the stack, not really an array/array
+ // pair
+ //
+ if (is_stobj)
+ ig.Emit (OpCodes.Ldelema, t);
+
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, this.type);
+ temp.Store (ec);
+ }
+
+ if (is_stobj)
+ ig.Emit (OpCodes.Stobj, t);
+ else if (has_type_arg)
+ ig.Emit (op, t);
+ else
+ ig.Emit (op);
+ } else {
+ ModuleBuilder mb = CodeGen.Module.Builder;
+ int arg_count = ea.Arguments.Count;
+ Type [] args = new Type [arg_count + 1];
+ MethodInfo set;
+
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, this.type);
+ temp.Store (ec);
+ }
+
+ 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);
+ }
+
+ if (temp != null)
+ temp.Emit (ec);
+ }
+
+ 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;
+
+ public struct Indexer {
+ public readonly Type Type;
+ public readonly MethodInfo Getter, Setter;
+
+ public Indexer (Type type, MethodInfo get, MethodInfo set)
+ {
+ this.Type = type;
+ this.Getter = get;
+ this.Setter = set;
+ }
+ }
+
+ 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 Indexer (property.PropertyType, 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, null);
+
+ 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;
+ }
+
+ if (!lookup_type.IsInterface)
+ return ix;
+
+ Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+ if (ifaces != null) {
+ foreach (Type itype in ifaces) {
+ MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
+ if (mi != null){
+ if (ix == null)
+ ix = new Indexers ();
+
+ ix.Append (mi);
+ }
+ }
+ }
+
+ 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 (Indexers.Indexer ix in ilist.Properties) {
+ if (ix.Getter != null)
+ AllGetters.Add(ix.Getter);
+ }
+ }
+ }
+
+ if (AllGetters.Count > 0) {
+ found_any_getters = true;
+ get = (MethodInfo) Invocation.OverloadResolve (
+ ec, new MethodGroupExpr (AllGetters, loc),
+ arguments, false, 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;
+ }
+
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+
+ eclass = ExprClass.IndexerAccess;
+ return this;
+ }
+
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ ArrayList AllSetters = new ArrayList();
+ if (!CommonResolve (ec))
+ return null;
+
+ 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 (Indexers.Indexer ix in ilist.Properties) {
+ if (ix.Setter != null)
+ AllSetters.Add(ix.Setter);
+ }
+ }
+ }
+ 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, false, 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 (Indexers.Indexer ix in ilist.Properties){
+ if (ix.Setter == set){
+ type = ix.Type;
+ break;
+ }
+ }
+
+ instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+
+ eclass = ExprClass.IndexerAccess;
+ return this;
+ }
+
+ bool prepared = false;
+ LocalTemporary temp;
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc, prepared, false);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, Type);
+ temp.Store (ec);
+ }
+ }
+
+ //
+ // 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, bool leave_copy, bool prepare_for_load)
+ {
+ prepared = prepare_for_load;
+ Argument a = (Argument) set_arguments [set_arguments.Count - 1];
+
+ if (prepared) {
+ source.Emit (ec);
+ if (leave_copy) {
+ ec.ig.Emit (OpCodes.Dup);
+ temp = new LocalTemporary (ec, Type);
+ temp.Store (ec);
+ }
+ } else if (leave_copy) {
+ temp = new LocalTemporary (ec, Type);
+ source.Emit (ec);
+ temp.Store (ec);
+ a.Expr = temp;
+ }
+
+ Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc, false, prepared);
+
+ if (temp != null)
+ temp.Emit (ec);
+ }
+
+
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+ }
+ }
+
+ /// <summary>
+ /// The base operator for method names
+ /// </summary>
+ public class BaseAccess : Expression {
+ public 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;
+ }
+
+ if (ec.IsFieldInitializer){
+ Error (1512, "Keyword base is not available in the current context");
+ 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 TypeExpression (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;
+ }
+
+ if (e is MethodGroupExpr)
+ ((MethodGroupExpr) e).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 static readonly EmptyExpression Null = new EmptyExpression ();
+
+ // TODO: should be protected
+ 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 Expression Source {
+ get {
+ return source;
+ }
+ }
+
+ 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 : TypeExpr {
+ Expression left;
+ string dim;
+
+ public ComposedCast (Expression left, string dim, Location l)
+ {
+ this.left = left;
+ this.dim = dim;
+ loc = l;
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ TypeExpr lexpr = left.ResolveAsTypeTerminal (ec);
+ if (lexpr == null)
+ return null;
+
+ Type ltype = lexpr.Type;
+
+ if ((ltype == TypeManager.void_type) && (dim != "*")) {
+ Report.Error (1547, Location,
+ "Keyword 'void' cannot be used in this context");
+ return null;
+ }
+
+ int pos = 0;
+ while ((pos < dim.Length) && (dim [pos] == '[')) {
+ pos++;
+
+ if (dim [pos] == ']') {
+ ltype = ltype.MakeArrayType ();
+ pos++;
+
+ if (pos < dim.Length)
+ continue;
+
+ type = ltype;
+ eclass = ExprClass.Type;
+ return this;
+ }
+
+ int rank = 0;
+ while (dim [pos] == ',') {
+ pos++; rank++;
+ }
+
+ if ((dim [pos] != ']') || (pos != dim.Length-1))
+ return null;
+
+ type = ltype.MakeArrayType (rank + 1);
+ eclass = ExprClass.Type;
+ return this;
+ }
+
+ //
+ // ltype.Fullname is already fully qualified, so we can skip
+ // a lot of probes, and go directly to TypeManager.LookupType
+ //
+ string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
+ string cname = fname + 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.InUnsafe && type.IsPointer){
+ UnsafeError (loc);
+ return null;
+ }
+
+ eclass = ExprClass.Type;
+ return this;
+ }
+
+ public override string Name {
+ get {
+ 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;
+ }
+
+ Constant c = count as Constant;
+ if (c != null && c.IsNegative) {
+ Report.Error (247, loc, "Cannot use a negative size with stackalloc");
+ return null;
+ }
+
+ if (ec.CurrentBranching.InCatch () ||
+ ec.CurrentBranching.InFinally (true)) {
+ Error (255,
+ "stackalloc can not be used in a catch or finally block");
+ return null;
+ }
+
+ TypeExpr texpr = t.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ otype = texpr.Type;
+
+ 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);
+ }
+ }
+}
--- /dev/null
+//
+// flowanalyis.cs: The control flow analysis code
+//
+// Author:
+// Martin Baulig (martin@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+namespace Mono.CSharp
+{
+ // <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 abstract class FlowBranching
+ {
+ // <summary>
+ // The type of a FlowBranching.
+ // </summary>
+ public enum BranchingType : byte {
+ // Normal (conditional or toplevel) block.
+ Block,
+
+ // Conditional.
+ Conditional,
+
+ // A loop block.
+ Loop,
+
+ // Try/Catch block.
+ Exception,
+
+ // Switch block.
+ Switch,
+
+ // Switch section.
+ SwitchSection
+ }
+
+ // <summary>
+ // The type of one sibling of a branching.
+ // </summary>
+ public enum SiblingType : byte {
+ Block,
+ Conditional,
+ SwitchSection,
+ Try,
+ Catch,
+ Finally
+ }
+
+ // <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 : byte {
+ Undefined = 0,
+
+ // 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
+ }
+
+ public sealed class Reachability
+ {
+ FlowReturns returns, breaks, throws, barrier;
+
+ public FlowReturns Returns {
+ get { return returns; }
+ }
+ public FlowReturns Breaks {
+ get { return breaks; }
+ }
+ public FlowReturns Throws {
+ get { return throws; }
+ }
+ public FlowReturns Barrier {
+ get { return barrier; }
+ }
+ public Reachability (FlowReturns returns, FlowReturns breaks,
+ FlowReturns throws, FlowReturns barrier)
+ {
+ this.returns = returns;
+ this.breaks = breaks;
+ this.throws = throws;
+ this.barrier = barrier;
+ }
+
+ public Reachability Clone ()
+ {
+ return new Reachability (returns, breaks, throws, barrier);
+ }
+
+ // <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 (a == FlowReturns.Undefined)
+ return b;
+
+ 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)
+ return FlowReturns.Always;
+ else
+ return FlowReturns.Sometimes;
+
+ default:
+ throw new ArgumentException ();
+ }
+ }
+
+ public static FlowReturns OrFlowReturns (FlowReturns a, FlowReturns b)
+ {
+ if (a == FlowReturns.Undefined)
+ return b;
+
+ switch (a) {
+ case FlowReturns.Never:
+ return b;
+
+ case FlowReturns.Sometimes:
+ if (b == FlowReturns.Always)
+ return FlowReturns.Always;
+ else
+ return FlowReturns.Sometimes;
+
+ case FlowReturns.Always:
+ return FlowReturns.Always;
+
+ default:
+ throw new ArgumentException ();
+ }
+ }
+
+ public static void And (ref Reachability a, Reachability b, bool do_break)
+ {
+ if (a == null) {
+ a = b.Clone ();
+ return;
+ }
+
+ //
+ // `break' does not "break" in a Switch or a LoopBlock
+ //
+ bool a_breaks = do_break && a.AlwaysBreaks;
+ bool b_breaks = do_break && b.AlwaysBreaks;
+
+ bool a_has_barrier, b_has_barrier;
+ if (do_break) {
+ //
+ // This is the normal case: the code following a barrier
+ // cannot be reached.
+ //
+ a_has_barrier = a.AlwaysHasBarrier;
+ b_has_barrier = b.AlwaysHasBarrier;
+ } else {
+ //
+ // Special case for Switch and LoopBlocks: we can reach the
+ // code after the barrier via the `break'.
+ //
+ a_has_barrier = !a.AlwaysBreaks && a.AlwaysHasBarrier;
+ b_has_barrier = !b.AlwaysBreaks && b.AlwaysHasBarrier;
+ }
+
+ bool a_unreachable = a_breaks || a.AlwaysThrows || a_has_barrier;
+ bool b_unreachable = b_breaks || b.AlwaysThrows || b_has_barrier;
+
+ //
+ // Do all code paths always return ?
+ //
+ if (a.AlwaysReturns) {
+ if (b.AlwaysReturns || b_unreachable)
+ a.returns = FlowReturns.Always;
+ else
+ a.returns = FlowReturns.Sometimes;
+ } else if (b.AlwaysReturns) {
+ if (a.AlwaysReturns || a_unreachable)
+ a.returns = FlowReturns.Always;
+ else
+ a.returns = FlowReturns.Sometimes;
+ } else if (!a.MayReturn) {
+ if (b.MayReturn)
+ a.returns = FlowReturns.Sometimes;
+ else
+ a.returns = FlowReturns.Never;
+ } else if (!b.MayReturn) {
+ if (a.MayReturn)
+ a.returns = FlowReturns.Sometimes;
+ else
+ a.returns = FlowReturns.Never;
+ }
+
+ a.breaks = AndFlowReturns (a.breaks, b.breaks);
+ a.throws = AndFlowReturns (a.throws, b.throws);
+ a.barrier = AndFlowReturns (a.barrier, b.barrier);
+
+ if (a_unreachable && b_unreachable)
+ a.barrier = FlowReturns.Always;
+ else if (a_unreachable || b_unreachable)
+ a.barrier = FlowReturns.Sometimes;
+ else
+ a.barrier = FlowReturns.Never;
+ }
+
+ public void Or (Reachability b)
+ {
+ returns = OrFlowReturns (returns, b.returns);
+ breaks = OrFlowReturns (breaks, b.breaks);
+ throws = OrFlowReturns (throws, b.throws);
+ barrier = OrFlowReturns (barrier, b.barrier);
+ }
+
+ public static Reachability Never ()
+ {
+ return new Reachability (
+ FlowReturns.Never, FlowReturns.Never,
+ FlowReturns.Never, FlowReturns.Never);
+ }
+
+ public FlowReturns Reachable {
+ get {
+ if ((returns == FlowReturns.Always) ||
+ (breaks == FlowReturns.Always) ||
+ (throws == FlowReturns.Always) ||
+ (barrier == FlowReturns.Always))
+ return FlowReturns.Never;
+ else if ((returns == FlowReturns.Never) &&
+ (breaks == FlowReturns.Never) &&
+ (throws == FlowReturns.Never) &&
+ (barrier == FlowReturns.Never))
+ return FlowReturns.Always;
+ else
+ return FlowReturns.Sometimes;
+ }
+ }
+
+ public bool AlwaysBreaks {
+ get { return breaks == FlowReturns.Always; }
+ }
+
+ public bool MayBreak {
+ get { return breaks != FlowReturns.Never; }
+ }
+
+ public bool AlwaysReturns {
+ get { return returns == FlowReturns.Always; }
+ }
+
+ public bool MayReturn {
+ get { return returns != FlowReturns.Never; }
+ }
+
+ public bool AlwaysThrows {
+ get { return throws == FlowReturns.Always; }
+ }
+
+ public bool MayThrow {
+ get { return throws != FlowReturns.Never; }
+ }
+
+ public bool AlwaysHasBarrier {
+ get { return barrier == FlowReturns.Always; }
+ }
+
+ public bool MayHaveBarrier {
+ get { return barrier != FlowReturns.Never; }
+ }
+
+ public bool IsUnreachable {
+ get { return Reachable == FlowReturns.Never; }
+ }
+
+ public void SetReturns ()
+ {
+ returns = FlowReturns.Always;
+ }
+
+ public void SetReturnsSometimes ()
+ {
+ returns = FlowReturns.Sometimes;
+ }
+
+ public void SetBreaks ()
+ {
+ breaks = FlowReturns.Always;
+ }
+
+ public void ResetBreaks ()
+ {
+ breaks = FlowReturns.Never;
+ }
+
+ public void SetThrows ()
+ {
+ throws = FlowReturns.Always;
+ }
+
+ public void SetThrowsSometimes ()
+ {
+ throws = FlowReturns.Sometimes;
+ }
+
+ public void SetBarrier ()
+ {
+ barrier = FlowReturns.Always;
+ }
+
+ public void ResetBarrier ()
+ {
+ barrier = FlowReturns.Never;
+ }
+
+ static string ShortName (FlowReturns returns)
+ {
+ switch (returns) {
+ case FlowReturns.Never:
+ return "N";
+ case FlowReturns.Sometimes:
+ return "S";
+ default:
+ return "A";
+ }
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[{0}:{1}:{2}:{3}:{4}]",
+ ShortName (returns), ShortName (breaks),
+ ShortName (throws), ShortName (barrier),
+ ShortName (Reachable));
+ }
+ }
+
+ public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc)
+ {
+ switch (type) {
+ case BranchingType.Exception:
+ throw new InvalidOperationException ();
+
+ case BranchingType.Switch:
+ return new FlowBranchingBlock (parent, type, SiblingType.SwitchSection, block, loc);
+
+ case BranchingType.SwitchSection:
+ return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
+
+ case BranchingType.Block:
+ return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
+
+ case BranchingType.Loop:
+ return new FlowBranchingLoop (parent, block, loc);
+
+ default:
+ return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc);
+ }
+ }
+
+ // <summary>
+ // The type of this flow branching.
+ // </summary>
+ public readonly BranchingType 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>
+ // If this is an infinite loop.
+ // </summary>
+ public bool Infinite;
+
+ //
+ // Private
+ //
+ VariableMap param_map, local_map;
+
+ static int next_id = 0;
+ int id;
+
+ // <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>
+ // The type of this branching.
+ // </summary>
+ public readonly SiblingType Type;
+
+ // <summary>
+ // Start location of this branching.
+ // </summary>
+ public readonly Location Location;
+
+ // <summary>
+ // This is only valid for SwitchSection, Try, Catch and Finally.
+ // </summary>
+ public readonly Block Block;
+
+ // <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;
+
+ // <summary>
+ // This is used to construct a list of UsageVector's.
+ // </summary>
+ public UsageVector Next;
+
+ //
+ // Private.
+ //
+ MyBitVector locals, parameters;
+ Reachability reachability;
+
+ static int next_id = 0;
+ int id;
+
+ //
+ // Normally, you should not use any of these constructors.
+ //
+ public UsageVector (SiblingType type, UsageVector parent,
+ Block block, Location loc,
+ int num_params, int num_locals)
+ {
+ this.Type = type;
+ this.Block = block;
+ this.Location = loc;
+ this.InheritsFrom = parent;
+ this.CountParameters = num_params;
+ this.CountLocals = num_locals;
+
+ if (parent != null) {
+ if (num_locals > 0)
+ locals = new MyBitVector (parent.locals, CountLocals);
+
+ if (num_params > 0)
+ parameters = new MyBitVector (parent.parameters, num_params);
+
+ reachability = parent.Reachability.Clone ();
+ } else {
+ if (num_locals > 0)
+ locals = new MyBitVector (null, CountLocals);
+
+ if (num_params > 0)
+ parameters = new MyBitVector (null, num_params);
+
+ reachability = Reachability.Never ();
+ }
+
+ id = ++next_id;
+ }
+
+ public UsageVector (SiblingType type, UsageVector parent,
+ Block block, Location loc)
+ : this (type, parent, block, loc,
+ parent.CountParameters, parent.CountLocals)
+ { }
+
+ public UsageVector (MyBitVector parameters, MyBitVector locals,
+ Reachability reachability, Block block,
+ Location loc)
+ {
+ this.Type = SiblingType.Block;
+ this.Location = loc;
+ this.Block = block;
+
+ this.reachability = reachability;
+ this.parameters = parameters;
+ this.locals = locals;
+
+ id = ++next_id;
+ }
+
+ // <summary>
+ // This does a deep copy of the usage vector.
+ // </summary>
+ public UsageVector Clone ()
+ {
+ UsageVector retval = new UsageVector (
+ Type, null, Block, Location,
+ CountParameters, CountLocals);
+
+ if (retval.locals != null)
+ retval.locals = locals.Clone ();
+
+ if (parameters != null)
+ retval.parameters = parameters.Clone ();
+
+ retval.reachability = reachability.Clone ();
+
+ return retval;
+ }
+
+ public bool IsAssigned (VariableInfo var)
+ {
+ if (!var.IsParameter && Reachability.IsUnreachable)
+ return true;
+
+ return var.IsAssigned (var.IsParameter ? parameters : locals);
+ }
+
+ public void SetAssigned (VariableInfo var)
+ {
+ if (!var.IsParameter && Reachability.IsUnreachable)
+ return;
+
+ IsDirty = true;
+ var.SetAssigned (var.IsParameter ? parameters : locals);
+ }
+
+ public bool IsFieldAssigned (VariableInfo var, string name)
+ {
+ if (!var.IsParameter && Reachability.IsUnreachable)
+ return true;
+
+ return var.IsFieldAssigned (var.IsParameter ? parameters : locals, name);
+ }
+
+ public void SetFieldAssigned (VariableInfo var, string name)
+ {
+ if (!var.IsParameter && Reachability.IsUnreachable)
+ return;
+
+ IsDirty = true;
+ var.SetFieldAssigned (var.IsParameter ? parameters : locals, name);
+ }
+
+ public Reachability Reachability {
+ get {
+ return reachability;
+ }
+ }
+
+ public void Return ()
+ {
+ if (!reachability.IsUnreachable) {
+ IsDirty = true;
+ reachability.SetReturns ();
+ }
+ }
+
+ public void Break ()
+ {
+ if (!reachability.IsUnreachable) {
+ IsDirty = true;
+ reachability.SetBreaks ();
+ }
+ }
+
+ public void Throw ()
+ {
+ if (!reachability.IsUnreachable) {
+ IsDirty = true;
+ reachability.SetThrows ();
+ }
+ }
+
+ public void Goto ()
+ {
+ if (!reachability.IsUnreachable) {
+ IsDirty = true;
+ reachability.SetBarrier ();
+ }
+ }
+
+ // <summary>
+ // Merges a child branching.
+ // </summary>
+ public UsageVector MergeChild (FlowBranching branching)
+ {
+ UsageVector result = branching.Merge ();
+
+ Report.Debug (2, " MERGING CHILD", this, branching, IsDirty,
+ result.ParameterVector, result.LocalVector,
+ result.Reachability, reachability, Type);
+
+ Reachability new_r = result.Reachability;
+
+ if (branching.Type == BranchingType.Loop) {
+ bool may_leave_loop = new_r.MayBreak;
+ new_r.ResetBreaks ();
+
+ if (branching.Infinite && !may_leave_loop) {
+ if (new_r.Returns == FlowReturns.Sometimes) {
+ // 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).
+ new_r.SetReturns ();
+ }
+
+ new_r.SetBarrier ();
+ } else {
+ if (new_r.Returns == FlowReturns.Always) {
+ // We're either finite or we may leave the loop.
+ new_r.SetReturnsSometimes ();
+ }
+ if (new_r.Throws == FlowReturns.Always) {
+ // We're either finite or we may leave the loop.
+ new_r.SetThrowsSometimes ();
+ }
+ }
+ } else if (branching.Type == BranchingType.Switch) {
+ if (new_r.MayBreak || new_r.MayReturn)
+ new_r.ResetBarrier ();
+
+ new_r.ResetBreaks ();
+ }
+
+ //
+ // 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 ((Type == SiblingType.SwitchSection) && !new_r.IsUnreachable) {
+ Report.Error (163, Location,
+ "Control cannot fall through from one " +
+ "case label to another");
+ return result;
+ }
+
+ if (locals != null && result.LocalVector != null)
+ locals.Or (result.LocalVector);
+
+ if (result.ParameterVector != null)
+ parameters.Or (result.ParameterVector);
+
+ reachability.Or (new_r);
+
+ Report.Debug (2, " MERGING CHILD DONE", this, result,
+ new_r, reachability);
+
+ IsDirty = true;
+
+ return result;
+ }
+
+ protected void MergeFinally (FlowBranching branching, UsageVector f_origins,
+ MyBitVector f_params)
+ {
+ for (UsageVector vector = f_origins; vector != null; vector = vector.Next) {
+ MyBitVector temp_params = f_params.Clone ();
+ temp_params.Or (vector.Parameters);
+ }
+ }
+
+ public void MergeFinally (FlowBranching branching, UsageVector f_vector,
+ UsageVector f_origins)
+ {
+ if (parameters != null) {
+ if (f_vector != null) {
+ MergeFinally (branching, f_origins, f_vector.Parameters);
+ MyBitVector.Or (ref parameters, f_vector.ParameterVector);
+ } else
+ MergeFinally (branching, f_origins, parameters);
+ }
+
+ if (f_vector != null && f_vector.LocalVector != null)
+ MyBitVector.Or (ref locals, f_vector.LocalVector);
+ }
+
+ // <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 (UsageVector o_vectors)
+ {
+ Report.Debug (1, " MERGING JUMP ORIGINS", this);
+
+ reachability = Reachability.Never ();
+
+ if (o_vectors == null) {
+ reachability.SetBarrier ();
+ return;
+ }
+
+ bool first = true;
+
+ for (UsageVector vector = o_vectors; vector != null;
+ vector = vector.Next) {
+ Report.Debug (1, " MERGING JUMP ORIGIN", vector);
+
+ if (first) {
+ if (locals != null && vector.Locals != null)
+ locals.Or (vector.locals);
+
+ if (parameters != null)
+ parameters.Or (vector.parameters);
+ first = false;
+ } else {
+ if (locals != null && vector.Locals != null)
+ locals.And (vector.locals);
+ if (parameters != null)
+ parameters.And (vector.parameters);
+ }
+
+ Reachability.And (ref reachability, vector.Reachability, true);
+ }
+
+ Report.Debug (1, " MERGING JUMP ORIGINS 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 (UsageVector f_origins)
+ {
+ Report.Debug (1, " MERGING FINALLY ORIGIN", this);
+
+ reachability = Reachability.Never ();
+
+ for (UsageVector vector = f_origins; vector != null; vector = vector.Next) {
+ Report.Debug (1, " MERGING FINALLY ORIGIN", vector);
+
+ if (parameters != null)
+ parameters.And (vector.parameters);
+
+ Reachability.And (ref reachability, vector.Reachability, true);
+ }
+
+ Report.Debug (1, " MERGING FINALLY ORIGIN DONE", this);
+ }
+
+ public void MergeBreakOrigins (UsageVector o_vectors)
+ {
+ Report.Debug (1, " MERGING BREAK ORIGINS", this);
+
+ if (o_vectors == null)
+ return;
+
+ bool first = true;
+
+ for (UsageVector vector = o_vectors; vector != null;
+ vector = vector.Next) {
+ Report.Debug (1, " MERGING BREAK ORIGIN", vector);
+
+ if (first) {
+ if (locals != null && vector.Locals != null)
+ locals.Or (vector.locals);
+
+ if (parameters != null)
+ parameters.Or (vector.parameters);
+ first = false;
+ } else {
+ if (locals != null && vector.Locals != null)
+ locals.And (vector.locals);
+ if (parameters != null)
+ parameters.And (vector.parameters);
+ }
+ }
+
+ Report.Debug (1, " MERGING BREAK ORIGINS 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)
+ {
+ IsDirty = true;
+ 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)
+ {
+ IsDirty = true;
+ locals.And (new_vector.locals);
+ }
+
+ public bool HasParameters {
+ get {
+ return parameters != null;
+ }
+ }
+
+ public bool HasLocals {
+ get {
+ return locals != null;
+ }
+ }
+
+ // <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 {
+ if (locals != null)
+ return locals.Clone ();
+ else
+ return null;
+ }
+ }
+
+ public MyBitVector ParameterVector {
+ get {
+ return parameters;
+ }
+ }
+
+ public MyBitVector LocalVector {
+ get {
+ return locals;
+ }
+ }
+
+ //
+ // Debugging stuff.
+ //
+
+ public override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+
+ sb.Append ("Vector (");
+ sb.Append (Type);
+ sb.Append (",");
+ sb.Append (id);
+ sb.Append (",");
+ sb.Append (IsDirty);
+ sb.Append (",");
+ sb.Append (reachability);
+ if (parameters != null) {
+ sb.Append (" - ");
+ sb.Append (parameters);
+ }
+ sb.Append (" - ");
+ sb.Append (locals);
+ sb.Append (")");
+
+ return sb.ToString ();
+ }
+ }
+
+ // <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>
+ protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype,
+ Block block, Location loc)
+ {
+ Parent = parent;
+ Block = block;
+ Location = loc;
+ Type = type;
+ id = ++next_id;
+
+ UsageVector vector;
+ if (Block != null) {
+ param_map = Block.ParameterMap;
+ local_map = Block.LocalMap;
+
+ UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
+ vector = new UsageVector (
+ stype, parent_vector, Block, loc,
+ param_map.Length, local_map.Length);
+ } else {
+ param_map = Parent.param_map;
+ local_map = Parent.local_map;
+ vector = new UsageVector (
+ stype, Parent.CurrentUsageVector, null, loc);
+ }
+
+ AddSibling (vector);
+ }
+
+ public abstract UsageVector CurrentUsageVector {
+ get;
+ }
+
+ // <summary>
+ // Creates a sibling of the current usage vector.
+ // </summary>
+ public virtual void CreateSibling (Block block, SiblingType type)
+ {
+ UsageVector vector = new UsageVector (
+ type, Parent.CurrentUsageVector, block, Location);
+ AddSibling (vector);
+
+ Report.Debug (1, " CREATED SIBLING", CurrentUsageVector);
+ }
+
+ public void CreateSibling ()
+ {
+ CreateSibling (null, SiblingType.Conditional);
+ }
+
+ protected abstract void AddSibling (UsageVector uv);
+
+ public virtual LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (Parent != null)
+ return Parent.LookupLabel (name, loc);
+
+ Report.Error (
+ 159, loc,
+ "No such label `" + name + "' in this scope");
+ return null;
+ }
+
+ public abstract void Label (UsageVector origin_vectors);
+
+ // <summary>
+ // Check whether all `out' parameters have been assigned.
+ // </summary>
+ public void CheckOutParameters (MyBitVector parameters, Location loc)
+ {
+ 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 `" +
+ var.Name + "' must be " +
+ "assigned before control leaves the current method.");
+ }
+ }
+
+ protected UsageVector Merge (UsageVector sibling_list)
+ {
+ if (sibling_list.Next == null)
+ return sibling_list;
+
+ MyBitVector locals = null;
+ MyBitVector parameters = null;
+
+ Reachability reachability = null;
+
+ Report.Debug (2, " MERGING SIBLINGS", this, Name);
+
+ for (UsageVector child = sibling_list; child != null; child = child.Next) {
+ bool do_break = (Type != BranchingType.Switch) &&
+ (Type != BranchingType.Loop);
+
+ Report.Debug (2, " MERGING SIBLING ", child,
+ child.ParameterVector, child.LocalVector,
+ reachability, child.Reachability, do_break);
+
+ Reachability.And (ref reachability, child.Reachability, do_break);
+
+ // 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.
+ //
+ bool do_break_2 = (child.Type != SiblingType.Block) &&
+ (child.Type != SiblingType.SwitchSection);
+ bool always_throws = (child.Type != SiblingType.Try) &&
+ child.Reachability.AlwaysThrows;
+ bool unreachable = always_throws ||
+ (do_break_2 && child.Reachability.AlwaysBreaks) ||
+ child.Reachability.AlwaysReturns ||
+ child.Reachability.AlwaysHasBarrier;
+
+ Report.Debug (2, " MERGING SIBLING #1", reachability,
+ Type, child.Type, child.Reachability.IsUnreachable,
+ do_break_2, always_throws, unreachable);
+
+ if (!unreachable && (child.LocalVector != null))
+ MyBitVector.And (ref locals, child.LocalVector);
+
+ // An `out' parameter must be assigned in all branches which do
+ // not always throw an exception.
+ if ((child.ParameterVector != null) && !child.Reachability.AlwaysThrows)
+ MyBitVector.And (ref parameters, child.ParameterVector);
+
+ Report.Debug (2, " MERGING SIBLING #2", parameters, locals);
+ }
+
+ if (reachability == null)
+ reachability = Reachability.Never ();
+
+ Report.Debug (2, " MERGING SIBLINGS DONE", parameters, locals,
+ reachability, Infinite);
+
+ return new UsageVector (
+ parameters, locals, reachability, null, Location);
+ }
+
+ protected abstract UsageVector Merge ();
+
+ // <summary>
+ // Merge a child branching.
+ // </summary>
+ public UsageVector MergeChild (FlowBranching child)
+ {
+ return CurrentUsageVector.MergeChild (child);
+ }
+
+ // <summary>
+ // Does the toplevel merging.
+ // </summary>
+ public Reachability MergeTopBlock ()
+ {
+ if ((Type != BranchingType.Block) || (Block == null))
+ throw new NotSupportedException ();
+
+ UsageVector vector = new UsageVector (
+ SiblingType.Conditional, null, Block, Location,
+ param_map.Length, local_map.Length);
+
+ UsageVector result = vector.MergeChild (this);
+
+ Report.Debug (4, "MERGE TOP BLOCK", Location, vector, result.Reachability);
+
+ if ((vector.Reachability.Throws != FlowReturns.Always) &&
+ (vector.Reachability.Barrier != FlowReturns.Always))
+ CheckOutParameters (vector.Parameters, Location);
+
+ return result.Reachability;
+ }
+
+ //
+ // Checks whether we're in a `try' block.
+ //
+ public virtual bool InTryOrCatch (bool is_return)
+ {
+ if ((Block != null) && Block.IsDestructor)
+ return true;
+ else if (!is_return &&
+ ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)))
+ return false;
+ else if (Parent != null)
+ return Parent.InTryOrCatch (is_return);
+ else
+ return false;
+ }
+
+ //
+ // Checks whether we're in a `catch' block.
+ //
+ public virtual bool InCatch ()
+ {
+ if (Parent != null)
+ return Parent.InCatch ();
+ else
+ return false;
+ }
+
+ //
+ // Checks whether we're in a `finally' block.
+ //
+ public virtual bool InFinally (bool is_return)
+ {
+ if (!is_return &&
+ ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)))
+ return false;
+ else if (Parent != null)
+ return Parent.InFinally (is_return);
+ else
+ return false;
+ }
+
+ public virtual bool InLoop ()
+ {
+ if (Type == BranchingType.Loop)
+ return true;
+ else if (Parent != null)
+ return Parent.InLoop ();
+ else
+ return false;
+ }
+
+ public virtual bool InSwitch ()
+ {
+ if (Type == BranchingType.Switch)
+ return true;
+ else if (Parent != null)
+ return Parent.InSwitch ();
+ else
+ return false;
+ }
+
+ public virtual bool BreakCrossesTryCatchBoundary ()
+ {
+ if ((Type == BranchingType.Loop) || (Type == BranchingType.Switch))
+ return false;
+ else if (Parent != null)
+ return Parent.BreakCrossesTryCatchBoundary ();
+ else
+ return false;
+ }
+
+ public virtual void AddFinallyVector (UsageVector vector)
+ {
+ if (Parent != null)
+ Parent.AddFinallyVector (vector);
+ else if ((Block == null) || !Block.IsDestructor)
+ throw new NotSupportedException ();
+ }
+
+ public virtual void AddBreakVector (UsageVector vector)
+ {
+ if (Parent != null)
+ Parent.AddBreakVector (vector);
+ else if ((Block == null) || !Block.IsDestructor)
+ throw new NotSupportedException ();
+ }
+
+ public virtual void StealFinallyClauses (ref ArrayList list)
+ {
+ if (Parent != null)
+ Parent.StealFinallyClauses (ref list);
+ }
+
+ 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 override string ToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (GetType ());
+ sb.Append (" (");
+
+ 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 ();
+ }
+
+ public string Name {
+ get {
+ return String.Format ("{0} ({1}:{2}:{3})",
+ GetType (), id, Type, Location);
+ }
+ }
+ }
+
+ public class FlowBranchingBlock : FlowBranching
+ {
+ UsageVector sibling_list = null;
+
+ public FlowBranchingBlock (FlowBranching parent, BranchingType type,
+ SiblingType stype, Block block, Location loc)
+ : base (parent, type, stype, block, loc)
+ { }
+
+ public override UsageVector CurrentUsageVector {
+ get { return sibling_list; }
+ }
+
+ protected override void AddSibling (UsageVector sibling)
+ {
+ sibling.Next = sibling_list;
+ sibling_list = sibling;
+ }
+
+ public override LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (Block == null)
+ return base.LookupLabel (name, loc);
+
+ LabeledStatement s = Block.LookupLabel (name);
+ if (s != null)
+ return s;
+
+ return base.LookupLabel (name, loc);
+ }
+
+ public override void Label (UsageVector origin_vectors)
+ {
+ if (!CurrentUsageVector.Reachability.IsUnreachable) {
+ UsageVector vector = CurrentUsageVector.Clone ();
+ vector.Next = origin_vectors;
+ origin_vectors = vector;
+ }
+
+ CurrentUsageVector.MergeJumpOrigins (origin_vectors);
+ }
+
+ protected override UsageVector Merge ()
+ {
+ return Merge (sibling_list);
+ }
+ }
+
+ public class FlowBranchingLoop : FlowBranchingBlock
+ {
+ UsageVector break_origins;
+
+ public FlowBranchingLoop (FlowBranching parent, Block block, Location loc)
+ : base (parent, BranchingType.Loop, SiblingType.Conditional, block, loc)
+ { }
+
+ public override void AddBreakVector (UsageVector vector)
+ {
+ vector = vector.Clone ();
+ vector.Next = break_origins;
+ break_origins = vector;
+ }
+
+ protected override UsageVector Merge ()
+ {
+ UsageVector vector = base.Merge ();
+
+ vector.MergeBreakOrigins (break_origins);
+
+ return vector;
+ }
+ }
+
+ public class FlowBranchingException : FlowBranching
+ {
+ ExceptionStatement stmt;
+ UsageVector current_vector;
+ UsageVector catch_vectors;
+ UsageVector finally_vector;
+ UsageVector finally_origins;
+ bool emit_finally;
+ bool in_try;
+
+ public FlowBranchingException (FlowBranching parent,
+ ExceptionStatement stmt)
+ : base (parent, BranchingType.Exception, SiblingType.Try,
+ null, stmt.loc)
+ {
+ this.stmt = stmt;
+ this.emit_finally = true;
+ }
+
+ protected override void AddSibling (UsageVector sibling)
+ {
+ if (sibling.Type == SiblingType.Try) {
+ sibling.Next = catch_vectors;
+ catch_vectors = sibling;
+ in_try = true;
+ } else if (sibling.Type == SiblingType.Catch) {
+ sibling.Next = catch_vectors;
+ catch_vectors = sibling;
+ in_try = false;
+ } else if (sibling.Type == SiblingType.Finally) {
+ sibling.MergeFinallyOrigins (finally_origins);
+ finally_vector = sibling;
+ in_try = false;
+ } else
+ throw new InvalidOperationException ();
+
+ current_vector = sibling;
+ }
+
+ public override UsageVector CurrentUsageVector {
+ get { return current_vector; }
+ }
+
+ public override bool InTryOrCatch (bool is_return)
+ {
+ return finally_vector == null;
+ }
+
+ public override bool InCatch ()
+ {
+ return !in_try && (finally_vector == null);
+ }
+
+ public override bool InFinally (bool is_return)
+ {
+ return finally_vector != null;
+ }
+
+ public override bool BreakCrossesTryCatchBoundary ()
+ {
+ return true;
+ }
+
+ public override void AddFinallyVector (UsageVector vector)
+ {
+ vector = vector.Clone ();
+ vector.Next = finally_origins;
+ finally_origins = vector;
+ }
+
+ public override void StealFinallyClauses (ref ArrayList list)
+ {
+ if (list == null)
+ list = new ArrayList ();
+ list.Add (stmt);
+ emit_finally = false;
+ base.StealFinallyClauses (ref list);
+ }
+
+ public bool EmitFinally {
+ get { return emit_finally; }
+ }
+
+ public override LabeledStatement LookupLabel (string name, Location loc)
+ {
+ if (current_vector.Block == null)
+ return base.LookupLabel (name, loc);
+
+ LabeledStatement s = current_vector.Block.LookupLabel (name);
+ if (s != null)
+ return s;
+
+ if (finally_vector != null) {
+ Report.Error (
+ 157, loc, "Control can not leave the body " +
+ "of the finally block");
+ return null;
+ }
+
+ return base.LookupLabel (name, loc);
+ }
+
+ public override void Label (UsageVector origin_vectors)
+ {
+ CurrentUsageVector.MergeJumpOrigins (origin_vectors);
+ }
+
+ protected override UsageVector Merge ()
+ {
+ UsageVector vector = Merge (catch_vectors);
+
+ vector.MergeFinally (this, finally_vector, finally_origins);
+
+ return vector;
+ }
+ }
+
+ // <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 if (type is GenericTypeParameterBuilder) {
+ CountPublic = CountNonPublic = Count = 0;
+
+ Fields = new FieldInfo [0];
+ } 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;
+
+ VariableInfo[] map;
+
+ public VariableMap (InternalParameters ip)
+ {
+ Count = ip != null ? ip.Count : 0;
+
+ // Dont bother allocating anything!
+ if (Count == 0)
+ return;
+
+ Length = 0;
+
+ for (int i = 0; i < Count; i++) {
+ Parameter.Modifier mod = ip.ParameterModifier (i);
+
+ if ((mod & Parameter.Modifier.OUT) == 0)
+ continue;
+
+ // Dont allocate till we find an out var.
+ if (map == null)
+ map = new VariableInfo [Count];
+
+ map [i] = new VariableInfo (ip.ParameterName (i),
+ TypeManager.GetElementType (ip.ParameterType (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 && parent.map != null) {
+ offset = parent.Length;
+ start = parent.Count;
+ }
+
+ Count = locals.Length + start;
+
+ if (Count == 0)
+ return;
+
+ map = new VariableInfo [Count];
+ Length = offset;
+
+ if (parent != null && parent.map != null) {
+ parent.map.CopyTo (map, 0);
+ }
+
+ for (int i = start; i < Count; i++) {
+ LocalInfo li = locals [i-start];
+
+ if (li.VariableType == null)
+ continue;
+
+ 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 {
+ if (map == null)
+ return null;
+
+ return map [index];
+ }
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("VariableMap ({0}:{1})", Count, Length);
+ }
+ }
+
+ // <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;
+ }
+
+ public static void And (ref MyBitVector target, MyBitVector vector)
+ {
+ if (target != null)
+ target.And (vector);
+ else
+ target = vector.Clone ();
+ }
+
+ public static void Or (ref MyBitVector target, MyBitVector vector)
+ {
+ if (target != null)
+ target.Or (vector);
+ else
+ target = vector.Clone ();
+ }
+
+ // <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 < System.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 ("{");
+
+ BitArray vector = Vector;
+ if (!IsDirty)
+ sb.Append ("=");
+ for (int i = 0; i < vector.Count; i++) {
+ sb.Append (vector [i] ? "1" : "0");
+ }
+
+ sb.Append ("}");
+ return sb.ToString ();
+ }
+ }
+}
--- /dev/null
+// 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)
+ {
+ }
+
+ }
+}
--- /dev/null
+// 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 == EmptyStatement.Value))
+ GenerateStatement (s.InitStatement, true, true, true);
+ output ("; ");
+ output (GetExpression (s.Test, 0));
+ output ("; ");
+ if (! (s.Increment == EmptyStatement.Value))
+ 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 == EmptyStatement.Value)
+ 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;
+ }
+ }
+}
+
+
--- /dev/null
+//
+// generic.cs: Generics support
+//
+// Authors: Martin Baulig (martin@ximian.com)
+// Miguel de Icaza (miguel@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// (C) 2004 Novell, Inc
+//
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Globalization;
+using System.Collections;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Mono.CSharp {
+
+ public abstract class GenericConstraints {
+ public abstract GenericParameterAttributes Attributes {
+ get;
+ }
+
+ public bool HasConstructorConstraint {
+ get { return (Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0; }
+ }
+
+ public bool HasReferenceTypeConstraint {
+ get { return (Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0; }
+ }
+
+ public bool HasValueTypeConstraint {
+ get { return (Attributes & GenericParameterAttributes.ValueTypeConstraint) != 0; }
+ }
+
+ public virtual bool HasClassConstraint {
+ get { return ClassConstraint != null; }
+ }
+
+ public abstract Type ClassConstraint {
+ get;
+ }
+
+ public abstract Type[] InterfaceConstraints {
+ get;
+ }
+
+ public abstract Type EffectiveBaseClass {
+ get;
+ }
+
+ // <summary>
+ // Returns whether the type parameter is "known to be a reference type".
+ // </summary>
+ public virtual bool IsReferenceType {
+ get {
+ if (HasReferenceTypeConstraint)
+ return true;
+ if (HasValueTypeConstraint)
+ return false;
+
+ if (ClassConstraint != null) {
+ if (ClassConstraint.IsValueType)
+ return false;
+
+ if (ClassConstraint != TypeManager.object_type)
+ return true;
+ }
+
+ foreach (Type t in InterfaceConstraints) {
+ if (!t.IsGenericParameter)
+ continue;
+
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
+ if ((gc != null) && gc.IsReferenceType)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ // <summary>
+ // Returns whether the type parameter is "known to be a value type".
+ // </summary>
+ public virtual bool IsValueType {
+ get {
+ if (HasValueTypeConstraint)
+ return true;
+ if (HasReferenceTypeConstraint)
+ return false;
+
+ if (ClassConstraint != null) {
+ if (!ClassConstraint.IsValueType)
+ return false;
+
+ if (ClassConstraint != TypeManager.value_type)
+ return true;
+ }
+
+ foreach (Type t in InterfaceConstraints) {
+ if (!t.IsGenericParameter)
+ continue;
+
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (t);
+ if ((gc != null) && gc.IsValueType)
+ return true;
+ }
+
+ return false;
+ }
+ }
+ }
+
+ public enum SpecialConstraint
+ {
+ Constructor,
+ ReferenceType,
+ ValueType
+ }
+
+ //
+ // Tracks the constraints for a type parameter
+ //
+ public class Constraints : GenericConstraints {
+ string name;
+ ArrayList constraints;
+ Location loc;
+
+ //
+ // name is the identifier, constraints is an arraylist of
+ // Expressions (with types) or `true' for the constructor constraint.
+ //
+ public Constraints (string name, ArrayList constraints,
+ Location loc)
+ {
+ this.name = name;
+ this.constraints = constraints;
+ this.loc = loc;
+ }
+
+ public string TypeParameter {
+ get {
+ return name;
+ }
+ }
+
+ GenericParameterAttributes attrs;
+ TypeExpr class_constraint;
+ ArrayList iface_constraints;
+ ArrayList type_param_constraints;
+ int num_constraints, first_constraint;
+ Type class_constraint_type;
+ Type[] iface_constraint_types;
+ Type effective_base_type;
+
+ public bool Resolve (EmitContext ec)
+ {
+ DeclSpace ds = ec.DeclSpace;
+
+ iface_constraints = new ArrayList ();
+ type_param_constraints = new ArrayList ();
+
+ foreach (object obj in constraints) {
+ if (HasConstructorConstraint) {
+ Report.Error (401, loc,
+ "The new() constraint must be last.");
+ return false;
+ }
+
+ if (obj is SpecialConstraint) {
+ SpecialConstraint sc = (SpecialConstraint) obj;
+
+ if (sc == SpecialConstraint.Constructor) {
+ if (!HasValueTypeConstraint) {
+ attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
+ continue;
+ }
+
+ Report.Error (
+ 451, loc, "The new () constraint " +
+ "cannot be used with the `struct' " +
+ "constraint.");
+ return false;
+ }
+
+ if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) {
+ Report.Error (449, loc,
+ "The `class' or `struct' " +
+ "constraint must be first");
+ return false;
+ }
+
+ if (sc == SpecialConstraint.ReferenceType)
+ attrs |= GenericParameterAttributes.ReferenceTypeConstraint;
+ else
+ attrs |= GenericParameterAttributes.ValueTypeConstraint;
+ continue;
+ }
+
+ TypeExpr expr;
+ if (obj is ConstructedType) {
+ ConstructedType cexpr = (ConstructedType) obj;
+ if (!cexpr.ResolveConstructedType (ec))
+ return false;
+ expr = cexpr;
+ } else
+ expr = ((Expression) obj).ResolveAsTypeTerminal (ec);
+
+ if (expr == null)
+ return false;
+
+ TypeParameterExpr texpr = expr as TypeParameterExpr;
+ if (texpr != null)
+ type_param_constraints.Add (expr);
+ else if (expr.IsInterface)
+ iface_constraints.Add (expr);
+ else if (class_constraint != null) {
+ Report.Error (406, loc,
+ "`{0}': the class constraint for `{1}' " +
+ "must come before any other constraints.",
+ expr.Name, name);
+ return false;
+ } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) {
+ Report.Error (450, loc, "`{0}': cannot specify both " +
+ "a constraint class and the `class' " +
+ "or `struct' constraint.", expr.Name);
+ return false;
+ } else
+ class_constraint = expr;
+
+ num_constraints++;
+ }
+
+ return true;
+ }
+
+ bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
+ {
+ seen.Add (tparam, true);
+
+ Constraints constraints = tparam.Constraints;
+ if (constraints == null)
+ return true;
+
+ if (constraints.HasValueTypeConstraint) {
+ Report.Error (456, loc, "Type parameter `{0}' has " +
+ "the `struct' constraint, so it cannot " +
+ "be used as a constraint for `{1}'",
+ tparam.Name, name);
+ return false;
+ }
+
+ if (constraints.type_param_constraints == null)
+ return true;
+
+ foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
+ if (seen.Contains (expr.TypeParameter)) {
+ Report.Error (454, loc, "Circular constraint " +
+ "dependency involving `{0}' and `{1}'",
+ tparam.Name, expr.Name);
+ return false;
+ }
+
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool ResolveTypes (EmitContext ec)
+ {
+ foreach (object obj in constraints) {
+ ConstructedType cexpr = obj as ConstructedType;
+ if (cexpr == null)
+ continue;
+
+ if (!cexpr.CheckConstraints (ec))
+ return false;
+ }
+
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ Hashtable seen = new Hashtable ();
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+ return false;
+ }
+
+ ArrayList list = new ArrayList ();
+
+ foreach (TypeExpr iface_constraint in iface_constraints) {
+ foreach (Type type in list) {
+ if (!type.Equals (iface_constraint.Type))
+ continue;
+
+ Report.Error (405, loc,
+ "Duplicate constraint `{0}' for type " +
+ "parameter `{1}'.", iface_constraint.Type,
+ name);
+ return false;
+ }
+
+ list.Add (iface_constraint.Type);
+ }
+
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ foreach (Type type in list) {
+ if (!type.Equals (expr.Type))
+ continue;
+
+ Report.Error (405, loc,
+ "Duplicate constraint `{0}' for type " +
+ "parameter `{1}'.", expr.Type, name);
+ return false;
+ }
+
+ list.Add (expr.Type);
+ }
+
+ iface_constraint_types = new Type [list.Count];
+ list.CopyTo (iface_constraint_types, 0);
+
+ if (class_constraint != null) {
+ class_constraint_type = class_constraint.Type;
+ if (class_constraint_type == null)
+ return false;
+
+ if (class_constraint_type.IsSealed) {
+ Report.Error (701, loc,
+ "`{0}' is not a valid bound. Bounds " +
+ "must be interfaces or non sealed " +
+ "classes", class_constraint_type);
+ return false;
+ }
+
+ if ((class_constraint_type == TypeManager.array_type) ||
+ (class_constraint_type == TypeManager.delegate_type) ||
+ (class_constraint_type == TypeManager.enum_type) ||
+ (class_constraint_type == TypeManager.value_type) ||
+ (class_constraint_type == TypeManager.object_type)) {
+ Report.Error (702, loc,
+ "Bound cannot be special class `{0}'",
+ class_constraint_type);
+ return false;
+ }
+ }
+
+ if (class_constraint_type != null)
+ effective_base_type = class_constraint_type;
+ else if (HasValueTypeConstraint)
+ effective_base_type = TypeManager.value_type;
+ else
+ effective_base_type = TypeManager.object_type;
+
+ return true;
+ }
+
+ public bool CheckDependencies (EmitContext ec)
+ {
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ if (!CheckDependencies (expr.TypeParameter, ec))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckDependencies (TypeParameter tparam, EmitContext ec)
+ {
+ Constraints constraints = tparam.Constraints;
+ if (constraints == null)
+ return true;
+
+ if (HasValueTypeConstraint && constraints.HasClassConstraint) {
+ Report.Error (455, loc, "Type parameter `{0}' inherits " +
+ "conflicting constraints `{1}' and `{2}'",
+ name, constraints.ClassConstraint,
+ "System.ValueType");
+ return false;
+ }
+
+ if (HasClassConstraint && constraints.HasClassConstraint) {
+ Type t1 = ClassConstraint;
+ TypeExpr e1 = class_constraint;
+ Type t2 = constraints.ClassConstraint;
+ TypeExpr e2 = constraints.class_constraint;
+
+ if (!Convert.ImplicitReferenceConversionExists (ec, e1, t2) &&
+ !Convert.ImplicitReferenceConversionExists (ec, e2, t1)) {
+ Report.Error (455, loc,
+ "Type parameter `{0}' inherits " +
+ "conflicting constraints `{1}' and `{2}'",
+ name, t1, t2);
+ return false;
+ }
+ }
+
+ if (constraints.type_param_constraints == null)
+ return true;
+
+ foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
+ if (!CheckDependencies (expr.TypeParameter, ec))
+ return false;
+ }
+
+ return true;
+ }
+
+ public void Define (GenericTypeParameterBuilder type)
+ {
+ type.SetGenericParameterAttributes (attrs);
+ }
+
+ public override GenericParameterAttributes Attributes {
+ get { return attrs; }
+ }
+
+ public override bool HasClassConstraint {
+ get { return class_constraint != null; }
+ }
+
+ public override Type ClassConstraint {
+ get { return class_constraint_type; }
+ }
+
+ public override Type[] InterfaceConstraints {
+ get { return iface_constraint_types; }
+ }
+
+ public override Type EffectiveBaseClass {
+ get { return effective_base_type; }
+ }
+
+ internal bool IsSubclassOf (Type t)
+ {
+ if ((class_constraint_type != null) &&
+ class_constraint_type.IsSubclassOf (t))
+ return true;
+
+ if (iface_constraint_types == null)
+ return false;
+
+ foreach (Type iface in iface_constraint_types) {
+ if (TypeManager.IsSubclassOf (iface, t))
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool CheckInterfaceMethod (EmitContext ec, GenericConstraints gc)
+ {
+ if (!ResolveTypes (ec))
+ return false;
+
+ if (gc.Attributes != attrs)
+ return false;
+
+ if (HasClassConstraint != gc.HasClassConstraint)
+ return false;
+ if (HasClassConstraint && !TypeManager.IsEqual (gc.ClassConstraint, ClassConstraint))
+ return false;
+
+ int gc_icount = gc.InterfaceConstraints != null ?
+ gc.InterfaceConstraints.Length : 0;
+ int icount = InterfaceConstraints != null ?
+ InterfaceConstraints.Length : 0;
+
+ if (gc_icount != icount)
+ return false;
+
+ foreach (Type iface in gc.InterfaceConstraints) {
+ bool ok = false;
+ foreach (Type check in InterfaceConstraints) {
+ if (TypeManager.IsEqual (iface, check)) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok)
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ //
+ // This type represents a generic type parameter
+ //
+ public class TypeParameter : MemberCore, IMemberContainer {
+ string name;
+ GenericConstraints gc;
+ Constraints constraints;
+ Location loc;
+ GenericTypeParameterBuilder type;
+
+ public TypeParameter (TypeContainer parent, string name,
+ Constraints constraints, Location loc)
+ : base (parent, new MemberName (name), null, loc)
+ {
+ this.name = name;
+ this.constraints = constraints;
+ this.loc = loc;
+ }
+
+ public GenericConstraints GenericConstraints {
+ get {
+ return gc != null ? gc : constraints;
+ }
+ }
+
+ public Constraints Constraints {
+ get {
+ return constraints;
+ }
+ }
+
+ public bool HasConstructorConstraint {
+ get {
+ if (constraints != null)
+ return constraints.HasConstructorConstraint;
+
+ return false;
+ }
+ }
+
+ public Type Type {
+ get {
+ return type;
+ }
+ }
+
+ public bool Resolve (DeclSpace ds)
+ {
+ if (constraints != null)
+ return constraints.Resolve (ds.EmitContext);
+
+ return true;
+ }
+
+ public void Define (GenericTypeParameterBuilder type)
+ {
+ if (this.type != null)
+ throw new InvalidOperationException ();
+
+ this.type = type;
+ TypeManager.AddTypeParameter (type, this);
+ }
+
+ public void DefineConstraints ()
+ {
+ if (constraints != null)
+ constraints.Define (type);
+ }
+
+ public bool DefineType (EmitContext ec)
+ {
+ return DefineType (ec, null, null, false);
+ }
+
+ public bool DefineType (EmitContext ec, MethodBuilder builder,
+ MethodInfo implementing, bool is_override)
+ {
+ if (implementing != null) {
+ if (is_override && (constraints != null)) {
+ Report.Error (
+ 460, loc, "Constraints for override and " +
+ "explicit interface implementation methods " +
+ "are inherited from the base method so they " +
+ "cannot be specified directly");
+ return false;
+ }
+
+ MethodBase mb = implementing;
+ if (mb.Mono_IsInflatedMethod)
+ mb = mb.GetGenericMethodDefinition ();
+
+ int pos = type.GenericParameterPosition;
+ ParameterData pd = Invocation.GetParameterData (mb);
+ GenericConstraints temp_gc = pd.GenericConstraints (pos);
+ Type mparam = mb.GetGenericArguments () [pos];
+
+ if (temp_gc != null)
+ gc = new InflatedConstraints (temp_gc, implementing.DeclaringType);
+ else if (constraints != null)
+ gc = new InflatedConstraints (constraints, implementing.DeclaringType);
+
+ bool ok = true;
+ if (constraints != null) {
+ if (temp_gc == null)
+ ok = false;
+ else if (!constraints.CheckInterfaceMethod (ec, gc))
+ ok = false;
+ } else {
+ if (!is_override && (temp_gc != null))
+ ok = false;
+ }
+
+ if (!ok) {
+ Report.SymbolRelatedToPreviousError (implementing);
+
+ Report.Error (
+ 425, loc, "The constraints for type " +
+ "parameter `{0}' of method `{1}' must match " +
+ "the constraints for type parameter `{2}' " +
+ "of interface method `{3}'. Consider using " +
+ "an explicit interface implementation instead",
+ Name, TypeManager.CSharpSignature (builder),
+ mparam, TypeManager.CSharpSignature (mb));
+ return false;
+ }
+ } else {
+ if (constraints != null) {
+ if (!constraints.ResolveTypes (ec))
+ return false;
+ }
+
+ gc = (GenericConstraints) constraints;
+ }
+
+ if (gc == null)
+ return true;
+
+ if (gc.HasClassConstraint)
+ type.SetBaseTypeConstraint (gc.ClassConstraint);
+
+ type.SetInterfaceConstraints (gc.InterfaceConstraints);
+ TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+
+ return true;
+ }
+
+ public bool CheckDependencies (EmitContext ec)
+ {
+ if (constraints != null)
+ return constraints.CheckDependencies (ec);
+
+ return true;
+ }
+
+ public override string DocCommentHeader {
+ get {
+ throw new InvalidOperationException (
+ "Unexpected attempt to get doc comment from " + this.GetType () + ".");
+ }
+ }
+
+ //
+ // MemberContainer
+ //
+
+ public override bool Define ()
+ {
+ return true;
+ }
+
+ protected override void VerifyObsoleteAttribute ()
+ { }
+
+ public override void ApplyAttributeBuilder (Attribute a,
+ CustomAttributeBuilder cb)
+ { }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return (AttributeTargets) 0;
+ }
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return new string [0];
+ }
+ }
+
+ //
+ // IMemberContainer
+ //
+
+ string IMemberContainer.Name {
+ get { return Name; }
+ }
+
+ MemberCache IMemberContainer.ParentCache {
+ get { return null; }
+ }
+
+ bool IMemberContainer.IsInterface {
+ get { return true; }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ return FindMembers (mt, bf, null, null);
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get { return null; }
+ }
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
+ {
+ if (constraints == null)
+ return MemberList.Empty;
+
+ ArrayList members = new ArrayList ();
+
+ GenericConstraints gc = (GenericConstraints) constraints;
+
+ if (gc.HasClassConstraint) {
+ MemberList list = TypeManager.FindMembers (
+ gc.ClassConstraint, mt, bf, filter, criteria);
+
+ members.AddRange (list);
+ }
+
+ foreach (Type t in gc.InterfaceConstraints) {
+ MemberList list = TypeManager.FindMembers (
+ t, mt, bf, filter, criteria);
+
+ members.AddRange (list);
+ }
+
+ return new MemberList (members);
+ }
+
+ public bool IsSubclassOf (Type t)
+ {
+ if (type.Equals (t))
+ return true;
+
+ if (constraints != null)
+ return constraints.IsSubclassOf (t);
+
+ return false;
+ }
+
+ public override string ToString ()
+ {
+ return "TypeParameter[" + name + "]";
+ }
+
+ protected class InflatedConstraints : GenericConstraints
+ {
+ GenericConstraints gc;
+ Type base_type;
+ Type class_constraint;
+ Type[] iface_constraints;
+ Type[] dargs;
+ Type declaring;
+
+ public InflatedConstraints (GenericConstraints gc, Type declaring)
+ {
+ this.gc = gc;
+ this.declaring = declaring;
+
+ dargs = TypeManager.GetTypeArguments (declaring);
+
+ ArrayList list = new ArrayList ();
+ if (gc.HasClassConstraint)
+ list.Add (inflate (gc.ClassConstraint));
+ foreach (Type iface in gc.InterfaceConstraints)
+ list.Add (inflate (iface));
+
+ bool has_class_constr = false;
+ if (list.Count > 0) {
+ Type first = (Type) list [0];
+ has_class_constr = !first.IsInterface && !first.IsGenericParameter;
+ }
+
+ if ((list.Count > 0) && has_class_constr) {
+ class_constraint = (Type) list [0];
+ iface_constraints = new Type [list.Count - 1];
+ list.CopyTo (1, iface_constraints, 0, list.Count - 1);
+ } else {
+ iface_constraints = new Type [list.Count];
+ list.CopyTo (iface_constraints, 0);
+ }
+
+ if (HasValueTypeConstraint)
+ base_type = TypeManager.value_type;
+ else if (class_constraint != null)
+ base_type = class_constraint;
+ else
+ base_type = TypeManager.object_type;
+ }
+
+ Type inflate (Type t)
+ {
+ if (t == null)
+ return null;
+ if (t.IsGenericParameter)
+ return dargs [t.GenericParameterPosition];
+ if (t.IsGenericInstance) {
+ t = t.GetGenericTypeDefinition ();
+ t = t.BindGenericParameters (dargs);
+ }
+
+ return t;
+ }
+
+ public override GenericParameterAttributes Attributes {
+ get { return gc.Attributes; }
+ }
+
+ public override Type ClassConstraint {
+ get { return class_constraint; }
+ }
+
+ public override Type EffectiveBaseClass {
+ get { return base_type; }
+ }
+
+ public override Type[] InterfaceConstraints {
+ get { return iface_constraints; }
+ }
+ }
+ }
+
+ //
+ // This type represents a generic type parameter reference.
+ //
+ // These expressions are born in a fully resolved state.
+ //
+ public class TypeParameterExpr : TypeExpr {
+ TypeParameter type_parameter;
+
+ public override string Name {
+ get {
+ return type_parameter.Name;
+ }
+ }
+
+ public TypeParameter TypeParameter {
+ get {
+ return type_parameter;
+ }
+ }
+
+ public TypeParameterExpr (TypeParameter type_parameter, Location loc)
+ {
+ this.type_parameter = type_parameter;
+ this.loc = loc;
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ type = type_parameter.Type;
+
+ return this;
+ }
+
+ public override bool IsInterface {
+ get { return false; }
+ }
+
+ public override bool CheckAccessLevel (DeclSpace ds)
+ {
+ return true;
+ }
+
+ public void Error_CannotUseAsUnmanagedType (Location loc)
+ {
+ Report.Error (-203, loc, "Can not use type parameter as unamanged type");
+ }
+ }
+
+ public class TypeArguments {
+ public readonly Location Location;
+ ArrayList args;
+ Type[] atypes;
+ int dimension;
+ bool has_type_args;
+ bool created;
+
+ public TypeArguments (Location loc)
+ {
+ args = new ArrayList ();
+ this.Location = loc;
+ }
+
+ public TypeArguments (int dimension, Location loc)
+ {
+ this.dimension = dimension;
+ this.Location = loc;
+ }
+
+ public void Add (Expression type)
+ {
+ if (created)
+ throw new InvalidOperationException ();
+
+ args.Add (type);
+ }
+
+ public void Add (TypeArguments new_args)
+ {
+ if (created)
+ throw new InvalidOperationException ();
+
+ args.AddRange (new_args.args);
+ }
+
+ public string[] GetDeclarations ()
+ {
+ string[] ret = new string [args.Count];
+ for (int i = 0; i < args.Count; i++) {
+ SimpleName sn = args [i] as SimpleName;
+ if (sn != null) {
+ ret [i] = sn.Name;
+ continue;
+ }
+
+ Report.Error (81, Location, "Type parameter declaration " +
+ "must be an identifier not a type");
+ return null;
+ }
+ return ret;
+ }
+
+ public Type[] Arguments {
+ get {
+ return atypes;
+ }
+ }
+
+ public bool HasTypeArguments {
+ get {
+ return has_type_args;
+ }
+ }
+
+ public int Count {
+ get {
+ if (dimension > 0)
+ return dimension;
+ else
+ return args.Count;
+ }
+ }
+
+ public bool IsUnbound {
+ get {
+ return dimension > 0;
+ }
+ }
+
+ public override string ToString ()
+ {
+ StringBuilder s = new StringBuilder ();
+
+ int count = Count;
+ for (int i = 0; i < count; i++){
+ //
+ // FIXME: Use TypeManager.CSharpname once we have the type
+ //
+ if (args != null)
+ s.Append (args [i].ToString ());
+ if (i+1 < count)
+ s.Append (",");
+ }
+ return s.ToString ();
+ }
+
+ public bool Resolve (EmitContext ec)
+ {
+ DeclSpace ds = ec.DeclSpace;
+ int count = args.Count;
+ bool ok = true;
+
+ atypes = new Type [count];
+
+ for (int i = 0; i < count; i++){
+ TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec);
+ if (te == null) {
+ ok = false;
+ continue;
+ }
+ if (te is TypeParameterExpr)
+ has_type_args = true;
+
+ atypes [i] = te.Type;
+ }
+ return ok;
+ }
+ }
+
+ public class ConstructedType : TypeExpr {
+ string name, full_name;
+ TypeArguments args;
+ Type[] gen_params, atypes;
+ Type gt;
+
+ public ConstructedType (string name, TypeArguments args, Location l)
+ {
+ loc = l;
+ this.name = MemberName.MakeName (name, args.Count);
+ this.args = args;
+
+ eclass = ExprClass.Type;
+ full_name = name + "<" + args.ToString () + ">";
+ }
+
+ public ConstructedType (string name, TypeParameter[] type_params, Location l)
+ : this (type_params, l)
+ {
+ loc = l;
+
+ this.name = name;
+ full_name = name + "<" + args.ToString () + ">";
+ }
+
+ protected ConstructedType (TypeArguments args, Location l)
+ {
+ loc = l;
+ this.args = args;
+
+ eclass = ExprClass.Type;
+ }
+
+ protected ConstructedType (TypeParameter[] type_params, Location l)
+ {
+ loc = l;
+
+ args = new TypeArguments (l);
+ foreach (TypeParameter type_param in type_params)
+ args.Add (new TypeParameterExpr (type_param, l));
+
+ eclass = ExprClass.Type;
+ }
+
+ public ConstructedType (Type t, TypeParameter[] type_params, Location l)
+ : this (type_params, l)
+ {
+ gt = t.GetGenericTypeDefinition ();
+
+ this.name = gt.FullName;
+ full_name = gt.FullName + "<" + args.ToString () + ">";
+ }
+
+ public ConstructedType (Type t, TypeArguments args, Location l)
+ : this (args, l)
+ {
+ gt = t.GetGenericTypeDefinition ();
+
+ this.name = gt.FullName;
+ full_name = gt.FullName + "<" + args.ToString () + ">";
+ }
+
+ public TypeArguments TypeArguments {
+ get { return args; }
+ }
+
+ protected string DeclarationName {
+ get {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (gt.FullName);
+ sb.Append ("<");
+ for (int i = 0; i < gen_params.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (gen_params [i]);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ }
+ }
+
+ protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
+ Type ctype)
+ {
+ if (TypeManager.HasGenericArguments (ctype)) {
+ Type[] types = TypeManager.GetTypeArguments (ctype);
+
+ TypeArguments new_args = new TypeArguments (loc);
+
+ for (int i = 0; i < types.Length; i++) {
+ Type t = types [i];
+
+ if (t.IsGenericParameter) {
+ int pos = t.GenericParameterPosition;
+ t = args.Arguments [pos];
+ }
+ new_args.Add (new TypeExpression (t, loc));
+ }
+
+ TypeExpr ct = new ConstructedType (ctype, new_args, loc);
+ if (ct.ResolveAsTypeTerminal (ec) == null)
+ return false;
+ ctype = ct.Type;
+ }
+
+ return Convert.ImplicitStandardConversionExists (ec, expr, ctype);
+ }
+
+ protected bool CheckConstraints (EmitContext ec, int index)
+ {
+ Type atype = atypes [index];
+ Type ptype = gen_params [index];
+
+ if (atype == ptype)
+ return true;
+
+ Expression aexpr = new EmptyExpression (atype);
+
+ GenericConstraints gc = TypeManager.GetTypeParameterConstraints (ptype);
+ if (gc == null)
+ return true;
+
+ //
+ // First, check the `class' and `struct' constraints.
+ //
+ if (gc.HasReferenceTypeConstraint && !atype.IsClass) {
+ Report.Error (452, loc, "The type `{0}' must be " +
+ "a reference type in order to use it " +
+ "as type parameter `{1}' in the " +
+ "generic type or method `{2}'.",
+ atype, ptype, DeclarationName);
+ return false;
+ } else if (gc.HasValueTypeConstraint && !atype.IsValueType) {
+ Report.Error (453, loc, "The type `{0}' must be " +
+ "a value type in order to use it " +
+ "as type parameter `{1}' in the " +
+ "generic type or method `{2}'.",
+ atype, ptype, DeclarationName);
+ return false;
+ }
+
+ //
+ // The class constraint comes next.
+ //
+ if (gc.HasClassConstraint) {
+ if (!CheckConstraint (ec, ptype, aexpr, gc.ClassConstraint)) {
+ Report.Error (309, loc, "The type `{0}' must be " +
+ "convertible to `{1}' in order to " +
+ "use it as parameter `{2}' in the " +
+ "generic type or method `{3}'",
+ atype, gc.ClassConstraint, ptype, DeclarationName);
+ return false;
+ }
+ }
+
+ //
+ // Now, check the interface constraints.
+ //
+ foreach (Type it in gc.InterfaceConstraints) {
+ Type itype;
+ if (it.IsGenericParameter)
+ itype = atypes [it.GenericParameterPosition];
+ else
+ itype = it;
+
+ if (!CheckConstraint (ec, ptype, aexpr, itype)) {
+ Report.Error (309, loc, "The type `{0}' must be " +
+ "convertible to `{1}' in order to " +
+ "use it as parameter `{2}' in the " +
+ "generic type or method `{3}'",
+ atype, itype, ptype, DeclarationName);
+ return false;
+ }
+ }
+
+ //
+ // Finally, check the constructor constraint.
+ //
+
+ if (!gc.HasConstructorConstraint)
+ return true;
+
+ if (TypeManager.IsBuiltinType (atype) || atype.IsValueType)
+ return true;
+
+ MethodGroupExpr mg = Expression.MemberLookup (
+ ec, atype, ".ctor", MemberTypes.Constructor,
+ BindingFlags.Public | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly, loc)
+ as MethodGroupExpr;
+
+ if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
+ Report.Error (310, loc, "The type `{0}' must have a public " +
+ "parameterless constructor in order to use it " +
+ "as parameter `{1}' in the generic type or " +
+ "method `{2}'", atype, ptype, DeclarationName);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ {
+ if (!ResolveConstructedType (ec))
+ return null;
+
+ return this;
+ }
+
+ public bool CheckConstraints (EmitContext ec)
+ {
+ for (int i = 0; i < gen_params.Length; i++) {
+ if (!CheckConstraints (ec, i))
+ return false;
+ }
+
+ return true;
+ }
+
+ public override TypeExpr ResolveAsTypeTerminal (EmitContext ec)
+ {
+ if (base.ResolveAsTypeTerminal (ec) == null)
+ return null;
+
+ if (!CheckConstraints (ec))
+ return null;
+
+ return this;
+ }
+
+ public bool ResolveConstructedType (EmitContext ec)
+ {
+ if (type != null)
+ return true;
+ if (gt != null)
+ return DoResolveType (ec);
+
+ //
+ // First, resolve the generic type.
+ //
+ DeclSpace ds;
+ Type nested = ec.DeclSpace.FindNestedType (loc, name, out ds);
+ if (nested != null) {
+ gt = nested.GetGenericTypeDefinition ();
+
+ TypeArguments new_args = new TypeArguments (loc);
+ if (ds.IsGeneric) {
+ foreach (TypeParameter param in ds.TypeParameters)
+ new_args.Add (new TypeParameterExpr (param, loc));
+ }
+ new_args.Add (args);
+
+ args = new_args;
+ return DoResolveType (ec);
+ }
+
+ Type t;
+ int num_args;
+
+ SimpleName sn = new SimpleName (name, loc);
+ TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
+ if (resolved == null)
+ return false;
+
+ t = resolved.Type;
+ if (t == null) {
+ Report.Error (246, loc, "Cannot find type `{0}'<...>",
+ Basename);
+ return false;
+ }
+
+ num_args = TypeManager.GetNumberOfTypeArguments (t);
+ if (num_args == 0) {
+ Report.Error (308, loc,
+ "The non-generic type `{0}' cannot " +
+ "be used with type arguments.",
+ TypeManager.CSharpName (t));
+ return false;
+ }
+
+ gt = t.GetGenericTypeDefinition ();
+ return DoResolveType (ec);
+ }
+
+ bool DoResolveType (EmitContext ec)
+ {
+ //
+ // Resolve the arguments.
+ //
+ if (args.Resolve (ec) == false)
+ return false;
+
+ gen_params = gt.GetGenericArguments ();
+ atypes = args.Arguments;
+
+ if (atypes.Length != gen_params.Length) {
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (gt),
+ gen_params.Length);
+ return false;
+ }
+
+ //
+ // Now bind the parameters.
+ //
+ type = gt.BindGenericParameters (atypes);
+ return true;
+ }
+
+ public Expression GetSimpleName (EmitContext ec)
+ {
+ return new SimpleName (Basename, args, loc);
+ }
+
+ public override bool CheckAccessLevel (DeclSpace ds)
+ {
+ return ds.CheckAccessLevel (gt);
+ }
+
+ public override bool AsAccessible (DeclSpace ds, int flags)
+ {
+ return ds.AsAccessible (gt, flags);
+ }
+
+ public override bool IsClass {
+ get { return gt.IsClass; }
+ }
+
+ public override bool IsValueType {
+ get { return gt.IsValueType; }
+ }
+
+ public override bool IsInterface {
+ get { return gt.IsInterface; }
+ }
+
+ public override bool IsSealed {
+ get { return gt.IsSealed; }
+ }
+
+ public override bool IsAttribute {
+ get { return false; }
+ }
+
+ public override bool Equals (object obj)
+ {
+ ConstructedType cobj = obj as ConstructedType;
+ if (cobj == null)
+ return false;
+
+ if ((type == null) || (cobj.type == null))
+ return false;
+
+ return type == cobj.type;
+ }
+
+ public string Basename {
+ get {
+ int pos = name.LastIndexOf ('`');
+ if (pos >= 0)
+ return name.Substring (0, pos);
+ else
+ return name;
+ }
+ }
+
+ public override string Name {
+ get {
+ return full_name;
+ }
+ }
+ }
+
+ public class GenericMethod : DeclSpace
+ {
+ public GenericMethod (NamespaceEntry ns, TypeContainer parent,
+ MemberName name, Location l)
+ : base (ns, parent, name, null, l)
+ { }
+
+ public override TypeBuilder DefineType ()
+ {
+ throw new Exception ();
+ }
+
+ public override bool Define ()
+ {
+ for (int i = 0; i < TypeParameters.Length; i++)
+ if (!TypeParameters [i].Resolve (Parent))
+ return false;
+
+ return true;
+ }
+
+ public bool Define (MethodBuilder mb, Type return_type)
+ {
+ if (!Define ())
+ return false;
+
+ GenericTypeParameterBuilder[] gen_params;
+ string[] names = MemberName.TypeArguments.GetDeclarations ();
+ gen_params = mb.DefineGenericParameters (names);
+ for (int i = 0; i < TypeParameters.Length; i++)
+ TypeParameters [i].Define (gen_params [i]);
+
+ ec = new EmitContext (
+ this, this, Location, null, return_type, ModFlags, false);
+
+ return true;
+ }
+
+ public bool DefineType (EmitContext ec, MethodBuilder mb,
+ MethodInfo implementing, bool is_override)
+ {
+ for (int i = 0; i < TypeParameters.Length; i++)
+ if (!TypeParameters [i].DefineType (
+ ec, mb, implementing, is_override))
+ return false;
+
+ return true;
+ }
+
+ public override bool DefineMembers (TypeContainer parent)
+ {
+ return true;
+ }
+
+ public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
+ {
+ throw new Exception ();
+ }
+
+ public override MemberCache MemberCache {
+ get {
+ throw new Exception ();
+ }
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ // FIXME
+ }
+
+ protected override void VerifyObsoleteAttribute()
+ {
+ // FIXME
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method | AttributeTargets.ReturnValue;
+ }
+ }
+
+ public override string DocCommentHeader {
+ get { return "M:"; }
+ }
+ }
+
+ public class DefaultValueExpression : Expression
+ {
+ Expression expr;
+ LocalTemporary temp_storage;
+
+ public DefaultValueExpression (Expression expr, Location loc)
+ {
+ this.expr = expr;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ type = texpr.Type;
+ if (type.IsGenericParameter || TypeManager.IsValueType (type))
+ temp_storage = new LocalTemporary (ec, type);
+
+ eclass = ExprClass.Variable;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (temp_storage != null) {
+ temp_storage.AddressOf (ec, AddressOp.LoadStore);
+ ec.ig.Emit (OpCodes.Initobj, type);
+ temp_storage.Emit (ec);
+ } else
+ ec.ig.Emit (OpCodes.Ldnull);
+ }
+ }
+
+ public partial class TypeManager
+ {
+ //
+ // A list of core types that the compiler requires or uses
+ //
+ static public Type new_constraint_attr_type;
+ static public Type activator_type;
+ static public Type generic_ienumerator_type;
+ static public Type generic_ienumerable_type;
+
+ // <remarks>
+ // Tracks the generic parameters.
+ // </remarks>
+ static PtrHashtable builder_to_type_param;
+
+ //
+ // These methods are called by code generated by the compiler
+ //
+ static public MethodInfo activator_create_instance;
+
+ static void InitGenerics ()
+ {
+ builder_to_type_param = new PtrHashtable ();
+ }
+
+ static void CleanUpGenerics ()
+ {
+ builder_to_type_param = null;
+ }
+
+ static void InitGenericCoreTypes ()
+ {
+ activator_type = CoreLookupType ("System.Activator");
+ new_constraint_attr_type = CoreLookupType (
+ "System.Runtime.CompilerServices.NewConstraintAttribute");
+
+ generic_ienumerator_type = CoreLookupType (
+ MemberName.MakeName ("System.Collections.Generic.IEnumerator", 1));
+ generic_ienumerable_type = CoreLookupType (
+ MemberName.MakeName ("System.Collections.Generic.IEnumerable", 1));
+ }
+
+ static void InitGenericCodeHelpers ()
+ {
+ // Activator
+ Type [] type_arg = { type_type };
+ activator_create_instance = GetMethod (
+ activator_type, "CreateInstance", type_arg);
+ }
+
+ public static void AddTypeParameter (Type t, TypeParameter tparam)
+ {
+ if (!builder_to_type_param.Contains (t))
+ builder_to_type_param.Add (t, tparam);
+ }
+
+ public static TypeContainer LookupGenericTypeContainer (Type t)
+ {
+ while (t.IsGenericInstance)
+ t = t.GetGenericTypeDefinition ();
+
+ return LookupTypeContainer (t);
+ }
+
+ public static TypeParameter LookupTypeParameter (Type t)
+ {
+ return (TypeParameter) builder_to_type_param [t];
+ }
+
+ public static bool HasConstructorConstraint (Type t)
+ {
+ GenericConstraints gc = GetTypeParameterConstraints (t);
+ if (gc == null)
+ return false;
+
+ return (gc.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
+ }
+
+ public static GenericConstraints GetTypeParameterConstraints (Type t)
+ {
+ if (!t.IsGenericParameter)
+ throw new InvalidOperationException ();
+
+ TypeParameter tparam = LookupTypeParameter (t);
+ if (tparam != null)
+ return tparam.GenericConstraints;
+
+ return new ReflectionConstraints (t);
+ }
+
+ public static bool IsGeneric (Type t)
+ {
+ DeclSpace ds = (DeclSpace) builder_to_declspace [t];
+
+ return ds.IsGeneric;
+ }
+
+ public static bool HasGenericArguments (Type t)
+ {
+ return GetNumberOfTypeArguments (t) > 0;
+ }
+
+ public static int GetNumberOfTypeArguments (Type t)
+ {
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null)
+ return tc.IsGeneric ? tc.CountTypeParameters : 0;
+ else
+ return t.HasGenericArguments ? t.GetGenericArguments ().Length : 0;
+ }
+
+ public static Type[] GetTypeArguments (Type t)
+ {
+ DeclSpace tc = LookupDeclSpace (t);
+ if (tc != null) {
+ if (!tc.IsGeneric)
+ return Type.EmptyTypes;
+
+ TypeParameter[] tparam = tc.TypeParameters;
+ Type[] ret = new Type [tparam.Length];
+ for (int i = 0; i < tparam.Length; i++) {
+ ret [i] = tparam [i].Type;
+ if (ret [i] == null)
+ throw new InternalErrorException ();
+ }
+
+ return ret;
+ } else
+ return t.GetGenericArguments ();
+ }
+
+ public static bool IsEqual (Type a, Type b)
+ {
+ if (a.Equals (b))
+ return true;
+
+ if ((a is TypeBuilder) && a.IsGenericTypeDefinition && b.IsGenericInstance) {
+ //
+ // `a' is a generic type definition's TypeBuilder and `b' is a
+ // generic instance of the same type.
+ //
+ // Example:
+ //
+ // class Stack<T>
+ // {
+ // void Test (Stack<T> stack) { }
+ // }
+ //
+ // The first argument of `Test' will be the generic instance
+ // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
+ //
+ //
+ // We hit this via Closure.Filter() for gen-82.cs.
+ //
+ if (a != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aparams = a.GetGenericArguments ();
+ Type[] bparams = b.GetGenericArguments ();
+
+ if (aparams.Length != bparams.Length)
+ return false;
+
+ for (int i = 0; i < aparams.Length; i++)
+ if (!IsEqual (aparams [i], bparams [i]))
+ return false;
+
+ return true;
+ }
+
+ if (a.IsGenericParameter && b.IsGenericParameter) {
+ if ((a.DeclaringMethod == null) || (b.DeclaringMethod == null))
+ return false;
+ return a.GenericParameterPosition == b.GenericParameterPosition;
+ }
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+ return IsEqual (a.GetElementType (), b.GetElementType ());
+ }
+
+ if (a.IsGenericInstance && b.IsGenericInstance) {
+ Type at = a.GetGenericTypeDefinition ();
+ Type bt = b.GetGenericTypeDefinition ();
+
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = a.GetGenericArguments ();
+ Type[] bargs = b.GetGenericArguments ();
+
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ for (int i = 0; i < aargs.Length; i++) {
+ if (!IsEqual (aargs [i], bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_infered, Type[] method_infered)
+ {
+ if (a.IsGenericParameter) {
+ //
+ // If a is an array of a's type, they may never
+ // become equal.
+ //
+ while (b.IsArray) {
+ b = b.GetElementType ();
+ if (a.Equals (b))
+ return false;
+ }
+
+ //
+ // If b is a generic parameter or an actual type,
+ // they may become equal:
+ //
+ // class X<T,U> : I<T>, I<U>
+ // class X<T> : I<T>, I<float>
+ //
+ if (b.IsGenericParameter || !b.IsGenericInstance) {
+ int pos = a.GenericParameterPosition;
+ Type[] args = a.DeclaringMethod != null ? method_infered : class_infered;
+ if (args [pos] == null) {
+ args [pos] = b;
+ return true;
+ }
+
+ return args [pos] == a;
+ }
+
+ //
+ // We're now comparing a type parameter with a
+ // generic instance. They may become equal unless
+ // the type parameter appears anywhere in the
+ // generic instance:
+ //
+ // class X<T,U> : I<T>, I<X<U>>
+ // -> error because you could instanciate it as
+ // X<X<int>,int>
+ //
+ // class X<T> : I<T>, I<X<T>> -> ok
+ //
+
+ Type[] bargs = GetTypeArguments (b);
+ for (int i = 0; i < bargs.Length; i++) {
+ if (a.Equals (bargs [i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ if (b.IsGenericParameter)
+ return MayBecomeEqualGenericTypes (b, a, class_infered, method_infered);
+
+ //
+ // At this point, neither a nor b are a type parameter.
+ //
+ // If one of them is a generic instance, let
+ // MayBecomeEqualGenericInstances() compare them (if the
+ // other one is not a generic instance, they can never
+ // become equal).
+ //
+
+ if (a.IsGenericInstance || b.IsGenericInstance)
+ return MayBecomeEqualGenericInstances (a, b, class_infered, method_infered);
+
+ //
+ // If both of them are arrays.
+ //
+
+ if (a.IsArray && b.IsArray) {
+ if (a.GetArrayRank () != b.GetArrayRank ())
+ return false;
+
+ a = a.GetElementType ();
+ b = b.GetElementType ();
+
+ return MayBecomeEqualGenericTypes (a, b, class_infered, method_infered);
+ }
+
+ //
+ // Ok, two ordinary types.
+ //
+
+ return a.Equals (b);
+ }
+
+ //
+ // Checks whether two generic instances may become equal for some
+ // particular instantiation (26.3.1).
+ //
+ public static bool MayBecomeEqualGenericInstances (Type a, Type b,
+ Type[] class_infered, Type[] method_infered)
+ {
+ if (!a.IsGenericInstance || !b.IsGenericInstance)
+ return false;
+ if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ())
+ return false;
+
+ Type[] aargs = GetTypeArguments (a);
+ Type[] bargs = GetTypeArguments (b);
+
+ return MayBecomeEqualGenericInstances (
+ GetTypeArguments (a), GetTypeArguments (b), class_infered, method_infered);
+ }
+
+ public static bool MayBecomeEqualGenericInstances (Type[] aargs, Type[] bargs,
+ Type[] class_infered, Type[] method_infered)
+ {
+ if (aargs.Length != bargs.Length)
+ return false;
+
+ Type[] args = new Type [aargs.Length];
+ for (int i = 0; i < aargs.Length; i++) {
+ if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_infered, method_infered))
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool IsEqualGenericInstance (Type type, Type parent)
+ {
+ int tcount = GetNumberOfTypeArguments (type);
+ int pcount = GetNumberOfTypeArguments (parent);
+
+ if (type.IsGenericInstance)
+ type = type.GetGenericTypeDefinition ();
+ if (parent.IsGenericInstance)
+ parent = parent.GetGenericTypeDefinition ();
+
+ if (tcount != pcount)
+ return false;
+
+ return type.Equals (parent);
+ }
+
+ static public bool IsGenericMethod (MethodBase mb)
+ {
+ if (mb.DeclaringType is TypeBuilder) {
+ IMethodData method = (IMethodData) builder_to_method [mb];
+ if (method == null)
+ return false;
+
+ return method.GenericMethod != null;
+ }
+
+ return mb.IsGenericMethodDefinition;
+ }
+
+ //
+ // Type inference.
+ //
+
+ static bool InferType (Type pt, Type at, Type[] infered)
+ {
+ if (pt.IsGenericParameter && (pt.DeclaringMethod != null)) {
+ int pos = pt.GenericParameterPosition;
+
+ if (infered [pos] == null) {
+ Type check = at;
+ while (check.IsArray)
+ check = check.GetElementType ();
+
+ if (pt == check)
+ return false;
+
+ infered [pos] = at;
+ return true;
+ }
+
+ if (infered [pos] != at)
+ return false;
+
+ return true;
+ }
+
+ if (!pt.ContainsGenericParameters) {
+ if (at.ContainsGenericParameters)
+ return InferType (at, pt, infered);
+ else
+ return true;
+ }
+
+ if (at.IsArray) {
+ if (!pt.IsArray ||
+ (at.GetArrayRank () != pt.GetArrayRank ()))
+ return false;
+
+ return InferType (pt.GetElementType (), at.GetElementType (), infered);
+ }
+
+ if (pt.IsArray) {
+ if (!at.IsArray ||
+ (pt.GetArrayRank () != at.GetArrayRank ()))
+ return false;
+
+ return InferType (pt.GetElementType (), at.GetElementType (), infered);
+ }
+
+ if (pt.IsByRef && at.IsByRef)
+ return InferType (pt.GetElementType (), at.GetElementType (), infered);
+ ArrayList list = new ArrayList ();
+ if (at.IsGenericInstance)
+ list.Add (at);
+ else {
+ for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
+ list.Add (bt);
+
+ list.AddRange (TypeManager.GetInterfaces (at));
+ }
+
+ bool found_one = false;
+
+ foreach (Type type in list) {
+ if (!type.IsGenericInstance)
+ continue;
+
+ Type[] infered_types = new Type [infered.Length];
+
+ if (!InferGenericInstance (pt, type, infered_types))
+ continue;
+
+ for (int i = 0; i < infered_types.Length; i++) {
+ if (infered [i] == null) {
+ infered [i] = infered_types [i];
+ continue;
+ }
+
+ if (infered [i] != infered_types [i])
+ return false;
+ }
+
+ found_one = true;
+ }
+
+ return found_one;
+ }
+
+ static bool InferGenericInstance (Type pt, Type at, Type[] infered_types)
+ {
+ Type[] at_args = at.GetGenericArguments ();
+ Type[] pt_args = pt.GetGenericArguments ();
+
+ if (at_args.Length != pt_args.Length)
+ return false;
+
+ for (int i = 0; i < at_args.Length; i++) {
+ if (!InferType (pt_args [i], at_args [i], infered_types))
+ return false;
+ }
+
+ for (int i = 0; i < infered_types.Length; i++) {
+ if (infered_types [i] == null)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool InferParamsTypeArguments (EmitContext ec, ArrayList arguments,
+ ref MethodBase method)
+ {
+ if ((arguments == null) || !TypeManager.IsGenericMethod (method))
+ return true;
+
+ int arg_count;
+
+ if (arguments == null)
+ arg_count = 0;
+ else
+ arg_count = arguments.Count;
+
+ ParameterData pd = Invocation.GetParameterData (method);
+
+ 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;
+
+ Type[] method_args = method.GetGenericArguments ();
+ Type[] infered_types = new Type [method_args.Length];
+
+ //
+ // 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];
+
+ if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+ continue;
+
+ Type pt = pd.ParameterType (i);
+ Type at = a.Type;
+
+ if (!InferType (pt, at, infered_types))
+ 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 ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+ continue;
+
+ if (!InferType (element_type, a.Type, infered_types))
+ return false;
+ }
+
+ for (int i = 0; i < infered_types.Length; i++)
+ if (infered_types [i] == null)
+ return false;
+
+ method = method.BindGenericParameters (infered_types);
+ return true;
+ }
+
+ public static bool InferTypeArguments (Type[] param_types, Type[] arg_types, Type[] infered_types)
+ {
+ if (infered_types == null)
+ return false;
+
+ for (int i = 0; i < arg_types.Length; i++) {
+ if (arg_types [i] == null)
+ continue;
+
+ if (!InferType (param_types [i], arg_types [i], infered_types))
+ return false;
+ }
+
+ for (int i = 0; i < infered_types.Length; i++)
+ if (infered_types [i] == null)
+ return false;
+
+ return true;
+ }
+
+ public static bool InferTypeArguments (EmitContext ec, ArrayList arguments,
+ ref MethodBase method)
+ {
+ if (!TypeManager.IsGenericMethod (method))
+ return true;
+
+ int arg_count;
+ if (arguments != null)
+ arg_count = arguments.Count;
+ else
+ arg_count = 0;
+
+ ParameterData pd = Invocation.GetParameterData (method);
+ if (arg_count != pd.Count)
+ return false;
+
+ Type[] method_args = method.GetGenericArguments ();
+
+ bool is_open = false;
+ for (int i = 0; i < method_args.Length; i++) {
+ if (method_args [i].IsGenericParameter) {
+ is_open = true;
+ break;
+ }
+ }
+ if (!is_open)
+ return true;
+
+ Type[] infered_types = new Type [method_args.Length];
+
+ Type[] param_types = new Type [pd.Count];
+ Type[] arg_types = new Type [pd.Count];
+
+ for (int i = 0; i < arg_count; i++) {
+ param_types [i] = pd.ParameterType (i);
+
+ Argument a = (Argument) arguments [i];
+ if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
+ continue;
+
+ arg_types [i] = a.Type;
+ }
+
+ if (!InferTypeArguments (param_types, arg_types, infered_types))
+ return false;
+
+ method = method.BindGenericParameters (infered_types);
+ return true;
+ }
+
+ public static bool InferTypeArguments (EmitContext ec, ParameterData apd,
+ ref MethodBase method)
+ {
+ if (!TypeManager.IsGenericMethod (method))
+ return true;
+
+ ParameterData pd = Invocation.GetParameterData (method);
+ if (apd.Count != pd.Count)
+ return false;
+
+ Type[] method_args = method.GetGenericArguments ();
+ Type[] infered_types = new Type [method_args.Length];
+
+ Type[] param_types = new Type [pd.Count];
+ Type[] arg_types = new Type [pd.Count];
+
+ for (int i = 0; i < apd.Count; i++) {
+ param_types [i] = pd.ParameterType (i);
+ arg_types [i] = apd.ParameterType (i);
+ }
+
+ if (!InferTypeArguments (param_types, arg_types, infered_types))
+ return false;
+
+ method = method.BindGenericParameters (infered_types);
+ return true;
+ }
+ }
+}
--- /dev/null
+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
+doc.cs
+enum.cs
+ecore.cs
+expression.cs
+flowanalysis.cs
+generic.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
+CryptoConvert.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs
+../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs
--- /dev/null
+//
+// 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;
+ ArrayList finally_blocks;
+
+ public Yield (Expression expr, Location l)
+ {
+ this.expr = expr;
+ loc = l;
+ }
+
+ public static bool CheckContext (EmitContext ec, Location loc)
+ {
+ if (ec.CurrentBranching.InFinally (true)){
+ Report.Error (1625, loc, "Cannot yield in the body of a " +
+ "finally clause");
+ return false;
+ }
+ if (ec.CurrentBranching.InCatch ()){
+ Report.Error (1631, loc, "Cannot yield in the body of a " +
+ "catch clause");
+ return false;
+ }
+ if (ec.CurrentAnonymousMethod != null){
+ Report.Error (1621, 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;
+
+ Iterator iterator = ec.CurrentIterator;
+ if (expr.Type != iterator.IteratorType){
+ expr = Convert.ImplicitConversionRequired (
+ ec, expr, iterator.IteratorType, loc);
+ if (expr == null)
+ return false;
+ }
+
+ ec.CurrentBranching.StealFinallyClauses (ref finally_blocks);
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ec.CurrentIterator.MarkYield (ec, expr, finally_blocks);
+ }
+ }
+
+ 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.Goto ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ec.CurrentIterator.EmitYieldBreak (ec.ig);
+ }
+ }
+
+ public class Iterator : Class {
+ ToplevelBlock original_block;
+ ToplevelBlock block;
+ string original_name;
+
+ Type iterator_type;
+ TypeExpr iterator_type_expr;
+ bool is_enumerable;
+ bool is_static;
+
+ Hashtable fields;
+
+ //
+ // The state as we generate the iterator
+ //
+ Label move_next_ok, move_next_error;
+ ArrayList resume_points = new ArrayList ();
+ int pc;
+
+ //
+ // Context from the original method
+ //
+ TypeContainer container;
+ TypeExpr current_type;
+ Type this_type;
+ Type return_type;
+ Type [] param_types;
+ InternalParameters parameters;
+
+ MethodInfo dispose_method;
+
+ Expression enumerator_type;
+ Expression enumerable_type;
+ Expression generic_enumerator_type;
+ Expression generic_enumerable_type;
+ TypeArguments generic_args;
+
+ protected enum State {
+ Uninitialized = -2,
+ After,
+ Running
+ }
+
+ static int proxy_count;
+
+ public void EmitYieldBreak (ILGenerator ig)
+ {
+ ig.Emit (OpCodes.Ldarg_0);
+ IntConstant.EmitInt (ig, (int) State.After);
+ ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
+ ig.Emit (OpCodes.Br, move_next_error);
+ }
+
+ public void EmitMoveNext (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ move_next_ok = ig.DefineLabel ();
+ move_next_error = ig.DefineLabel ();
+
+ LocalBuilder retval = ec.GetTemporaryLocal (TypeManager.int32_type);
+
+ ig.BeginExceptionBlock ();
+
+ Label dispatcher = ig.DefineLabel ();
+ ig.Emit (OpCodes.Br, dispatcher);
+
+ ResumePoint entry_point = new ResumePoint (null);
+ resume_points.Add (entry_point);
+ entry_point.Define (ig);
+
+ ec.EmitTopBlock (original_block, parameters, Location);
+ EmitYieldBreak (ig);
+
+ ig.MarkLabel (dispatcher);
+
+ Label [] labels = new Label [resume_points.Count];
+ for (int i = 0; i < labels.Length; i++)
+ labels [i] = ((ResumePoint) resume_points [i]).Label;
+
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
+ ig.Emit (OpCodes.Switch, labels);
+
+ Label end = ig.DefineLabel ();
+
+ ig.MarkLabel (move_next_error);
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Stloc, retval);
+ ig.Emit (OpCodes.Leave, end);
+
+ ig.MarkLabel (move_next_ok);
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Stloc, retval);
+ ig.Emit (OpCodes.Leave, end);
+
+ ig.BeginFaultBlock ();
+
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Callvirt, dispose_method);
+
+ ig.EndExceptionBlock ();
+
+ ig.MarkLabel (end);
+ ig.Emit (OpCodes.Ldloc, retval);
+ ig.Emit (OpCodes.Ret);
+ }
+
+ public void EmitDispose (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label end = ig.DefineLabel ();
+ Label dispatcher = ig.DefineLabel ();
+ ig.Emit (OpCodes.Br, dispatcher);
+
+ ec.RemapToProxy = true;
+ Label [] labels = new Label [resume_points.Count];
+ for (int i = 0; i < labels.Length; i++) {
+ ResumePoint point = (ResumePoint) resume_points [i];
+
+ if (point.FinallyBlocks == null) {
+ labels [i] = end;
+ continue;
+ }
+
+ labels [i] = ig.DefineLabel ();
+ ig.MarkLabel (labels [i]);
+
+ ig.BeginExceptionBlock ();
+ ig.BeginFinallyBlock ();
+
+ foreach (ExceptionStatement stmt in point.FinallyBlocks) {
+ if (stmt != null)
+ stmt.EmitFinally (ec);
+ }
+
+ ig.EndExceptionBlock ();
+ ig.Emit (OpCodes.Br, end);
+ }
+ ec.RemapToProxy = false;
+
+ ig.MarkLabel (dispatcher);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
+ ig.Emit (OpCodes.Switch, labels);
+
+ ig.Emit (OpCodes.Ldarg_0);
+ IntConstant.EmitInt (ig, (int) State.After);
+ ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
+
+ ig.MarkLabel (end);
+ }
+
+ protected class ResumePoint
+ {
+ public Label Label;
+ public readonly ExceptionStatement[] FinallyBlocks;
+
+ public ResumePoint (ArrayList list)
+ {
+ if (list != null) {
+ FinallyBlocks = new ExceptionStatement [list.Count];
+ list.CopyTo (FinallyBlocks, 0);
+ }
+ }
+
+ public void Define (ILGenerator ig)
+ {
+ Label = ig.DefineLabel ();
+ ig.MarkLabel (Label);
+ }
+ }
+
+ //
+ // Invoked when a local variable declaration needs to be mapped to
+ // a field in our proxy class
+ //
+ // Prefixes registered:
+ // v_ for EmitContext.MapVariable
+ // s_ for Storage
+ //
+ public FieldBuilder MapVariable (string pfx, string name, Type t)
+ {
+ string full_name = pfx + name;
+ FieldBuilder fb = (FieldBuilder) fields [full_name];
+ if (fb != null)
+ return fb;
+
+ fb = TypeBuilder.DefineField (full_name, t, FieldAttributes.Private);
+ fields.Add (full_name, fb);
+ return fb;
+ }
+
+ //
+ // Called back from Yield
+ //
+ public void MarkYield (EmitContext ec, Expression expr,
+ ArrayList finally_blocks)
+ {
+ ILGenerator ig = ec.ig;
+
+ // Store the new current
+ ig.Emit (OpCodes.Ldarg_0);
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Stfld, current_field.FieldBuilder);
+
+ // increment pc
+ pc++;
+ ig.Emit (OpCodes.Ldarg_0);
+ IntConstant.EmitInt (ig, pc);
+ ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
+
+ // Return ok
+ ig.Emit (OpCodes.Br, move_next_ok);
+
+ ResumePoint point = new ResumePoint (finally_blocks);
+ resume_points.Add (point);
+ point.Define (ig);
+ }
+
+ public void MarkFinally (EmitContext ec, ArrayList finally_blocks)
+ {
+ ILGenerator ig = ec.ig;
+
+ // increment pc
+ pc++;
+ ig.Emit (OpCodes.Ldarg_0);
+ IntConstant.EmitInt (ig, pc);
+ ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
+
+ ResumePoint point = new ResumePoint (finally_blocks);
+ resume_points.Add (point);
+ point.Define (ig);
+ }
+
+ private static MemberName MakeProxyName (string name)
+ {
+ int pos = name.LastIndexOf ('.');
+ if (pos > 0)
+ name = name.Substring (pos + 1);
+
+ return new MemberName ("<" + name + ">__" + (proxy_count++));
+ }
+
+ //
+ // Our constructor
+ //
+ public Iterator (TypeContainer container, string name, Type return_type,
+ Type [] param_types, InternalParameters parameters,
+ int modifiers, ToplevelBlock block, Location loc)
+ : base (container.NamespaceEntry, container, MakeProxyName (name),
+ Modifiers.PRIVATE, null, loc)
+ {
+ this.container = container;
+ this.return_type = return_type;
+ this.param_types = param_types;
+ this.parameters = parameters;
+ this.original_name = name;
+ this.original_block = block;
+ this.block = new ToplevelBlock (loc);
+
+ fields = new Hashtable ();
+
+ is_static = (modifiers & Modifiers.STATIC) != 0;
+ }
+
+ public bool DefineIterator ()
+ {
+ ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+
+ if (!CheckType (return_type)) {
+ Report.Error (
+ 1624, Location,
+ "The body of `{0}' cannot be an iterator block " +
+ "because '{1}' is not an iterator interface type",
+ original_name, TypeManager.CSharpName (return_type));
+ return false;
+ }
+
+ 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 (
+ 1623, Location,
+ "Iterators cannot have ref or out parameters");
+ return false;
+ }
+ }
+
+ if (container.CurrentType != null)
+ this_type = container.CurrentType;
+ else
+ this_type = container.TypeBuilder;
+
+ generic_args = new TypeArguments (Location);
+ generic_args.Add (new TypeExpression (iterator_type, Location));
+
+ ArrayList list = new ArrayList ();
+ if (is_enumerable) {
+ enumerable_type = new TypeExpression (
+ TypeManager.ienumerable_type, Location);
+ list.Add (enumerable_type);
+
+ generic_enumerable_type = new ConstructedType (
+ TypeManager.generic_ienumerable_type,
+ generic_args, Location);
+ list.Add (generic_enumerable_type);
+ }
+
+ enumerator_type = new TypeExpression (
+ TypeManager.ienumerator_type, Location);
+ list.Add (enumerator_type);
+
+ list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
+
+ generic_enumerator_type = new ConstructedType (
+ TypeManager.generic_ienumerator_type,
+ generic_args, Location);
+ list.Add (generic_enumerator_type);
+
+ iterator_type_expr = new TypeExpression (iterator_type, Location);
+
+ container.AddIterator (this);
+
+ Bases = list;
+ return true;
+ }
+
+ MethodInfo FetchMethodDispose ()
+ {
+ MemberList dispose_list;
+
+ dispose_list = FindMembers (
+ current_type.Type,
+ MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
+ Type.FilterName, "Dispose");
+
+ if (dispose_list.Count != 1)
+ throw new InternalErrorException ("Cannot find Dipose() method.");
+
+ return (MethodInfo) dispose_list [0];
+ }
+
+ protected override bool DoDefineMembers ()
+ {
+ if (!base.DoDefineMembers ())
+ return false;
+
+ dispose_method = FetchMethodDispose ();
+ if (dispose_method == null)
+ return false;
+
+ return true;
+ }
+
+ //
+ // Returns the new block for the method, or null on failure
+ //
+ protected override bool DefineNestedTypes ()
+ {
+ if (CurrentType != null)
+ current_type = new TypeExpression (CurrentType, Location);
+ else
+ current_type = new TypeExpression (TypeBuilder, Location);
+
+ Define_Fields ();
+ Define_Constructor ();
+ Define_Current (false);
+ Define_Current (true);
+ Define_MoveNext ();
+ Define_Reset ();
+ Define_Dispose ();
+
+ if (is_enumerable) {
+ Define_GetEnumerator (false);
+ Define_GetEnumerator (true);
+ }
+
+ Create_Block ();
+
+ return base.DefineNestedTypes ();
+ }
+
+
+ Field pc_field;
+ Field current_field;
+ Method dispose;
+
+ public Field this_field;
+ public Field[] parameter_fields;
+
+ void Create_Block ()
+ {
+ int first = is_static ? 0 : 1;
+
+ ArrayList args = new ArrayList ();
+ if (!is_static) {
+ Type t = this_type;
+ args.Add (new Argument (
+ new ThisParameterReference (t, 0, Location)));
+ }
+
+ args.Add (new Argument (new BoolLiteral (false)));
+
+ for (int i = 0; i < parameters.Count; i++) {
+ Type t = parameters.ParameterType (i);
+ args.Add (new Argument (
+ new SimpleParameterReference (t, first + i, Location)));
+ }
+
+ Expression new_expr = new New (current_type, args, Location);
+
+ block.AddStatement (new NoCheckReturn (new_expr, Location));
+ }
+
+ void Define_Fields ()
+ {
+ Location loc = Location.Null;
+
+ pc_field = new Field (
+ this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "PC",
+ null, null, loc);
+ AddField (pc_field);
+
+ current_field = new Field (
+ this, iterator_type_expr, Modifiers.PRIVATE, "current",
+ null, null, loc);
+ AddField (current_field);
+
+ if (!is_static) {
+ this_field = new Field (
+ this, new TypeExpression (this_type, loc),
+ Modifiers.PRIVATE, "this", null, null, loc);
+ AddField (this_field);
+ }
+
+ parameter_fields = new Field [parameters.Count];
+ for (int i = 0; i < parameters.Count; i++) {
+ string fname = String.Format (
+ "field{0}_{1}", i, parameters.ParameterName (i));
+
+ parameter_fields [i] = new Field (
+ this,
+ new TypeExpression (parameters.ParameterType (i), loc),
+ Modifiers.PRIVATE, fname, null, null, loc);
+ AddField (parameter_fields [i]);
+ }
+ }
+
+ void Define_Constructor ()
+ {
+ Parameters ctor_params;
+
+ ArrayList list = new ArrayList ();
+
+ if (!is_static)
+ list.Add (new Parameter (
+ new TypeExpression (this_type, Location),
+ "this", Parameter.Modifier.NONE, null));
+ list.Add (new Parameter (
+ TypeManager.system_boolean_expr, "initialized",
+ Parameter.Modifier.NONE, null));
+
+ Parameter[] old_fixed = parameters.Parameters.FixedParameters;
+ if (old_fixed != null)
+ list.AddRange (old_fixed);
+
+ Parameter[] fixed_params = new Parameter [list.Count];
+ list.CopyTo (fixed_params);
+
+ ctor_params = new Parameters (
+ fixed_params, parameters.Parameters.ArrayParameter,
+ Location);
+
+ Constructor ctor = new Constructor (
+ this, Name, Modifiers.PUBLIC, ctor_params,
+ new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters, Location),
+ Location);
+ AddConstructor (ctor);
+
+ ToplevelBlock block = ctor.Block = new ToplevelBlock (Location);
+
+ if (!is_static) {
+ Type t = this_type;
+
+ Assign assign = new Assign (
+ new FieldExpression (this_field),
+ new SimpleParameterReference (t, 1, Location),
+ Location);
+
+ block.AddStatement (new StatementExpression (assign, Location));
+ }
+
+ int first = is_static ? 2 : 3;
+
+ for (int i = 0; i < parameters.Count; i++) {
+ Type t = parameters.ParameterType (i);
+
+ Assign assign = new Assign (
+ new FieldExpression (parameter_fields [i]),
+ new SimpleParameterReference (t, first + i, Location),
+ Location);
+
+ block.AddStatement (new StatementExpression (assign, Location));
+ }
+
+ State initial = is_enumerable ? State.Uninitialized : State.Running;
+ block.AddStatement (new SetState (this, initial, Location));
+
+ block.AddStatement (new If (
+ new SimpleParameterReference (
+ TypeManager.bool_type, first - 1, Location),
+ new SetState (this, State.Running, Location),
+ Location));
+ }
+
+ Statement Create_ThrowInvalidOperation ()
+ {
+ TypeExpr ex_type = new TypeExpression (
+ TypeManager.invalid_operation_exception_type, Location);
+
+ return new Throw (new New (ex_type, null, Location), Location);
+ }
+
+ Statement Create_ThrowNotSupported ()
+ {
+ TypeExpr ex_type = new TypeExpression (
+ TypeManager.not_supported_exception_type, Location);
+
+ return new Throw (new New (ex_type, null, Location), Location);
+ }
+
+ void Define_Current (bool is_generic)
+ {
+ MemberName left;
+ Expression type;
+ if (is_generic) {
+ left = new MemberName (
+ "System.Collections.Generic.IEnumerator",
+ generic_args);
+ type = iterator_type_expr;
+ } else {
+ left = new MemberName ("System.Collections.IEnumerator");
+ type = TypeManager.system_object_expr;
+ }
+
+ MemberName name = new MemberName (left, "Current", null);
+
+ ToplevelBlock get_block = new ToplevelBlock (Location);
+
+ get_block.AddStatement (new If (
+ new Binary (
+ Binary.Operator.LessThanOrEqual,
+ new FieldExpression (pc_field),
+ new IntLiteral ((int) State.Running), Location),
+ Create_ThrowInvalidOperation (),
+ new Return (
+ new FieldExpression (current_field), Location),
+ Location));
+
+ Accessor getter = new Accessor (get_block, 0, null, Location);
+
+ Property current = new Property (
+ this, type, 0, false, name, null, getter, null, Location);
+ AddProperty (current);
+ }
+
+ void Define_MoveNext ()
+ {
+ Method move_next = new Method (
+ this, null, TypeManager.system_boolean_expr,
+ Modifiers.PUBLIC, false, new MemberName ("MoveNext"),
+ Parameters.EmptyReadOnlyParameters, null,
+ Location.Null);
+ AddMethod (move_next);
+
+ ToplevelBlock block = move_next.Block = new ToplevelBlock (Location);
+
+ MoveNextMethod inline = new MoveNextMethod (this, Location);
+ block.AddStatement (inline);
+ }
+
+ void Define_GetEnumerator (bool is_generic)
+ {
+ MemberName left;
+ Expression type;
+ if (is_generic) {
+ left = new MemberName (
+ "System.Collections.Generic.IEnumerable",
+ generic_args);
+ type = generic_enumerator_type;
+ } else {
+ left = new MemberName ("System.Collections.IEnumerable");
+ type = enumerator_type;
+ }
+
+ MemberName name = new MemberName (left, "GetEnumerator", null);
+
+ Method get_enumerator = new Method (
+ this, null, type, 0, false, name,
+ Parameters.EmptyReadOnlyParameters, null,
+ Location.Null);
+ AddMethod (get_enumerator);
+
+ get_enumerator.Block = new ToplevelBlock (Location);
+
+ Expression ce = new MemberAccess (
+ new SimpleName ("System.Threading.Interlocked", Location),
+ "CompareExchange", Location);
+
+ Expression pc = new FieldExpression (pc_field);
+ Expression before = new IntLiteral ((int) State.Running);
+ Expression uninitialized = new IntLiteral ((int) State.Uninitialized);
+
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (pc, Argument.AType.Ref));
+ args.Add (new Argument (before, Argument.AType.Expression));
+ args.Add (new Argument (uninitialized, Argument.AType.Expression));
+
+ get_enumerator.Block.AddStatement (new If (
+ new Binary (
+ Binary.Operator.Equality,
+ new Invocation (ce, args, Location),
+ uninitialized, Location),
+ new Return (new This (block, Location), Location),
+ Location));
+
+ args = new ArrayList ();
+ if (!is_static)
+ args.Add (new Argument (new FieldExpression (this_field)));
+
+ args.Add (new Argument (new BoolLiteral (true)));
+
+ for (int i = 0; i < parameters.Count; i++)
+ args.Add (new Argument (
+ new FieldExpression (parameter_fields [i])));
+
+ Expression new_expr = new New (current_type, args, Location);
+ get_enumerator.Block.AddStatement (new Return (new_expr, Location));
+ }
+
+ protected class SimpleParameterReference : Expression
+ {
+ int idx;
+
+ public SimpleParameterReference (Type type, int idx, Location loc)
+ {
+ this.idx = idx;
+ this.loc = loc;
+ this.type = type;
+ eclass = ExprClass.Variable;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ DoEmit (ec);
+ }
+
+ protected virtual void DoEmit (EmitContext ec)
+ {
+ ParameterReference.EmitLdArg (ec.ig, idx);
+ }
+ }
+
+ protected class ThisParameterReference : SimpleParameterReference
+ {
+ public ThisParameterReference (Type type, int idx, Location loc)
+ : base (type, idx, loc)
+ { }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ base.DoEmit (ec);
+ if (ec.TypeContainer is Struct)
+ ec.ig.Emit (OpCodes.Ldobj, type);
+ }
+ }
+
+ protected class FieldExpression : Expression
+ {
+ Field field;
+
+ public FieldExpression (Field field)
+ {
+ this.field = field;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
+ fexpr.InstanceExpression = ec.GetThis (loc);
+ return fexpr.Resolve (ec);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new InvalidOperationException ();
+ }
+ }
+
+ protected class MoveNextMethod : Statement {
+ Iterator iterator;
+
+ public MoveNextMethod (Iterator iterator, Location loc)
+ {
+ this.loc = loc;
+ this.iterator = iterator;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ ec.CurrentBranching.CurrentUsageVector.Return ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ int code_flags = Modifiers.METHOD_YIELDS;
+ if (iterator.is_static)
+ code_flags |= Modifiers.STATIC;
+
+ EmitContext new_ec = new EmitContext (
+ iterator.container, loc, ec.ig,
+ TypeManager.int32_type, code_flags);
+
+ new_ec.CurrentIterator = iterator;
+
+ iterator.EmitMoveNext (new_ec);
+ }
+ }
+
+ protected class DisposeMethod : Statement {
+ Iterator iterator;
+
+ public DisposeMethod (Iterator iterator, Location loc)
+ {
+ this.loc = loc;
+ this.iterator = iterator;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ iterator.EmitDispose (ec);
+ }
+ }
+
+ protected class StatementList : Statement {
+ ArrayList statements;
+
+ public StatementList (Location loc)
+ {
+ this.loc = loc;
+ statements = new ArrayList ();
+ }
+
+ public void Add (Statement statement)
+ {
+ statements.Add (statement);
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ foreach (Statement stmt in statements) {
+ if (!stmt.Resolve (ec))
+ return false;
+ }
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ foreach (Statement stmt in statements)
+ stmt.Emit (ec);
+ }
+ }
+
+ protected class SetState : Statement
+ {
+ Iterator iterator;
+ State state;
+
+ public SetState (Iterator iterator, State state, Location loc)
+ {
+ this.iterator = iterator;
+ this.state = state;
+ this.loc = loc;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Ldarg_0);
+ IntConstant.EmitInt (ec.ig, (int) state);
+ ec.ig.Emit (OpCodes.Stfld, iterator.pc_field.FieldBuilder);
+ }
+ }
+
+ void Define_Reset ()
+ {
+ Method reset = new Method (
+ this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
+ false, new MemberName ("Reset"),
+ Parameters.EmptyReadOnlyParameters, null, Location);
+ AddMethod (reset);
+
+ reset.Block = new ToplevelBlock (Location);
+ reset.Block.AddStatement (Create_ThrowNotSupported ());
+ }
+
+ void Define_Dispose ()
+ {
+ dispose = new Method (
+ this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
+ false, new MemberName ("Dispose"),
+ Parameters.EmptyReadOnlyParameters, null, Location);
+ AddMethod (dispose);
+
+ dispose.Block = new ToplevelBlock (Location);
+ dispose.Block.AddStatement (new DisposeMethod (this, Location));
+ }
+
+ public ToplevelBlock Block {
+ get { return block; }
+ }
+
+ public Type IteratorType {
+ get { return iterator_type; }
+ }
+
+ //
+ // 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;
+ }
+ }
+
+ bool CheckType (Type t)
+ {
+ if (t == TypeManager.ienumerable_type) {
+ iterator_type = TypeManager.object_type;
+ is_enumerable = true;
+ return true;
+ } else if (t == TypeManager.ienumerator_type) {
+ iterator_type = TypeManager.object_type;
+ is_enumerable = false;
+ return true;
+ }
+
+ if (!t.IsGenericInstance)
+ return false;
+
+ Type[] args = TypeManager.GetTypeArguments (t);
+ if (args.Length != 1)
+ return false;
+
+ Type gt = t.GetGenericTypeDefinition ();
+ if (gt == TypeManager.generic_ienumerable_type) {
+ iterator_type = args [0];
+ is_enumerable = true;
+ return true;
+ } else if (gt == TypeManager.generic_ienumerator_type) {
+ iterator_type = args [0];
+ is_enumerable = false;
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
+
--- /dev/null
+//
+// 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;
+
+//
+// I put System.Null just so we do not have to special case it on
+// TypeManager.CSharpName
+//
+namespace System {
+ //
+ // Represents the Null Type, just used as a placeholder for the type in NullLiteral
+ //
+ public class Null {
+ }
+}
+
+namespace Mono.CSharp {
+
+ //
+ // The NullType just exists to compare type equality, and for
+ // expressions that might have the `null type'
+ //
+ public class NullType {
+ }
+
+ //
+ // The null Literal constant
+ //
+ 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.null_type;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Ldnull);
+ }
+
+ public override bool IsNegative {
+ get {
+ return false;
+ }
+ }
+
+ public override bool IsZeroInteger {
+ get { return true; }
+ }
+ }
+
+ //
+ // A null literal in a pointer context
+ //
+ public class NullPointer : NullLiteral {
+ public new static readonly NullLiteral Null;
+
+ static NullPointer ()
+ {
+ Null = new NullPointer ();
+ }
+
+ private NullPointer ()
+ {
+ type = TypeManager.object_type;
+ }
+
+ 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 static IntLiteral One, Zero;
+
+ static IntLiteral ()
+ {
+ Zero = new IntLiteral (0);
+ One = new IntLiteral (1);
+ }
+
+ 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;
+ }
+ }
+}
--- /dev/null
+//
+// 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 Mono.CompilerServices.SymbolWriter;
+
+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 : ISourceFile {
+ public readonly string Name;
+ public readonly string Path;
+ public readonly int Index;
+ public SourceFileEntry SourceFileEntry;
+ public bool HasLineDirective;
+
+ public SourceFile (string name, string path, int index)
+ {
+ this.Index = index;
+ this.Name = name;
+ this.Path = path;
+ }
+
+ SourceFileEntry ISourceFile.Entry {
+ get { return SourceFileEntry; }
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("SourceFile ({0}:{1}:{2}:{3})",
+ Name, Path, Index, SourceFileEntry);
+ }
+ }
+
+ /// <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 current_source;
+
+ public readonly static Location Null;
+
+ static Location ()
+ {
+ source_files = new Hashtable ();
+ source_list = new ArrayList ();
+ current_source = 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.Warning (2002, name, "Source file '{0}' specified multiple times");
+ return;
+ }
+
+ 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 = name == "" ? "" : 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;
+ }
+*/
+
+ // <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.SourceFileEntry = 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 SourceFile SourceFile {
+ get {
+ int index = token & source_mask;
+ if (index == 0)
+ return null;
+ return (SourceFile) source_list [index - 1];
+ }
+ }
+ }
+}
--- /dev/null
+// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de
+
+#line 2 "mb-parser.jay"
+//
+// Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
+//
+// Authors: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
+// Anirban Bhattacharjee (banirban@novell.com)
+// Jambunathan K (kjambunathan@novell.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// Copyright (C) 2001, 2002, 2003, 2004 A Rafael D Teixeira
+// Copyright (C) 2003, 2004 Novell
+//
+//
+
+namespace Mono.CSharp
+{
+ using System.Text;
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using Mono.CSharp;
+
+ /// <summary>
+ /// The MonoBASIC Parser
+ /// </summary>
+// [DefaultParser]
+// public class Parser : GenericParser
+// {
+
+
+// /// <summary>
+// /// Current block is used to add statements as we find
+// /// them.
+// /// </summary>
+// Block current_block;
+
+// /// <summary>
+// /// Tmp block is used to store block endings in if/select's
+// /// </summary>
+// Block tmp_block;
+
+// /// <summary>
+// /// Tmp block is used to store tmp copies of expressions
+// /// </summary>
+// Expression tmp_expr;
+
+// /// <summary>
+// /// Tmp catch is used to store catch clauses in try..catch..finally
+// /// </summary>
+// ArrayList tmp_catch_clauses;
+
+// /// <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>
+// /// This are used when parsing parameters in property
+// /// declarations.
+// /// </summary>
+// Parameters set_parameters;
+// Parameters get_parameters;
+
+// /// <summary>
+// /// This is used by the sub_header parser to store modifiers
+// /// to be passed to sub/constructor
+// /// </summary>
+// int current_modifiers;
+
+// /// <summary>
+// /// This is used by the sub_header parser to store attributes
+// /// to be passed to sub/constructor
+// /// </summary>
+// Attributes current_attributes;
+
+// /// <summary>
+// /// Using during property parsing to describe the implicit
+// /// value parameter that is passed to the "set" accessor
+// /// method
+// /// </summary>
+// string get_implicit_value_parameter_name;
+
+// // <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 get_implicit_value_parameter_type;
+
+// /// <summary>
+// /// Using during property parsing to describe the implicit
+// /// value parameter that is passed to the "set" accessor
+// /// method
+// /// </summary>
+// string set_implicit_value_parameter_name;
+
+// // <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 set_implicit_value_parameter_type;
+
+// Location member_location;
+
+// // An out-of-band stack.
+// //
+// Stack oob_stack;
+
+// ArrayList current_rank_specifiers;
+
+// DoOptions do_type;
+// //
+// // Switch stack.
+// //
+// Stack switch_stack;
+
+// // Expression stack for nested ifs
+// Stack expr_stack;
+
+// Stack tmp_blocks;
+// Stack statement_stack;
+
+// // A stack for With expressions.
+// //
+// Stack with_stack;
+
+
+// static public bool InitialOptionExplicit = false;
+// static public bool InitialOptionStrict = false;
+// static public bool InitialOptionCompareBinary = true;
+// static public ArrayList ImportsList = null;
+
+// bool OptionExplicit;
+// bool OptionStrict;
+// bool OptionCompareBinary;
+
+// static public bool UseExtendedSyntax; // for ".mbs" files
+
+// bool implicit_modifiers;
+
+// public override string[] extensions()
+// {
+// string [] list = { ".vb", ".mbs" };
+// return list;
+// }
+
+
+ /// <summary>
+ /// The C# Parser
+ /// </summary>
+ public class CSharpParser {
+ NamespaceEntry current_namespace;
+ TypeContainer current_container;
+ TypeContainer current_class;
+
+ IIteratorContainer iterator_container;
+
+ /// <summary>
+ /// Current block is used to add statements as we find
+ /// them.
+ /// </summary>
+ Block current_block, top_current_block;
+
+ /// <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;
+
+ static public int yacc_verbose_flag;
+
+ // Name of the file we are parsing
+ public string name;
+
+ ///
+ /// The current file.
+ ///
+ SourceFile file;
+
+ /// This is used by the sub_header parser to store modifiers
+ /// to be passed to sub/constructor
+ int current_modifiers;
+
+ /// This is used by the sub_header parser to store attributes
+ /// to be passed to sub/constructor
+ Attributes current_attributes;
+
+ /// This is used by the attributes parser to syntactically
+ /// validate the attribute rules
+ bool allow_global_attribs = true;
+
+ bool expecting_global_attribs = false;
+ bool expecting_local_attribs = false;
+
+ bool local_attrib_section_added = false;
+
+ ///FIXME
+ ArrayList current_rank_specifiers;
+
+ /// <summary>
+ /// Using during property parsing to describe the implicit
+ /// value parameter that is passed to the "set" accessor
+ /// method
+ /// </summary>
+ string get_implicit_value_parameter_name;
+
+ // <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 get_implicit_value_parameter_type;
+
+ /// <summary>
+ /// Using during property parsing to describe the implicit
+ /// value parameter that is passed to the "set" accessor
+ /// method
+ /// </summary>
+ string set_implicit_value_parameter_name;
+
+ // <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 set_implicit_value_parameter_type;
+
+ /// <summary>
+ /// This are used when parsing parameters in property
+ /// declarations.
+ /// </summary>
+ Parameters set_parameters;
+ Parameters get_parameters;
+
+// static public ArrayList ImportsList = null;
+
+ bool implicit_modifiers;
+
+
+ /// <summary>
+ /// This is used as a helper class for handling of
+ /// pre-processor statements.
+ /// </summary>
+
+ // FIXME: This class MBASException is actually a kludge
+ // It can be done away with a more elegant replacement.
+
+ public class MBASException : ApplicationException
+ {
+ public int code;
+ public Location loc;
+
+ public MBASException(int code, Location loc, string text) : base(text)
+ {
+ this.code = code;
+ this.loc = loc;
+ }
+ }
+
+
+
+ public class IfElseStateMachine {
+
+ public enum State {
+ START,
+ IF_SEEN,
+ ELSEIF_SEEN,
+ ELSE_SEEN,
+ ENDIF_SEEN,
+ MAX
+ }
+
+ public enum Token {
+ START,
+ IF,
+ ELSEIF,
+ ELSE,
+ ENDIF,
+ EOF,
+ MAX
+ }
+
+ State state;
+ Stack stateStack;
+
+ public static Hashtable errStrings = new Hashtable();
+
+ int err=0;
+ static int[,] errTable = new int[(int)State.MAX, (int)Token.MAX];
+
+ static IfElseStateMachine()
+ {
+ // FIXME: Fix both the error nos and the error strings.
+ // Currently the error numbers and the error strings are
+ // just placeholders for getting the state-machine going.
+
+ errStrings.Add(0, "");
+ errStrings.Add(30012, "#If must end with a matching #End If");
+ errStrings.Add(30013, "#ElseIf, #Else or #End If must be preceded by a matching #If");
+ errStrings.Add(30014, "#ElseIf must be preceded by a matching #If or #ElseIf");
+ errStrings.Add(30028, "#Else must be preceded by a matching #If or #ElseIf");
+ errStrings.Add(32030, "#ElseIf cannot follow #Else as part of #If block");
+
+ errTable[(int)State.START, (int)Token.IF] = 0;
+ errTable[(int)State.START, (int)Token.ELSEIF] = 30014;
+ errTable[(int)State.START, (int)Token.ELSE] = 30028;
+ errTable[(int)State.START, (int)Token.ENDIF] = 30013;
+ errTable[(int)State.START, (int)Token.EOF] = 0;
+
+ errTable[(int)State.IF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ELSEIF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ELSE] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSEIF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSE] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ELSE_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ELSEIF] = 32030;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ELSE] = 32030;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.ELSE_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ENDIF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ELSEIF] = 30014;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ELSE] = 30028;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ENDIF] = 30013;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.EOF] = 0;
+ }
+
+ public IfElseStateMachine()
+ {
+ state = State.START;
+
+ stateStack = new Stack();
+ stateStack.Push(state);
+ }
+
+ // The parameter here need not be qualified with IfElseStateMachine
+ // But it hits a bug in mcs. So temporarily scoping it so that builds
+ // are not broken.
+
+ public void HandleToken(IfElseStateMachine.Token tok)
+ {
+ err = (int) errTable[(int)state, (int)tok];
+
+ if(err != 0)
+ throw new ApplicationException("Unexpected pre-processor directive #"+tok);
+
+ if(tok == Token.IF) {
+ stateStack.Push(state);
+ state = (State) tok;
+ }
+ else if(tok == Token.ENDIF) {
+ state = (State)stateStack.Pop();
+ }
+ else
+ state = (State)tok;
+ }
+
+ public int Error {
+ get {
+ return err;
+ }
+ }
+
+ public string ErrString {
+ get {
+ return (string) errStrings[err];
+ }
+ }
+ }
+
+
+ public class TokenizerController {
+
+ struct State
+ {
+ public bool CanAcceptTokens;
+ public bool CanSelectBlock;
+
+ }
+
+ State currentState;
+ Stack stateStack;
+ Tokenizer lexer;
+
+ public TokenizerController(Tokenizer lexer)
+ {
+ this.lexer = lexer;
+ stateStack = new Stack();
+
+ currentState.CanAcceptTokens = true;
+ currentState.CanSelectBlock = true;
+
+ stateStack.Push(currentState);
+ }
+
+ State parentState {
+ get {
+ return (State)stateStack.Peek();
+ }
+ }
+
+ public bool IsAcceptingTokens {
+ get {
+ return currentState.CanAcceptTokens;
+ }
+ }
+
+ public void PositionCursorAtNextPreProcessorDirective()
+ {
+ lexer.PositionCursorAtNextPreProcessorDirective();
+ }
+
+ public void PositionTokenizerCursor(IfElseStateMachine.Token tok, BoolLiteral expr)
+ {
+ if(tok == IfElseStateMachine.Token.ENDIF) {
+ currentState = (State)stateStack.Pop();
+
+ if(currentState.CanAcceptTokens)
+ return;
+ else {
+ PositionCursorAtNextPreProcessorDirective();
+ return;
+ }
+ }
+
+ if(tok == IfElseStateMachine.Token.IF) {
+ stateStack.Push(currentState);
+
+ currentState.CanAcceptTokens = parentState.CanAcceptTokens;
+ currentState.CanSelectBlock = true;
+ }
+
+ if(parentState.CanAcceptTokens &&
+ currentState.CanSelectBlock && (bool)(expr.GetValue()) ) {
+
+ currentState.CanAcceptTokens = true;
+ currentState.CanSelectBlock = false;
+ return;
+ }
+ else {
+ currentState.CanAcceptTokens = false;
+ PositionCursorAtNextPreProcessorDirective();
+ return;
+ }
+ }
+ }
+
+ bool in_external_source = false;
+ int in_marked_region = 0;
+
+ TokenizerController tokenizerController;
+ IfElseStateMachine ifElseStateMachine;
+
+
+
+#line default
+
+ /** error output stream.
+ It should be changeable.
+ */
+ public System.IO.TextWriter ErrorOutput = System.Console.Out;
+
+ /** simplified error message.
+ @see <a href="#yyerror(java.lang.String, java.lang.String[])">yyerror</a>
+ */
+ public void yyerror (string message) {
+ yyerror(message, null);
+ }
+
+ /** (syntax) error message.
+ Can be overwritten to control message format.
+ @param message text to be displayed.
+ @param expected vector of acceptable tokens, if available.
+ */
+ public void yyerror (string message, string[] expected) {
+ if ((yacc_verbose_flag > 0) && (expected != null) && (expected.Length > 0)) {
+ ErrorOutput.Write (message+", expecting");
+ for (int n = 0; n < expected.Length; ++ n)
+ ErrorOutput.Write (" "+expected[n]);
+ ErrorOutput.WriteLine ();
+ } else
+ ErrorOutput.WriteLine (message);
+ }
+
+ /** debugging support, requires the package jay.yydebug.
+ Set to null to suppress debugging messages.
+ */
+ internal yydebug.yyDebug debug;
+
+ protected static int yyFinal = 2;
+ public static string [] yyRule = {
+ "$accept : compilation_unit",
+ "end_of_stmt : logical_end_of_line",
+ "end_of_stmt : COLON",
+ "logical_end_of_line : EOL",
+ "logical_end_of_line : logical_end_of_line pp_directive",
+ "compilation_unit : logical_end_of_line opt_option_directives opt_imports_directives declarations EOF",
+ "compilation_unit : logical_end_of_line opt_option_directives opt_imports_directives opt_attributes EOF",
+ "opt_option_directives :",
+ "opt_option_directives : option_directives",
+ "option_directives : option_directive",
+ "option_directives : option_directives option_directive",
+ "option_directive : option_explicit_directive",
+ "option_directive : option_strict_directive",
+ "option_directive : option_compare_directive",
+ "on_off :",
+ "on_off : ON",
+ "on_off : OFF",
+ "text_or_binary : BINARY",
+ "text_or_binary : TEXT",
+ "option_explicit_directive : OPTION EXPLICIT on_off logical_end_of_line",
+ "option_strict_directive : OPTION STRICT on_off logical_end_of_line",
+ "option_compare_directive : OPTION COMPARE text_or_binary logical_end_of_line",
+ "opt_declarations :",
+ "opt_declarations : declarations",
+ "declarations : declaration",
+ "declarations : declarations declaration",
+ "$$1 :",
+ "declaration : declaration_qualifiers $$1 namespace_declaration",
+ "$$2 :",
+ "declaration : declaration_qualifiers $$2 type_spec_declaration",
+ "identifier : IDENTIFIER",
+ "identifier : BINARY",
+ "identifier : TEXT",
+ "identifier : COMPARE",
+ "identifier : EXPLICIT",
+ "identifier : OFF",
+ "type_character : PERCENT",
+ "type_character : LONGTYPECHAR",
+ "type_character : AT_SIGN",
+ "type_character : SINGLETYPECHAR",
+ "type_character : NUMBER_SIGN",
+ "type_character : DOLAR_SIGN",
+ "opt_type_character :",
+ "opt_type_character : type_character",
+ "qualified_identifier : identifier",
+ "qualified_identifier : qualified_identifier DOT identifier",
+ "opt_imports_directives :",
+ "opt_imports_directives : imports_directives",
+ "imports_directives : imports_directive",
+ "imports_directives : imports_directives imports_directive",
+ "imports_directive : IMPORTS imports_terms logical_end_of_line",
+ "imports_terms : imports_term",
+ "imports_terms : imports_terms COMMA imports_term",
+ "imports_term : namespace_or_type_name",
+ "imports_term : identifier ASSIGN namespace_or_type_name",
+ "opt_params :",
+ "opt_params : OPEN_PARENS CLOSE_PARENS",
+ "opt_params : OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS",
+ "opt_attributes :",
+ "opt_attributes : attribute_sections",
+ "attribute_sections : attribute_section",
+ "$$3 :",
+ "attribute_sections : attribute_sections $$3 attribute_section",
+ "attribute_section : OP_LT attribute_list OP_GT opt_end_of_stmt",
+ "opt_end_of_stmt :",
+ "opt_end_of_stmt : end_of_stmt",
+ "attribute_list : attribute",
+ "attribute_list : attribute_list COMMA attribute",
+ "$$4 :",
+ "attribute : namespace_or_type_name $$4 opt_attribute_arguments",
+ "$$5 :",
+ "$$6 :",
+ "attribute : attribute_target_specifier $$5 COLON namespace_or_type_name $$6 opt_attribute_arguments",
+ "attribute_target_specifier : ASSEMBLY",
+ "attribute_target_specifier : MODULE",
+ "attribute_target_specifier : namespace_or_type_name",
+ "opt_attribute_arguments :",
+ "opt_attribute_arguments : OPEN_PARENS opt_attribute_arguments_list CLOSE_PARENS",
+ "opt_attribute_arguments_list :",
+ "opt_attribute_arguments_list : attribute_arguments_list",
+ "attribute_arguments_list : positional_argument_list",
+ "attribute_arguments_list : positional_argument_list COMMA named_argument_list",
+ "attribute_arguments_list : named_argument_list",
+ "positional_argument_list : constant_expression",
+ "positional_argument_list : positional_argument_list COMMA constant_expression",
+ "named_argument_list : named_argument",
+ "named_argument_list : named_argument_list COMMA named_argument",
+ "named_argument : identifier ATTR_ASSIGN constant_expression",
+ "$$7 :",
+ "namespace_declaration : NAMESPACE qualified_identifier logical_end_of_line $$7 opt_declarations END NAMESPACE logical_end_of_line",
+ "declaration_qualifiers : opt_attributes opt_modifiers",
+ "type_spec_declaration : class_declaration",
+ "type_spec_declaration : module_declaration",
+ "type_spec_declaration : interface_declaration",
+ "type_spec_declaration : delegate_declaration",
+ "type_spec_declaration : struct_declaration",
+ "type_spec_declaration : enum_declaration",
+ "$$8 :",
+ "$$9 :",
+ "class_declaration : CLASS identifier logical_end_of_line $$8 opt_inherits opt_implements $$9 opt_class_member_declarations END CLASS logical_end_of_line",
+ "opt_inherits :",
+ "opt_inherits : INHERITS type_list logical_end_of_line",
+ "opt_implements :",
+ "opt_implements : IMPLEMENTS type_list logical_end_of_line",
+ "opt_modifiers :",
+ "opt_modifiers : modifiers",
+ "modifiers : modifier",
+ "modifiers : modifiers modifier",
+ "modifier : PUBLIC",
+ "modifier : PROTECTED",
+ "modifier : PRIVATE",
+ "modifier : SHARED",
+ "modifier : FRIEND",
+ "modifier : NOTINHERITABLE",
+ "modifier : OVERRIDABLE",
+ "modifier : NOTOVERRIDABLE",
+ "modifier : OVERRIDES",
+ "modifier : OVERLOADS",
+ "modifier : SHADOWS",
+ "modifier : MUSTINHERIT",
+ "modifier : READONLY",
+ "modifier : DEFAULT",
+ "modifier : WRITEONLY",
+ "$$10 :",
+ "module_declaration : MODULE identifier logical_end_of_line $$10 opt_module_member_declarations END MODULE logical_end_of_line",
+ "opt_module_member_declarations :",
+ "opt_module_member_declarations : module_member_declarations",
+ "module_member_declarations : module_member_declaration",
+ "module_member_declarations : module_member_declarations module_member_declaration",
+ "$$11 :",
+ "module_member_declaration : opt_attributes opt_modifiers $$11 module_member_declarator",
+ "module_member_declarator : constructor_declaration",
+ "module_member_declarator : method_declaration",
+ "module_member_declarator : field_declaration",
+ "module_member_declarator : constant_declaration",
+ "module_member_declarator : property_declaration",
+ "module_member_declarator : event_declaration",
+ "module_member_declarator : type_spec_declaration",
+ "constant_declaration : CONST constant_declarators logical_end_of_line",
+ "opt_class_member_declarations :",
+ "opt_class_member_declarations : class_member_declarations",
+ "class_member_declarations : class_member_declaration",
+ "class_member_declarations : class_member_declarations class_member_declaration",
+ "class_member_declaration : opt_attributes opt_modifiers class_member_declarator",
+ "class_member_declarator : field_declaration",
+ "class_member_declarator : constant_declaration",
+ "class_member_declarator : method_declaration",
+ "class_member_declarator : constructor_declaration",
+ "class_member_declarator : property_declaration",
+ "class_member_declarator : event_declaration",
+ "class_member_declarator : type_spec_declaration",
+ "method_declaration : sub_declaration",
+ "method_declaration : func_declaration",
+ "$$12 :",
+ "sub_declaration : SUB identifier opt_params $$12 opt_evt_handler opt_implement_clause logical_end_of_line begin_block opt_statement_list end_block END SUB logical_end_of_line",
+ "$$13 :",
+ "$$14 :",
+ "func_declaration : FUNCTION identifier opt_type_character opt_params opt_type_with_ranks $$13 opt_implement_clause logical_end_of_line begin_block $$14 opt_statement_list end_block END FUNCTION logical_end_of_line",
+ "$$15 :",
+ "$$16 :",
+ "struct_declaration : STRUCTURE identifier logical_end_of_line opt_implement_clause $$15 opt_struct_member_declarations $$16 END STRUCTURE logical_end_of_line",
+ "opt_logical_end_of_line :",
+ "opt_logical_end_of_line : logical_end_of_line",
+ "opt_struct_member_declarations :",
+ "opt_struct_member_declarations : struct_member_declarations",
+ "struct_member_declarations : struct_member_declaration",
+ "struct_member_declarations : struct_member_declarations struct_member_declaration",
+ "struct_member_declaration : opt_modifiers struct_member_declarator",
+ "struct_member_declarator : field_declaration",
+ "struct_member_declarator : constant_declaration",
+ "struct_member_declarator : constructor_declaration",
+ "struct_member_declarator : method_declaration",
+ "struct_member_declarator : event_declaration",
+ "struct_member_declarator : type_spec_declaration",
+ "event_declaration : EVENT identifier AS type opt_implement_clause logical_end_of_line",
+ "$$17 :",
+ "enum_declaration : ENUM identifier opt_type_spec logical_end_of_line opt_enum_member_declarations $$17 END ENUM logical_end_of_line",
+ "opt_enum_member_declarations :",
+ "opt_enum_member_declarations : enum_member_declarations",
+ "enum_member_declarations : enum_member_declaration",
+ "enum_member_declarations : enum_member_declarations enum_member_declaration",
+ "enum_member_declaration : opt_attributes identifier logical_end_of_line",
+ "$$18 :",
+ "enum_member_declaration : opt_attributes identifier $$18 ASSIGN expression logical_end_of_line",
+ "interface_property_declaration : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line",
+ "$$19 :",
+ "$$20 :",
+ "$$21 :",
+ "interface_declaration : INTERFACE identifier logical_end_of_line $$19 opt_interface_base $$20 interface_body $$21 END INTERFACE logical_end_of_line",
+ "opt_interface_base :",
+ "opt_interface_base : interface_bases",
+ "interface_bases : interface_base",
+ "interface_bases : interface_bases interface_base",
+ "interface_base : INHERITS type_list logical_end_of_line",
+ "interface_body : opt_interface_member_declarations",
+ "opt_interface_member_declarations :",
+ "opt_interface_member_declarations : interface_member_declarations",
+ "interface_member_declarations : interface_member_declaration",
+ "interface_member_declarations : interface_member_declarations interface_member_declaration",
+ "interface_member_declaration : opt_attributes opt_modifiers interface_member_declarator",
+ "interface_member_declarator : interface_method_declaration",
+ "interface_member_declarator : interface_property_declaration",
+ "interface_method_declaration : SUB identifier opt_params logical_end_of_line",
+ "interface_method_declaration : FUNCTION identifier opt_type_character opt_params opt_type_with_ranks logical_end_of_line",
+ "property_declaration : non_abstract_propery_declaration",
+ "$$22 :",
+ "non_abstract_propery_declaration : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks opt_implement_clause logical_end_of_line $$22 accessor_declarations END PROPERTY logical_end_of_line",
+ "opt_property_parameters :",
+ "opt_property_parameters : OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS",
+ "opt_implement_clause :",
+ "opt_implement_clause : IMPLEMENTS implement_clause_list",
+ "implement_clause_list : qualified_identifier",
+ "implement_clause_list : implement_clause_list COMMA qualified_identifier",
+ "accessor_declarations : get_accessor_declaration opt_set_accessor_declaration",
+ "accessor_declarations : set_accessor_declaration opt_get_accessor_declaration",
+ "opt_get_accessor_declaration :",
+ "opt_get_accessor_declaration : get_accessor_declaration",
+ "opt_set_accessor_declaration :",
+ "opt_set_accessor_declaration : set_accessor_declaration",
+ "$$23 :",
+ "$$24 :",
+ "get_accessor_declaration : opt_attributes GET logical_end_of_line $$23 begin_block $$24 opt_statement_list end_block END GET logical_end_of_line",
+ "$$25 :",
+ "set_accessor_declaration : opt_attributes SET opt_set_parameter logical_end_of_line $$25 begin_block opt_statement_list end_block END SET logical_end_of_line",
+ "opt_set_parameter :",
+ "opt_set_parameter : OPEN_PARENS CLOSE_PARENS",
+ "opt_set_parameter : OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_with_ranks CLOSE_PARENS",
+ "field_declaration : opt_dim_stmt variable_declarators logical_end_of_line",
+ "opt_dim_stmt :",
+ "opt_dim_stmt : DIM",
+ "delegate_declaration : DELEGATE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS logical_end_of_line",
+ "delegate_declaration : DELEGATE FUNCTION identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks logical_end_of_line",
+ "opt_evt_handler :",
+ "$$26 :",
+ "$$27 :",
+ "constructor_declaration : SUB NEW opt_params logical_end_of_line $$26 begin_block opt_statement_list end_block $$27 END SUB logical_end_of_line",
+ "opt_formal_parameter_list :",
+ "opt_formal_parameter_list : formal_parameter_list",
+ "formal_parameter_list : parameters",
+ "parameters : parameter",
+ "parameters : parameters COMMA parameter",
+ "parameter : opt_attributes opt_parameter_modifier identifier opt_type_character opt_rank_specifiers opt_type_with_ranks opt_variable_initializer",
+ "opt_parameter_modifier :",
+ "opt_parameter_modifier : parameter_modifiers",
+ "parameter_modifiers : parameter_modifiers parameter_modifier",
+ "parameter_modifiers : parameter_modifier",
+ "parameter_modifier : BYREF",
+ "parameter_modifier : BYVAL",
+ "parameter_modifier : OPTIONAL",
+ "parameter_modifier : PARAM_ARRAY",
+ "opt_statement_list :",
+ "opt_statement_list : statement_list end_of_stmt",
+ "statement_list : statement",
+ "statement_list : statement_list end_of_stmt statement",
+ "block : begin_block opt_statement_list end_block",
+ "begin_block :",
+ "end_block :",
+ "statement : declaration_statement",
+ "statement : embedded_statement",
+ "statement : ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF expression",
+ "statement : REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF expression",
+ "statement : RAISEEVENT identifier opt_raise_event_args",
+ "opt_raise_event_args :",
+ "opt_raise_event_args : OPEN_PARENS opt_argument_list CLOSE_PARENS",
+ "embedded_statement : expression_statement",
+ "embedded_statement : selection_statement",
+ "embedded_statement : try_statement",
+ "embedded_statement : synclock_statement",
+ "embedded_statement : jump_statement",
+ "jump_statement : return_statement",
+ "jump_statement : goto_statement",
+ "jump_statement : throw_statement",
+ "goto_statement : GOTO label_name",
+ "throw_statement : THROW opt_expression",
+ "return_statement : RETURN opt_expression",
+ "synclock_statement : SYNCLOCK expression end_of_stmt block END SYNCLOCK",
+ "try_statement : try_catch",
+ "try_statement : try_catch_finally",
+ "try_catch : TRY end_of_stmt block opt_catch_clauses END TRY",
+ "try_catch_finally : TRY end_of_stmt block opt_catch_clauses FINALLY end_of_stmt block END TRY",
+ "opt_catch_clauses :",
+ "opt_catch_clauses : catch_clauses",
+ "catch_clauses : catch_clause",
+ "catch_clauses : catch_clauses catch_clause",
+ "opt_identifier :",
+ "opt_identifier : identifier",
+ "$$28 :",
+ "catch_clause : CATCH opt_catch_args end_of_stmt $$28 block",
+ "opt_catch_args :",
+ "opt_catch_args : catch_args",
+ "catch_args : identifier AS type",
+ "$$29 :",
+ "while_statement : WHILE $$29 boolean_expression end_of_stmt begin_block opt_statement_list end_block END WHILE",
+ "selection_statement : if_statement",
+ "if_statement : IF boolean_expression opt_then end_of_stmt block END IF",
+ "if_statement : IF boolean_expression opt_then end_of_stmt block ELSE end_of_stmt block END IF",
+ "if_statement : IF boolean_expression opt_then end_of_stmt block else_if_statement_rest",
+ "else_if_statement_rest : ELSEIF boolean_expression opt_then end_of_stmt block END IF",
+ "else_if_statement_rest : ELSEIF boolean_expression opt_then end_of_stmt block ELSE end_of_stmt block END IF",
+ "else_if_statement_rest : ELSEIF boolean_expression opt_then end_of_stmt block else_if_statement_rest",
+ "opt_then :",
+ "opt_then : THEN",
+ "case_clauses : case_clause",
+ "case_clauses : case_clauses COMMA case_clause",
+ "case_clause : opt_is comparison_operator expression",
+ "case_clause : expression",
+ "opt_is :",
+ "opt_is : IS",
+ "comparison_operator : OP_LT",
+ "comparison_operator : OP_GT",
+ "comparison_operator : OP_LE",
+ "comparison_operator : OP_NE",
+ "opt_case :",
+ "opt_case : CASE",
+ "expression_statement : statement_expression",
+ "statement_expression : invocation_expression",
+ "statement_expression : object_creation_expression",
+ "statement_expression : assignment_expression",
+ "object_creation_expression : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS",
+ "object_creation_expression : NEW type",
+ "new_expression : object_creation_expression",
+ "declaration_statement : local_variable_declaration",
+ "declaration_statement : local_constant_declaration",
+ "local_variable_declaration : DIM variable_declarators",
+ "local_constant_declaration : CONST constant_declarators",
+ "constant_declarators : constant_declarator",
+ "constant_declarators : constant_declarators COMMA constant_declarator",
+ "constant_declarator : variable_name opt_type_decl opt_variable_initializer",
+ "variable_declarators : variable_declarator",
+ "variable_declarators : variable_declarators COMMA variable_declarator",
+ "variable_declarator : variable_names opt_type_decl opt_variable_initializer",
+ "variable_names : variable_name",
+ "variable_names : variable_names COMMA variable_name",
+ "variable_name : identifier opt_type_character opt_array_name_modifier",
+ "opt_type_spec :",
+ "opt_type_spec : AS type",
+ "opt_type_with_ranks : opt_type_spec",
+ "opt_type_decl : opt_type_with_ranks",
+ "opt_type_decl : AS NEW type",
+ "opt_type_decl : AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS",
+ "opt_array_name_modifier :",
+ "opt_variable_initializer :",
+ "opt_variable_initializer : ASSIGN variable_initializer",
+ "variable_initializer : expression",
+ "variable_initializer : array_initializer",
+ "array_initializer : OPEN_BRACE CLOSE_BRACE",
+ "array_initializer : OPEN_BRACE variable_initializer_list CLOSE_BRACE",
+ "variable_initializer_list : variable_initializer",
+ "variable_initializer_list : variable_initializer_list COMMA variable_initializer",
+ "opt_rank_specifiers :",
+ "opt_rank_specifiers : rank_specifiers",
+ "rank_specifiers : rank_specifier",
+ "rank_specifiers : rank_specifiers rank_specifier",
+ "rank_specifier : OPEN_PARENS opt_dim_specifiers CLOSE_PARENS",
+ "opt_dim_specifiers :",
+ "opt_dim_specifiers : expression",
+ "opt_dim_specifiers : opt_dim_specifiers COMMA expression",
+ "opt_dim_specifiers : opt_dim_specifiers COMMA",
+ "primary_expression : literal",
+ "primary_expression : parenthesized_expression",
+ "primary_expression : this_access",
+ "primary_expression : base_access",
+ "primary_expression : qualified_identifier",
+ "primary_expression : get_type_expression",
+ "primary_expression : member_access",
+ "primary_expression : invocation_expression",
+ "primary_expression : new_expression",
+ "primary_expression : cast_expression",
+ "literal : boolean_literal",
+ "literal : integer_literal",
+ "literal : real_literal",
+ "literal : LITERAL_CHARACTER",
+ "literal : LITERAL_STRING",
+ "literal : NOTHING",
+ "real_literal : LITERAL_SINGLE",
+ "real_literal : LITERAL_DOUBLE",
+ "real_literal : LITERAL_DECIMAL",
+ "integer_literal : LITERAL_INTEGER",
+ "boolean_literal : TRUE",
+ "boolean_literal : FALSE",
+ "parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS",
+ "member_access : primary_expression DOT identifier",
+ "member_access : predefined_type DOT identifier",
+ "predefined_type : builtin_types",
+ "invocation_expression : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS",
+ "invocation_expression : CALL primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS",
+ "base_access : MYBASE DOT IDENTIFIER",
+ "opt_argument_list : argument_list",
+ "argument_list : argument",
+ "argument_list : argument_list COMMA argument",
+ "argument : expression",
+ "argument : BYREF variable_reference",
+ "argument :",
+ "argument : ADDRESSOF expression",
+ "variable_reference : expression",
+ "expression : conditional_xor_expression",
+ "opt_expression :",
+ "opt_expression : expression",
+ "this_access : ME",
+ "this_access : MYCLASS",
+ "cast_expression : DIRECTCAST OPEN_PARENS expression COMMA type CLOSE_PARENS",
+ "cast_expression : CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS",
+ "cast_expression : cast_operator OPEN_PARENS expression CLOSE_PARENS",
+ "cast_operator : CBOOL",
+ "cast_operator : CBYTE",
+ "cast_operator : CCHAR",
+ "cast_operator : CDBL",
+ "cast_operator : CDEC",
+ "cast_operator : CINT",
+ "cast_operator : CLNG",
+ "cast_operator : COBJ",
+ "cast_operator : CSHORT",
+ "cast_operator : CSNG",
+ "cast_operator : CSTR",
+ "get_type_expression : GETTYPE OPEN_PARENS type CLOSE_PARENS",
+ "exponentiation_expression : primary_expression",
+ "exponentiation_expression : exponentiation_expression OP_EXP primary_expression",
+ "prefixed_unary_expression : exponentiation_expression",
+ "prefixed_unary_expression : PLUS prefixed_unary_expression",
+ "prefixed_unary_expression : MINUS prefixed_unary_expression",
+ "multiplicative_expression : prefixed_unary_expression",
+ "multiplicative_expression : multiplicative_expression STAR prefixed_unary_expression",
+ "multiplicative_expression : multiplicative_expression DIV prefixed_unary_expression",
+ "integer_division_expression : multiplicative_expression",
+ "integer_division_expression : integer_division_expression OP_IDIV multiplicative_expression",
+ "mod_expression : integer_division_expression",
+ "mod_expression : mod_expression MOD integer_division_expression",
+ "additive_expression : mod_expression",
+ "additive_expression : additive_expression PLUS mod_expression",
+ "additive_expression : additive_expression MINUS mod_expression",
+ "concat_expression : additive_expression",
+ "concat_expression : concat_expression OP_CONCAT additive_expression",
+ "shift_expression : concat_expression",
+ "shift_expression : shift_expression OP_SHIFT_LEFT concat_expression",
+ "shift_expression : shift_expression OP_SHIFT_RIGHT concat_expression",
+ "relational_expression : shift_expression",
+ "relational_expression : relational_expression ASSIGN shift_expression",
+ "relational_expression : relational_expression OP_NE shift_expression",
+ "relational_expression : relational_expression OP_LT shift_expression",
+ "relational_expression : relational_expression OP_GT shift_expression",
+ "relational_expression : relational_expression OP_LE shift_expression",
+ "relational_expression : relational_expression OP_GE shift_expression",
+ "relational_expression : relational_expression IS shift_expression",
+ "relational_expression : TYPEOF shift_expression IS type",
+ "negation_expression : relational_expression",
+ "negation_expression : NOT negation_expression",
+ "conditional_and_expression : negation_expression",
+ "conditional_and_expression : conditional_and_expression AND negation_expression",
+ "conditional_and_expression : conditional_and_expression ANDALSO negation_expression",
+ "conditional_or_expression : conditional_and_expression",
+ "conditional_or_expression : conditional_or_expression OR conditional_and_expression",
+ "conditional_or_expression : conditional_or_expression ORELSE conditional_and_expression",
+ "conditional_xor_expression : conditional_or_expression",
+ "conditional_xor_expression : conditional_xor_expression XOR conditional_or_expression",
+ "assignment_expression : prefixed_unary_expression ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression STAR ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression DIV ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression PLUS ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression MINUS ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression OP_CONCAT ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression OP_EXP ASSIGN expression",
+ "assignment_expression : prefixed_unary_expression ASSIGN ADDRESSOF expression",
+ "constant_expression : expression",
+ "boolean_expression : expression",
+ "type : namespace_or_type_name",
+ "type : builtin_types",
+ "type_list : type",
+ "type_list : type_list COMMA type",
+ "namespace_or_type_name : qualified_identifier",
+ "builtin_types : OBJECT",
+ "builtin_types : primitive_type",
+ "primitive_type : numeric_type",
+ "primitive_type : BOOLEAN",
+ "primitive_type : CHAR",
+ "primitive_type : STRING",
+ "numeric_type : integral_type",
+ "numeric_type : floating_point_type",
+ "numeric_type : DECIMAL",
+ "integral_type :",
+ "integral_type : BYTE",
+ "integral_type : SHORT",
+ "integral_type : INTEGER",
+ "integral_type : LONG",
+ "floating_point_type : SINGLE",
+ "floating_point_type : DOUBLE",
+ "pp_directive : HASH IDENTIFIER OPEN_PARENS LITERAL_STRING COMMA LITERAL_INTEGER CLOSE_PARENS EOL",
+ "pp_directive : HASH IDENTIFIER LITERAL_STRING EOL",
+ "pp_directive : HASH END IDENTIFIER EOL",
+ "pp_directive : HASH CONST IDENTIFIER ASSIGN boolean_literal EOL",
+ "$$30 :",
+ "pp_directive : HASH IF $$30 boolean_literal opt_then EOL",
+ "$$31 :",
+ "pp_directive : HASH ELSEIF $$31 boolean_literal opt_then EOL",
+ "$$32 :",
+ "pp_directive : HASH ELSE $$32 EOL",
+ "$$33 :",
+ "pp_directive : HASH END IF $$33 EOL",
+ "pp_directive : HASH error EOL",
+ };
+ protected static string [] yyNames = {
+ "end-of-file",null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,"'!'",null,"'#'","'$'","'%'","'&'",
+ null,"'('","')'","'*'","'+'","','","'-'","'.'","'/'",null,null,null,
+ null,null,null,null,null,null,null,"':'",null,"'<'","'='","'>'","'?'",
+ "'@'",null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ "'['","'\\\\'","']'","'^'",null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,"'{'",null,"'}'",null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,null,null,null,null,null,null,null,null,null,null,null,null,null,
+ null,"EOF","NONE","ERROR","ADDHANDLER","ADDRESSOF","ALIAS","AND",
+ "ANDALSO","ANSI","AS","ASSEMBLY","AUTO","BINARY","BOOLEAN","BYREF",
+ "BYTE","BYVAL","CALL","CASE","CATCH","CBOOL","CBYTE","CCHAR","CDATE",
+ "CDEC","CDBL","CHAR","CINT","CLASS","CLNG","COBJ","COMPARE","CONST",
+ "CSHORT","CSNG","CSTR","CTYPE","DATE","DECIMAL","DECLARE","DEFAULT",
+ "DELEGATE","DIM","DIRECTCAST","DO","DOUBLE","EACH","ELSE","ELSEIF",
+ "END","ENDIF","ENUM","EOL","ERASE","EVENT","EXIT","EXPLICIT","FALSE",
+ "FINALLY","FOR","FRIEND","FUNCTION","GET","GETTYPE","GOSUB","GOTO",
+ "HANDLES","IF","IMPLEMENTS","IMPORTS","IN","INHERITS","INTEGER",
+ "INTERFACE","IS","LET","LIB","LIKE","LONG","LOOP","ME","MOD","MODULE",
+ "MUSTINHERIT","MUSTOVERRIDE","MYBASE","MYCLASS","NAMESPACE","NEW",
+ "NEXT","NOT","NOTHING","NOTINHERITABLE","NOTOVERRIDABLE","OBJECT",
+ "OFF","ON","OPTION","OPTIONAL","OR","ORELSE","OVERLOADS",
+ "OVERRIDABLE","OVERRIDES","PARAM_ARRAY","PRESERVE","PRIVATE",
+ "PROPERTY","PROTECTED","PUBLIC","RAISEEVENT","READONLY","REDIM","REM",
+ "REMOVEHANDLER","RESUME","RETURN","SELECT","SET","SHADOWS","SHARED",
+ "SHORT","SINGLE","SIZEOF","STATIC","STEP","STOP","STRICT","STRING",
+ "STRUCTURE","SUB","SYNCLOCK","TEXT","THEN","THROW","TO","TRUE","TRY",
+ "TYPEOF","UNICODE","UNTIL","VARIANT","WEND","WHEN","WHILE","WITH",
+ "WITHEVENTS","WRITEONLY","XOR","YIELD","HASH","OPEN_BRACKET",
+ "CLOSE_BRACKET","OPEN_PARENS","OPEN_BRACE","CLOSE_BRACE",
+ "CLOSE_PARENS","DOT","COMMA","COLON","PLUS","MINUS","ASSIGN","OP_LT",
+ "OP_GT","STAR","DIV","OP_EXP","INTERR","OP_IDIV","OP_CONCAT",
+ "EXCLAMATION","PERCENT","LONGTYPECHAR","AT_SIGN","SINGLETYPECHAR",
+ "NUMBER_SIGN","DOLAR_SIGN","ATTR_ASSIGN","\":=\"","OP_LE","\"<=\"",
+ "OP_GE","\">=\"","OP_NE","\"<>\"","OP_XOR","\"xor\"","OP_SHIFT_LEFT",
+ "\"<<\"","OP_SHIFT_RIGHT","\">>\"","LITERAL_INTEGER",
+ "\"int literal\"","LITERAL_SINGLE","\"float literal\"",
+ "LITERAL_DOUBLE","\"double literal\"","LITERAL_DECIMAL",
+ "\"decimal literal\"","LITERAL_CHARACTER","\"character literal\"",
+ "LITERAL_STRING","\"string literal\"","LITERAL_DATE",
+ "\"datetime literal\"","IDENTIFIER","LOWPREC","OP_OR","OP_AND",
+ "BITWISE_OR","BITWISE_AND","BITWISE_NOT","CARRET","UMINUS","OP_INC",
+ "OP_DEC","HIGHPREC","label_name",
+ };
+
+ /** index-checked interface to yyNames[].
+ @param token single character or %token value.
+ @return token name or [illegal] or [unknown].
+ */
+ public static string yyname (int token) {
+ if ((token < 0) || (token > yyNames.Length)) return "[illegal]";
+ string name;
+ if ((name = yyNames[token]) != null) return name;
+ return "[unknown]";
+ }
+
+ /** computes list of expected tokens on error by tracing the tables.
+ @param state for which to compute the list.
+ @return list of token names.
+ */
+ protected string[] yyExpecting (int state) {
+ int token, n, len = 0;
+ bool[] ok = new bool[yyNames.Length];
+
+ if ((n = yySindex[state]) != 0)
+ for (token = n < 0 ? -n : 0;
+ (token < yyNames.Length) && (n+token < yyTable.Length); ++ token)
+ if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) {
+ ++ len;
+ ok[token] = true;
+ }
+ if ((n = yyRindex[state]) != 0)
+ for (token = n < 0 ? -n : 0;
+ (token < yyNames.Length) && (n+token < yyTable.Length); ++ token)
+ if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) {
+ ++ len;
+ ok[token] = true;
+ }
+
+ string [] result = new string[len];
+ for (n = token = 0; n < len; ++ token)
+ if (ok[token]) result[n++] = yyNames[token];
+ return result;
+ }
+
+ /** the generated parser, with debugging messages.
+ Maintains a state and a value stack, currently with fixed maximum size.
+ @param yyLex scanner.
+ @param yydebug debug message writer implementing yyDebug, or null.
+ @return result of the last reduction, if any.
+ @throws yyException on irrecoverable parse error.
+ */
+ internal Object yyparse (yyParser.yyInput yyLex, Object yyd)
+ {
+ this.debug = (yydebug.yyDebug)yyd;
+ return yyparse(yyLex);
+ }
+
+ /** initial size and increment of the state/value stack [default 256].
+ This is not final so that it can be overwritten outside of invocations
+ of yyparse().
+ */
+ protected int yyMax;
+
+ /** executed at the beginning of a reduce action.
+ Used as $$ = yyDefault($1), prior to the user-specified action, if any.
+ Can be overwritten to provide deep copy, etc.
+ @param first value for $1, or null.
+ @return first.
+ */
+ protected Object yyDefault (Object first) {
+ return first;
+ }
+
+ /** the generated parser.
+ Maintains a state and a value stack, currently with fixed maximum size.
+ @param yyLex scanner.
+ @return result of the last reduction, if any.
+ @throws yyException on irrecoverable parse error.
+ */
+ internal Object yyparse (yyParser.yyInput yyLex)
+ {
+ if (yyMax <= 0) yyMax = 256; // initial size
+ int yyState = 0; // state stack ptr
+ int [] yyStates = new int[yyMax]; // state stack
+ Object yyVal = null; // value stack ptr
+ Object [] yyVals = new Object[yyMax]; // value stack
+ int yyToken = -1; // current input
+ int yyErrorFlag = 0; // #tks to shift
+
+ int yyTop = 0;
+ goto skip;
+ yyLoop:
+ yyTop++;
+ skip:
+ for (;; ++ yyTop) {
+ if (yyTop >= yyStates.Length) { // dynamically increase
+ int[] i = new int[yyStates.Length+yyMax];
+ yyStates.CopyTo (i, 0);
+ yyStates = i;
+ Object[] o = new Object[yyVals.Length+yyMax];
+ yyVals.CopyTo (o, 0);
+ yyVals = o;
+ }
+ yyStates[yyTop] = yyState;
+ yyVals[yyTop] = yyVal;
+ if (debug != null) debug.push(yyState, yyVal);
+
+ yyDiscarded: for (;;) { // discarding a token does not change stack
+ int yyN;
+ if ((yyN = yyDefRed[yyState]) == 0) { // else [default] reduce (yyN)
+ if (yyToken < 0) {
+ yyToken = yyLex.advance() ? yyLex.token() : 0;
+ if (debug != null)
+ debug.lex(yyState, yyToken, yyname(yyToken), yyLex.value());
+ }
+ if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0)
+ && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) {
+ if (debug != null)
+ debug.shift(yyState, yyTable[yyN], yyErrorFlag-1);
+ yyState = yyTable[yyN]; // shift to yyN
+ yyVal = yyLex.value();
+ yyToken = -1;
+ if (yyErrorFlag > 0) -- yyErrorFlag;
+ goto yyLoop;
+ }
+ if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0
+ && yyN < yyTable.Length && yyCheck[yyN] == yyToken)
+ yyN = yyTable[yyN]; // reduce (yyN)
+ else
+ switch (yyErrorFlag) {
+
+ case 0:
+ yyerror(String.Format ("syntax error, got token `{0}'", yyname (yyToken)), yyExpecting(yyState));
+ if (debug != null) debug.error("syntax error");
+ goto case 1;
+ case 1: case 2:
+ yyErrorFlag = 3;
+ do {
+ if ((yyN = yySindex[yyStates[yyTop]]) != 0
+ && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length
+ && yyCheck[yyN] == Token.yyErrorCode) {
+ if (debug != null)
+ debug.shift(yyStates[yyTop], yyTable[yyN], 3);
+ yyState = yyTable[yyN];
+ yyVal = yyLex.value();
+ goto yyLoop;
+ }
+ if (debug != null) debug.pop(yyStates[yyTop]);
+ } while (-- yyTop >= 0);
+ if (debug != null) debug.reject();
+ throw new yyParser.yyException("irrecoverable syntax error");
+
+ case 3:
+ if (yyToken == 0) {
+ if (debug != null) debug.reject();
+ throw new yyParser.yyException("irrecoverable syntax error at end-of-file");
+ }
+ if (debug != null)
+ debug.discard(yyState, yyToken, yyname(yyToken),
+ yyLex.value());
+ yyToken = -1;
+ goto yyDiscarded; // leave stack alone
+ }
+ }
+ int yyV = yyTop + 1-yyLen[yyN];
+ if (debug != null)
+ debug.reduce(yyState, yyStates[yyV-1], yyN, yyRule[yyN], yyLen[yyN]);
+ yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);
+ switch (yyN) {
+case 5:
+#line 753 "mb-parser.jay"
+ {
+ yyVal=yyVals[-1+yyTop];
+ }
+ break;
+case 6:
+#line 761 "mb-parser.jay"
+ {
+ /* ????? */ ;
+ }
+ break;
+case 14:
+#line 784 "mb-parser.jay"
+ {
+ yyVal = (object)true;
+ }
+ break;
+case 15:
+#line 788 "mb-parser.jay"
+ {
+ yyVal = (object)true;
+ }
+ break;
+case 16:
+#line 792 "mb-parser.jay"
+ {
+ yyVal = (object)false;
+ }
+ break;
+case 17:
+#line 799 "mb-parser.jay"
+ {
+ yyVal = (object)true;
+ }
+ break;
+case 18:
+#line 803 "mb-parser.jay"
+ {
+ yyVal = (object)false;
+ }
+ break;
+case 19:
+#line 810 "mb-parser.jay"
+ {
+/* if (!UseExtendedSyntax)*/
+/* OptionExplicit = (bool)$3;*/
+/* else*/
+/* Report.Warning (*/
+/* 9999, lexer.Location, */
+/* "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");*/
+ }
+ break;
+case 20:
+#line 823 "mb-parser.jay"
+ {
+/* if (!UseExtendedSyntax)*/
+/* OptionStrict = (bool)$3;*/
+/* else*/
+/* Report.Warning (*/
+/* 9999, lexer.Location, */
+/* "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");*/
+ }
+ break;
+case 21:
+#line 835 "mb-parser.jay"
+ {
+/* OptionCompareBinary = (bool)$3;*/
+ }
+ break;
+case 26:
+#line 852 "mb-parser.jay"
+ {
+/* FIXME: Need to check declaration qualifiers for multi-file compilation*/
+/* FIXME: Qualifiers cannot be applied to namespaces*/
+ allow_global_attribs = false;
+ }
+ break;
+case 27:
+#line 858 "mb-parser.jay"
+ {
+ current_namespace.DeclarationFound = true;
+ }
+ break;
+case 28:
+#line 862 "mb-parser.jay"
+ {
+ /* FIXME: Need to check declaration qualifiers for multi-file compilation*/
+ allow_global_attribs = false;
+ }
+ break;
+case 29:
+#line 867 "mb-parser.jay"
+ {
+ string name = "";
+ int mod_flags;
+
+ if (yyVals[0+yyTop] is Class){
+ Class c = (Class) yyVals[0+yyTop];
+ mod_flags = c.ModFlags;
+ name = c.Name;
+ } else if (yyVals[0+yyTop] is Struct){
+ Struct s = (Struct) yyVals[0+yyTop];
+ 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;
+ }
+ break;
+case 36:
+#line 902 "mb-parser.jay"
+ { yyVal = TypeManager.system_int32_expr; }
+ break;
+case 37:
+#line 903 "mb-parser.jay"
+ { yyVal = TypeManager.system_int64_expr; }
+ break;
+case 38:
+#line 904 "mb-parser.jay"
+ { yyVal = TypeManager.system_decimal_expr; }
+ break;
+case 39:
+#line 905 "mb-parser.jay"
+ { yyVal = TypeManager.system_single_expr; }
+ break;
+case 40:
+#line 906 "mb-parser.jay"
+ { yyVal = TypeManager.system_double_expr; }
+ break;
+case 41:
+#line 907 "mb-parser.jay"
+ { yyVal = TypeManager.system_string_expr; }
+ break;
+case 42:
+#line 911 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 43:
+#line 912 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 44:
+#line 918 "mb-parser.jay"
+ {
+ yyVal = new MemberName ((string) yyVals[0+yyTop]);
+ }
+ break;
+case 45:
+#line 922 "mb-parser.jay"
+ {
+ yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], (string) yyVals[0+yyTop], null);
+ }
+ break;
+case 53:
+#line 948 "mb-parser.jay"
+ {
+ string name = ((MemberName) yyVals[0+yyTop]).GetName ();
+ current_namespace.Using (name, lexer.Location);
+ }
+ break;
+case 54:
+#line 953 "mb-parser.jay"
+ {
+ current_namespace.UsingAlias ((string) yyVals[-2+yyTop], (MemberName) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 55:
+#line 960 "mb-parser.jay"
+ { yyVal = Parameters.EmptyReadOnlyParameters; }
+ break;
+case 56:
+#line 961 "mb-parser.jay"
+ { yyVal = Parameters.EmptyReadOnlyParameters; }
+ break;
+case 57:
+#line 962 "mb-parser.jay"
+ { yyVal = yyVals[-1+yyTop]; }
+ break;
+case 58:
+#line 967 "mb-parser.jay"
+ {
+ current_attributes = null;
+ }
+ break;
+case 59:
+#line 971 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ local_attrib_section_added = false;
+ current_attributes = (Attributes) yyVals[0+yyTop];
+ }
+ break;
+case 60:
+#line 980 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ if (yyVals[0+yyTop] == null) {
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ local_attrib_section_added = true;
+ allow_global_attribs = false;
+
+ yyVal = new Attributes ((ArrayList) yyVals[0+yyTop]);
+ }
+
+ if (expecting_global_attribs) {
+ yyVal = null;
+ CodeGen.AddGlobalAttributes ((ArrayList) yyVals[0+yyTop]);
+ }
+
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ }
+ break;
+case 61:
+#line 1004 "mb-parser.jay"
+ {
+ yyVal = lexer.Location;
+ }
+ break;
+case 62:
+#line 1008 "mb-parser.jay"
+ {
+ yyVal = yyVals[-2+yyTop];
+ if (yyVals[0+yyTop] != null) {
+ ArrayList attrs = (ArrayList) yyVals[0+yyTop];
+
+ if (expecting_local_attribs) {
+ if (local_attrib_section_added) {
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ Report.Error (30205, (Location) yyVals[-1+yyTop], "Multiple attribute sections may not be used; Coalesce multiple attribute sections in to a single attribute section");
+ break;
+ }
+
+ if (yyVals[-2+yyTop] == null)
+ yyVal = new Attributes (attrs);
+ else
+ ((Attributes) yyVals[-2+yyTop]).AddAttributes (attrs);
+
+ local_attrib_section_added = true;
+ allow_global_attribs = false;
+ }
+
+ if (expecting_global_attribs) {
+ yyVal = null;
+ CodeGen.AddGlobalAttributes ((ArrayList) yyVals[0+yyTop]);
+ }
+ }
+
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ }
+ break;
+case 63:
+#line 1043 "mb-parser.jay"
+ {
+ yyVal = null;
+ if (yyVals[-2+yyTop] != null) {
+ if (expecting_global_attribs && !(bool) yyVals[0+yyTop]) {
+ Report.Error (30205, lexer.Location, "End of statement expected");
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ if ((bool) yyVals[0+yyTop]) {
+ Report.Error (32035, lexer.Location, "Use a line continuation after the attribute specifier to apply it to the following statement.");
+ break;
+ }
+ }
+
+ yyVal = yyVals[-2+yyTop];
+ }
+ }
+ break;
+case 64:
+#line 1064 "mb-parser.jay"
+ { yyVal = false; }
+ break;
+case 65:
+#line 1065 "mb-parser.jay"
+ { yyVal = true; }
+ break;
+case 66:
+#line 1070 "mb-parser.jay"
+ {
+ ArrayList attrs = null;
+ if (yyVals[0+yyTop] != null) {
+ attrs = new ArrayList ();
+ attrs.Add (yyVals[0+yyTop]);
+ }
+ yyVal = attrs;
+ }
+ break;
+case 67:
+#line 1079 "mb-parser.jay"
+ {
+ ArrayList attrs = null;
+
+ if (yyVals[0+yyTop] != null) {
+ attrs = (yyVals[-2+yyTop] == null) ? new ArrayList () : (ArrayList) yyVals[-2+yyTop];
+ attrs.Add (yyVals[0+yyTop]);
+ }
+
+ yyVal = attrs;
+ }
+ break;
+case 68:
+#line 1093 "mb-parser.jay"
+ {
+ yyVal = lexer.Location;
+ }
+ break;
+case 69:
+#line 1097 "mb-parser.jay"
+ {
+ yyVal = null;
+
+ if (expecting_global_attribs)
+ Report.Error (32015, (Location) yyVals[-1+yyTop], "Expecting Assembly or Module attribute specifiers");
+ else {
+ expecting_local_attribs = true;
+ MemberName mname = (MemberName) yyVals[-2+yyTop];
+ string name = mname.GetName ();
+
+ yyVal = new Attribute (null, name, (ArrayList) yyVals[0+yyTop],
+ (Location) yyVals[-1+yyTop]);
+ }
+ }
+ break;
+case 70:
+#line 1112 "mb-parser.jay"
+ {
+ yyVal = lexer.Location;
+ }
+ break;
+case 71:
+#line 1117 "mb-parser.jay"
+ {
+ yyVal = lexer.Location;
+ }
+ break;
+case 72:
+#line 1121 "mb-parser.jay"
+ {
+ yyVal = null;
+
+ string attribute_target = (string) yyVals[-5+yyTop];
+ if (attribute_target != "assembly" && attribute_target != "module") {
+ Report.Error (29999, lexer.Location, "`" + (string)yyVals[-5+yyTop] + "' is an invalid attribute modifier");
+ break;
+ }
+ if (!allow_global_attribs) {
+ Report.Error (30637, (Location) yyVals[-4+yyTop], "Global attribute statements must precede any declarations in a file");
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ Report.Error (30183, (Location) yyVals[-4+yyTop], "Global attributes cannot be combined with local attributes");
+ break;
+ }
+
+ expecting_global_attribs = true;
+
+ MemberName mname = (MemberName) yyVals[-2+yyTop];
+ string aname = mname.GetName ();
+
+ yyVal = new Attribute (attribute_target, aname, (ArrayList) yyVals[0+yyTop], (Location) yyVals[-1+yyTop]);
+ }
+ break;
+case 73:
+#line 1150 "mb-parser.jay"
+ { yyVal = "assembly"; }
+ break;
+case 74:
+#line 1151 "mb-parser.jay"
+ { yyVal = "module"; }
+ break;
+case 76:
+#line 1157 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 77:
+#line 1159 "mb-parser.jay"
+ {
+ yyVal = yyVals[-1+yyTop];
+ }
+ break;
+case 80:
+#line 1171 "mb-parser.jay"
+ {
+ ArrayList args = new ArrayList (4);
+ args.Add (yyVals[0+yyTop]);
+
+ yyVal = args;
+ }
+ break;
+case 81:
+#line 1178 "mb-parser.jay"
+ {
+ ArrayList args = new ArrayList (4);
+ args.Add (yyVals[-2+yyTop]);
+ args.Add (yyVals[0+yyTop]);
+
+ yyVal = args;
+ }
+ break;
+case 82:
+#line 1186 "mb-parser.jay"
+ {
+ ArrayList args = new ArrayList (4);
+ args.Add (null);
+ args.Add (yyVals[0+yyTop]);
+
+ yyVal = args;
+ }
+ break;
+case 83:
+#line 1197 "mb-parser.jay"
+ {
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Expression));
+
+ yyVal = args;
+ }
+ break;
+case 84:
+#line 1204 "mb-parser.jay"
+ {
+ ArrayList args = (ArrayList) yyVals[-2+yyTop];
+ args.Add (new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Expression));
+
+ yyVal = args;
+ }
+ break;
+case 85:
+#line 1214 "mb-parser.jay"
+ {
+ ArrayList args = new ArrayList ();
+ args.Add (yyVals[0+yyTop]);
+
+ yyVal = args;
+ }
+ break;
+case 86:
+#line 1221 "mb-parser.jay"
+ {
+ ArrayList args = (ArrayList) yyVals[-2+yyTop];
+ args.Add (yyVals[0+yyTop]);
+
+ yyVal = args;
+ }
+ break;
+case 87:
+#line 1231 "mb-parser.jay"
+ {
+ yyVal = new DictionaryEntry (
+ (string) yyVals[-2+yyTop],
+ new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Expression));
+ }
+ break;
+case 88:
+#line 1240 "mb-parser.jay"
+ {
+ if (current_attributes != null) {
+ Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces."
+ + " Expected class, delegate, enum, interface, or struct");
+ }
+
+ MemberName name = (MemberName) yyVals[-1+yyTop];
+
+ if ((current_namespace.Parent != null) && (name.Left != null)) {
+ Report.Error (134, lexer.Location,
+ "Cannot use qualified namespace names in nested " +
+ "namespace declarations");
+ }
+
+ current_namespace = new NamespaceEntry (
+ current_namespace, file, name.GetName (), lexer.Location);
+ }
+ break;
+case 89:
+#line 1259 "mb-parser.jay"
+ {
+ current_namespace = current_namespace.Parent;
+ }
+ break;
+case 97:
+#line 1280 "mb-parser.jay"
+ {
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ MemberName name = MakeName (new MemberName ((string) yyVals[-1+yyTop]));
+ int mod_flags = current_modifiers;
+
+
+ current_class = new Class (current_namespace, current_container, name,
+ mod_flags, (Attributes) current_attributes, lexer.Location);
+
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+ }
+ break;
+case 98:
+#line 1297 "mb-parser.jay"
+ {
+ ArrayList bases = (ArrayList) yyVals[-1+yyTop];
+ ArrayList ifaces = (ArrayList) yyVals[0+yyTop];
+
+ if (ifaces != null){
+ if (bases != null)
+ bases.AddRange(ifaces);
+ else
+ bases = ifaces;
+ }
+
+ if (bases != null) {
+ if (current_class.Name == "System.Object") {
+ Report.Error (537, current_class.Location,
+ "The class System.Object cannot have a base " +
+ "class or implement an interface.");
+ }
+ current_class.Bases = (ArrayList) bases;
+ }
+
+ current_class.Register ();
+ }
+ break;
+case 99:
+#line 1321 "mb-parser.jay"
+ {
+ yyVal = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ break;
+case 100:
+#line 1330 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 101:
+#line 1331 "mb-parser.jay"
+ { yyVal = yyVals[-1+yyTop]; }
+ break;
+case 102:
+#line 1335 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 103:
+#line 1336 "mb-parser.jay"
+ { yyVal = yyVals[-1+yyTop]; }
+ break;
+case 104:
+#line 1341 "mb-parser.jay"
+ {
+ yyVal = (int) 0;
+ current_modifiers = 0;
+ }
+ break;
+case 105:
+#line 1346 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ current_modifiers = (int) yyVals[0+yyTop];
+ }
+ break;
+case 107:
+#line 1355 "mb-parser.jay"
+ {
+ int m1 = (int) yyVals[-1+yyTop];
+ int m2 = (int) yyVals[0+yyTop];
+
+ if ((m1 & m2) != 0) {
+ Location l = lexer.Location;
+ Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
+ }
+ yyVal = (int) (m1 | m2);
+ }
+ break;
+case 108:
+#line 1368 "mb-parser.jay"
+ { yyVal = Modifiers.PUBLIC; }
+ break;
+case 109:
+#line 1369 "mb-parser.jay"
+ { yyVal = Modifiers.PROTECTED; }
+ break;
+case 110:
+#line 1370 "mb-parser.jay"
+ { yyVal = Modifiers.PRIVATE; }
+ break;
+case 111:
+#line 1371 "mb-parser.jay"
+ { yyVal = Modifiers.STATIC; }
+ break;
+case 112:
+#line 1372 "mb-parser.jay"
+ { yyVal = Modifiers.INTERNAL; }
+ break;
+case 113:
+#line 1373 "mb-parser.jay"
+ { yyVal = Modifiers.SEALED; }
+ break;
+case 114:
+#line 1374 "mb-parser.jay"
+ { yyVal = Modifiers.VIRTUAL; }
+ break;
+case 115:
+#line 1375 "mb-parser.jay"
+ { yyVal = Modifiers.NONVIRTUAL; }
+ break;
+case 116:
+#line 1376 "mb-parser.jay"
+ { yyVal = Modifiers.OVERRIDE; }
+ break;
+case 117:
+#line 1377 "mb-parser.jay"
+ { yyVal = Modifiers.NEW; }
+ break;
+case 118:
+#line 1378 "mb-parser.jay"
+ { yyVal = Modifiers.SHADOWS; }
+ break;
+case 119:
+#line 1379 "mb-parser.jay"
+ { yyVal = Modifiers.ABSTRACT; }
+ break;
+case 120:
+#line 1380 "mb-parser.jay"
+ { yyVal = Modifiers.READONLY; }
+ break;
+case 121:
+#line 1381 "mb-parser.jay"
+ { yyVal = Modifiers.DEFAULT; }
+ break;
+case 122:
+#line 1382 "mb-parser.jay"
+ { yyVal = Modifiers.WRITEONLY; }
+ break;
+case 123:
+#line 1387 "mb-parser.jay"
+ {
+ MemberName name = MakeName(new MemberName ((string) yyVals[-1+yyTop]));
+ current_class = new VBModule (current_namespace, current_container, name,
+ current_modifiers, current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl(name.GetName (true), current_class);
+
+ current_class.Register ();
+ }
+ break;
+case 124:
+#line 1399 "mb-parser.jay"
+ {
+ yyVal = current_class;
+/* FIXME: ?????*/
+/* TypeManager.AddStandardModule (current_class);*/
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ break;
+case 129:
+#line 1422 "mb-parser.jay"
+ {
+ current_modifiers = ((int)yyVals[0+yyTop]) | Modifiers.STATIC;
+ bool explicit_static = (((int) yyVals[0+yyTop] & Modifiers.STATIC) > 0);
+ implicit_modifiers = (!explicit_static);
+ }
+ break;
+case 130:
+#line 1429 "mb-parser.jay"
+ {
+ implicit_modifiers = false;
+ yyVal = yyVals[-1+yyTop];
+ }
+ break;
+case 138:
+#line 1449 "mb-parser.jay"
+ {
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ int modflags = (int) current_modifiers;
+
+ /* Structure members are Public by default */
+ if ((current_container is Struct) && (modflags == 0))
+ modflags = Modifiers.PUBLIC;
+
+ ArrayList consts = (ArrayList) yyVals[-1+yyTop];
+ if(consts.Count > 0)
+ {
+ VariableDeclaration.FixupTypes ((ArrayList) yyVals[-1+yyTop]);
+ VariableDeclaration.FixupArrayTypes ((ArrayList) yyVals[-1+yyTop]);
+
+ foreach (VariableDeclaration constant in (ArrayList) yyVals[-1+yyTop]){
+ Location l = constant.Location;
+ Const c = new Const (current_class,
+ (Expression) constant.type,
+ (String) constant.identifier,
+ (Expression) constant.expression_or_array_initializer,
+ modflags, current_attributes, l);
+
+ current_container.AddConstant (c);
+ }
+ }
+ }
+ break;
+case 143:
+#line 1493 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 153:
+#line 1571 "mb-parser.jay"
+ {
+ MemberName name = new MemberName ((string) yyVals[-1+yyTop]);
+
+ if ((current_container is Struct) && (current_modifiers == 0))
+ current_modifiers = Modifiers.PUBLIC;
+
+
+ GenericMethod generic = null;
+ Method method = new Method (current_class, generic, TypeManager.system_void_expr,
+ (int) current_modifiers, false, name,
+ (Parameters) yyVals[0+yyTop], (Attributes) current_attributes,
+ lexer.Location);
+
+ current_local_parameters = (Parameters) yyVals[0+yyTop];
+ yyVal = method;
+
+ iterator_container = (IIteratorContainer) method;
+ }
+ break;
+case 154:
+#line 1595 "mb-parser.jay"
+ {
+ Method method = (Method) yyVals[-9+yyTop];
+ Block b = (Block) yyVals[-3+yyTop];
+ 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 = (ToplevelBlock) yyVals[-3+yyTop];
+ current_container.AddMethod (method);
+
+ current_local_parameters = null;
+ iterator_container = null;
+ }
+ break;
+case 155:
+#line 1625 "mb-parser.jay"
+ {
+ MemberName name = new MemberName ((string) yyVals[-3+yyTop]);
+ Expression rettype = (yyVals[0+yyTop] == null) ? ((yyVals[-2+yyTop] == null) ? TypeManager.system_object_expr : (Expression) yyVals[-2+yyTop] ) : (Expression) yyVals[0+yyTop];
+
+ GenericMethod generic = null;
+
+ Method method = new Method (current_class, generic, rettype, current_modifiers,
+ false, name, (Parameters) yyVals[-1+yyTop], current_attributes,
+ lexer.Location);
+
+ current_local_parameters = (Parameters) yyVals[-1+yyTop];
+
+ yyVal = method;
+ iterator_container = method;
+ }
+ break;
+case 156:
+#line 1643 "mb-parser.jay"
+ {
+ Method method = (Method) yyVals[-3+yyTop];
+
+ ArrayList retval = new ArrayList ();
+ retval.Add (new VariableDeclaration ((string) yyVals[-7+yyTop], method.Type, lexer.Location));
+ declare_local_variables (method.Type, retval, lexer.Location);
+ }
+ break;
+case 157:
+#line 1653 "mb-parser.jay"
+ {
+ Method method = (Method) yyVals[-9+yyTop];
+ Block b = (Block) yyVals[-3+yyTop];
+ 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 = (ToplevelBlock) b;
+ current_container.AddMethod (method);
+
+ current_local_parameters = null;
+ iterator_container = null;
+ }
+ break;
+case 158:
+#line 1683 "mb-parser.jay"
+ {
+ MemberName name = MakeName (new MemberName ((string) yyVals[-2+yyTop]));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ current_class = new Struct (current_namespace, current_container, name, current_modifiers,
+ current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+
+ if (yyVals[0+yyTop] != null)
+ current_class.Bases = (ArrayList) yyVals[0+yyTop];
+
+ current_class.Register ();
+ }
+ break;
+case 159:
+#line 1701 "mb-parser.jay"
+ {
+ yyVal = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ break;
+case 174:
+#line 1806 "mb-parser.jay"
+ {
+ VariableDeclaration var = new VariableDeclaration ((string) yyVals[-4+yyTop], (Expression) yyVals[-2+yyTop], lexer.Location);
+
+ MemberName name = new MemberName ((string) yyVals[-4+yyTop]);
+
+ Event e = new EventField (current_class, (Expression) yyVals[-2+yyTop], current_modifiers, false, name,
+ var.expression_or_array_initializer, current_attributes,
+ lexer.Location);
+
+ current_container.AddEvent (e);
+ }
+ break;
+case 175:
+#line 1860 "mb-parser.jay"
+ {
+ Location enum_location = lexer.Location;
+
+ Expression base_type = TypeManager.system_int32_expr;
+ if ((Expression) yyVals[-2+yyTop] != null)
+ base_type = (Expression) yyVals[-2+yyTop];
+
+ ArrayList enum_members = (ArrayList) yyVals[0+yyTop];
+ if (enum_members.Count == 0)
+ Report.Error (30280, enum_location,
+ "Enum can not have empty member list");
+
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ MemberName full_name = MakeName (new MemberName ((string) yyVals[-3+yyTop]));
+ Enum e = new Enum (current_namespace, current_container, base_type,
+ (int) current_modifiers, full_name,
+ (Attributes) current_attributes, enum_location);
+
+ foreach (VariableDeclaration ev in (ArrayList) yyVals[0+yyTop]) {
+ e.AddEnumMember (ev.identifier,
+ (Expression) ev.expression_or_array_initializer,
+ ev.Location, ev.OptAttributes, ev.DocComment);
+ }
+
+ string name = full_name.GetName ();
+ current_container.AddEnum (e);
+ RootContext.Tree.RecordDecl (name, e);
+
+ }
+ break;
+case 177:
+#line 1896 "mb-parser.jay"
+ { yyVal = new ArrayList (4); }
+ break;
+case 178:
+#line 1897 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 179:
+#line 1902 "mb-parser.jay"
+ {
+ ArrayList l = new ArrayList ();
+
+ l.Add (yyVals[0+yyTop]);
+ yyVal = l;
+ }
+ break;
+case 180:
+#line 1909 "mb-parser.jay"
+ {
+ ArrayList l = (ArrayList) yyVals[-1+yyTop];
+
+ l.Add (yyVals[0+yyTop]);
+
+ yyVal = l;
+ }
+ break;
+case 181:
+#line 1920 "mb-parser.jay"
+ {
+ yyVal = new VariableDeclaration ((string) yyVals[-1+yyTop], null, lexer.Location, (Attributes) yyVals[-2+yyTop]);
+ }
+ break;
+case 182:
+#line 1924 "mb-parser.jay"
+ {
+ yyVal = lexer.Location;
+ }
+ break;
+case 183:
+#line 1928 "mb-parser.jay"
+ {
+ yyVal = new VariableDeclaration ((string) yyVals[-4+yyTop], yyVals[-1+yyTop], lexer.Location, (Attributes) yyVals[-5+yyTop]);
+ }
+ break;
+case 184:
+#line 2019 "mb-parser.jay"
+ {
+ get_implicit_value_parameter_type =
+ (yyVals[-1+yyTop] == null) ? ((yyVals[-3+yyTop] == null) ?
+ TypeManager.system_object_expr : (Expression) yyVals[-3+yyTop] ) : (Expression) yyVals[-1+yyTop];
+
+ current_local_parameters = (Parameters) yyVals[-2+yyTop];
+ if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+ get_parameters = current_local_parameters.Copy (lexer.Location);
+ set_parameters = current_local_parameters.Copy (lexer.Location);
+
+ Parameter implicit_value_parameter = new Parameter (
+ get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ }
+ else
+ {
+ get_parameters = Parameters.EmptyReadOnlyParameters;
+ set_parameters = new Parameters (null, null ,lexer.Location);
+
+ Parameter implicit_value_parameter = new Parameter (
+ get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ }
+ lexer.PropertyParsing = true;
+
+ Location loc = lexer.Location;
+ MemberName name = new MemberName ((string) yyVals[-4+yyTop]);
+
+ Accessor get_block = new Accessor (null, 0, null, loc);
+ Accessor set_block = new Accessor (null, 0, null, loc);
+
+ Property prop = new Property (current_class, get_implicit_value_parameter_type,
+ (int) current_modifiers, true,
+ name, current_attributes,
+ get_parameters, get_block,
+ set_parameters, set_block, lexer.Location);
+
+ current_container.AddProperty (prop);
+
+ get_implicit_value_parameter_type = null;
+ set_implicit_value_parameter_type = null;
+ get_parameters = null;
+ set_parameters = null;
+ current_local_parameters = null;
+ }
+ break;
+case 185:
+#line 2105 "mb-parser.jay"
+ {
+ MemberName name = new MemberName ((string) yyVals[-1+yyTop]);
+
+ current_class = new Interface (current_namespace, current_container,
+ name, (int) current_modifiers,
+ (Attributes) current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+
+ }
+ break;
+case 186:
+#line 2117 "mb-parser.jay"
+ {
+ current_class.Bases = (ArrayList) yyVals[0+yyTop];
+ current_class.Register ();
+ }
+ break;
+case 187:
+#line 2122 "mb-parser.jay"
+ {
+ yyVal = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ break;
+case 189:
+#line 2132 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 190:
+#line 2133 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 192:
+#line 2139 "mb-parser.jay"
+ {
+ ArrayList bases = (ArrayList) yyVals[-1+yyTop];
+ bases.AddRange ((ArrayList) yyVals[0+yyTop]);
+ yyVal = bases;
+ }
+ break;
+case 193:
+#line 2147 "mb-parser.jay"
+ { yyVal = yyVals[-1+yyTop]; }
+ break;
+case 200:
+#line 2170 "mb-parser.jay"
+ {
+ Method m = (Method) yyVals[0+yyTop];
+
+ current_container.AddMethod (m);
+ }
+ break;
+case 202:
+#line 2181 "mb-parser.jay"
+ {
+ MemberName name = (MemberName) new MemberName ((string) yyVals[-2+yyTop]);
+
+ GenericMethod generic = null;
+
+ yyVal = new Method (current_class, generic, TypeManager.system_void_expr,
+ (int) current_modifiers, true, name, (Parameters) yyVals[-1+yyTop],
+ (Attributes) current_attributes, lexer.Location);
+ }
+ break;
+case 203:
+#line 2192 "mb-parser.jay"
+ {
+ MemberName name = new MemberName ((string) yyVals[-4+yyTop]);
+ Expression return_type = (yyVals[-1+yyTop] == null) ?
+ ((yyVals[-3+yyTop] == null) ? TypeManager.system_object_expr : (Expression) yyVals[-3+yyTop] )
+ : (Expression) yyVals[-1+yyTop];
+
+ GenericMethod generic = null;
+ yyVal = new Method (current_class, generic, return_type, (int) current_modifiers,
+ true, name, (Parameters) yyVals[-2+yyTop], (Attributes) current_attributes,
+ lexer.Location);
+ }
+ break;
+case 205:
+#line 2268 "mb-parser.jay"
+ {
+ get_implicit_value_parameter_type =
+ (yyVals[-2+yyTop] == null) ? ((yyVals[-4+yyTop] == null) ?
+ TypeManager.system_object_expr : (Expression) yyVals[-4+yyTop] ) : (Expression) yyVals[-2+yyTop];
+ get_implicit_value_parameter_name = (string) yyVals[-5+yyTop];
+
+ current_local_parameters = (Parameters) yyVals[-3+yyTop];
+ if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+ get_parameters = current_local_parameters.Copy (lexer.Location);
+ set_parameters = current_local_parameters.Copy (lexer.Location);
+ }
+ else
+ {
+ get_parameters = Parameters.EmptyReadOnlyParameters;
+ set_parameters = new Parameters (null, null ,lexer.Location);
+ }
+ lexer.PropertyParsing = true;
+
+ yyVal = lexer.Location;
+ }
+ break;
+case 206:
+#line 2290 "mb-parser.jay"
+ {
+ lexer.PropertyParsing = false;
+
+ Property prop;
+ Pair pair = (Pair) yyVals[-3+yyTop];
+
+ Accessor get_block = (Accessor) pair.First;
+ Accessor set_block = (Accessor) pair.Second;
+
+ Location loc = lexer.Location;
+ MemberName name = new MemberName ((string) yyVals[-10+yyTop]);
+
+ /* FIXME: Implements Clause needs to be taken care of.*/
+
+ if ((current_container is Struct) && (current_modifiers == 0))
+ current_modifiers = Modifiers.PUBLIC;
+
+
+ prop = new Property (current_class, get_implicit_value_parameter_type,
+ (int) current_modifiers, false,
+ name, (Attributes) current_attributes,
+ get_parameters, get_block,
+ set_parameters, set_block, lexer.Location);
+
+ current_container.AddProperty (prop);
+ get_implicit_value_parameter_type = null;
+ set_implicit_value_parameter_type = null;
+ get_parameters = null;
+ set_parameters = null;
+ current_local_parameters = null;
+ }
+ break;
+case 207:
+#line 2325 "mb-parser.jay"
+ {
+ yyVal = Parameters.EmptyReadOnlyParameters;
+ }
+ break;
+case 208:
+#line 2329 "mb-parser.jay"
+ {
+ yyVal = yyVals[-1+yyTop];
+ }
+ break;
+case 209:
+#line 2336 "mb-parser.jay"
+ {
+ yyVal = null;
+ }
+ break;
+case 210:
+#line 2340 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 211:
+#line 2347 "mb-parser.jay"
+ {
+ MemberName mname = (MemberName) yyVals[0+yyTop];
+ ArrayList impl_list = new ArrayList ();
+ impl_list.Add (mname.GetTypeExpression (lexer.Location));
+ yyVal = impl_list;
+ }
+ break;
+case 212:
+#line 2354 "mb-parser.jay"
+ {
+ MemberName mname = (MemberName) yyVals[0+yyTop];
+ ArrayList impl_list = (ArrayList) yyVals[-2+yyTop];
+ impl_list.Add (mname.GetTypeExpression (lexer.Location));
+ yyVal = impl_list;
+ }
+ break;
+case 213:
+#line 2364 "mb-parser.jay"
+ {
+ yyVal = new Pair (yyVals[-1+yyTop], yyVals[0+yyTop]);
+ }
+ break;
+case 214:
+#line 2368 "mb-parser.jay"
+ {
+ yyVal = new Pair (yyVals[0+yyTop], yyVals[-1+yyTop]);
+ }
+ break;
+case 215:
+#line 2374 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 217:
+#line 2379 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 219:
+#line 2385 "mb-parser.jay"
+ {
+ if ((current_modifiers & Modifiers.WRITEONLY) != 0)
+ Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor");
+
+ current_local_parameters = get_parameters;
+
+ lexer.PropertyParsing = false;
+
+ }
+ break;
+case 220:
+#line 2395 "mb-parser.jay"
+ {
+ ArrayList retval = new ArrayList ();
+ retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
+ declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
+ }
+ break;
+case 221:
+#line 2403 "mb-parser.jay"
+ {
+ yyVal = new Accessor ((ToplevelBlock) yyVals[-3+yyTop], (int) current_modifiers,
+ (Attributes) yyVals[-10+yyTop], lexer.Location);
+
+ current_local_parameters = null;
+ lexer.PropertyParsing = true;
+ }
+ break;
+case 222:
+#line 2416 "mb-parser.jay"
+ {
+ if ((current_modifiers & Modifiers.READONLY) != 0)
+ Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor");
+
+ Parameter implicit_value_parameter = new Parameter (
+ set_implicit_value_parameter_type,
+ set_implicit_value_parameter_name,
+ Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ current_local_parameters = set_parameters;
+
+ lexer.PropertyParsing = false;
+ }
+ break;
+case 223:
+#line 2434 "mb-parser.jay"
+ {
+ yyVal = new Accessor ((ToplevelBlock) yyVals[-3+yyTop], (int) current_modifiers,
+ (Attributes) yyVals[-10+yyTop], lexer.Location);
+ current_local_parameters = null;
+ lexer.PropertyParsing = true;
+ }
+ break;
+case 224:
+#line 2444 "mb-parser.jay"
+ {
+ set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; /* TypeManager.system_object_expr;*/
+ set_implicit_value_parameter_name = "Value";
+ }
+ break;
+case 225:
+#line 2449 "mb-parser.jay"
+ {
+ set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type;
+ set_implicit_value_parameter_name = "Value";
+ }
+ break;
+case 226:
+#line 2454 "mb-parser.jay"
+ {
+ Parameter.Modifier pm = (Parameter.Modifier)yyVals[-3+yyTop];
+ if ((pm | Parameter.Modifier.VAL) != 0)
+ Report.Error (31065,
+ lexer.Location,
+ "Set cannot have a paremeter modifier other than 'ByVal'");
+
+ set_implicit_value_parameter_type = (Expression) yyVals[-1+yyTop];
+
+ if (set_implicit_value_parameter_type.ToString () != get_implicit_value_parameter_type.ToString ())
+ Report.Error (31064,
+ lexer.Location,
+ "Set value parameter type can not be different from property type");
+
+ if (yyVals[-3+yyTop] != null)
+ set_implicit_value_parameter_name = (string) yyVals[-2+yyTop];
+ else
+ set_implicit_value_parameter_name = "Value";
+ }
+ break;
+case 227:
+#line 2478 "mb-parser.jay"
+ {
+ int mod = (int) current_modifiers;
+
+ VariableDeclaration.FixupTypes ((ArrayList) yyVals[-1+yyTop]);
+ VariableDeclaration.FixupArrayTypes ((ArrayList) yyVals[-1+yyTop]);
+
+/* if (current_container is Module)*/
+/* mod = mod | Modifiers.STATIC;*/
+
+ /* Structure members are Public by default */
+ if ((current_container is Struct) && (mod == 0))
+ mod = Modifiers.PUBLIC;
+
+ if ((mod & Modifiers.Accessibility) == 0)
+ mod |= Modifiers.PRIVATE;
+
+ foreach (VariableDeclaration var in (ArrayList) yyVals[-1+yyTop]){
+ Location l = var.Location;
+ Field field = new Field (current_class, var.type, mod,
+ var.identifier, var.expression_or_array_initializer,
+ (Attributes) null, l);
+
+ current_container.AddField (field);
+ }
+ }
+ break;
+case 230:
+#line 2555 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+ MemberName name = MakeName (new MemberName ((string) yyVals[-4+yyTop]));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ Delegate del = new Delegate (current_namespace, current_container, TypeManager.system_void_expr,
+ current_modifiers, name, (Parameters) yyVals[-2+yyTop], current_attributes, l);
+
+ current_container.AddDelegate (del);
+ RootContext.Tree.RecordDecl (name.GetName (true), del);
+ }
+ break;
+case 231:
+#line 2573 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+ MemberName name = MakeName (new MemberName ((string) yyVals[-5+yyTop]));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ Expression rettype = (yyVals[-1+yyTop] == null) ? TypeManager.system_object_expr : (Expression) yyVals[-1+yyTop];
+ Delegate del = new Delegate (current_namespace, current_container, rettype,
+ current_modifiers, name, (Parameters) yyVals[-3+yyTop], current_attributes, l);
+
+ current_container.AddDelegate (del);
+ RootContext.Tree.RecordDecl (name.GetName (true), del);
+ }
+ break;
+case 232:
+#line 2592 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 233:
+#line 2619 "mb-parser.jay"
+ {
+ current_local_parameters = (Parameters) yyVals[-1+yyTop];
+ yyVal = new Constructor (current_class, current_container.Basename, 0, (Parameters) yyVals[-1+yyTop],
+ (ConstructorInitializer) null, lexer.Location);
+ }
+ break;
+case 234:
+#line 2627 "mb-parser.jay"
+ {
+ Constructor c = (Constructor) yyVals[-3+yyTop];
+ c.Block = (ToplevelBlock) yyVals[0+yyTop];
+ c.ModFlags = (int) current_modifiers;
+ c.OptAttributes = current_attributes;
+
+ /* FIXME: Some more error checking from mcs needs to be merged here ???*/
+
+ c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
+
+ current_container.AddConstructor(c);
+ current_local_parameters = null;
+ }
+ break;
+case 236:
+#line 2645 "mb-parser.jay"
+ {
+ yyVal = Parameters.EmptyReadOnlyParameters;
+ }
+ break;
+case 237:
+#line 2649 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 238:
+#line 2656 "mb-parser.jay"
+ {
+ ArrayList pars_list = (ArrayList) yyVals[0+yyTop];
+ Parameter [] pars = null;
+ Parameter array_parameter = null;
+ int non_array_count = pars_list.Count;
+ if (pars_list.Count > 0 && (((Parameter) pars_list [pars_list.Count - 1]).ModFlags & Parameter.Modifier.PARAMS) != 0) {
+ array_parameter = (Parameter) pars_list [pars_list.Count - 1];
+ non_array_count = pars_list.Count - 1;
+ }
+ foreach (Parameter par in pars_list)
+ if (par != array_parameter && (par.ModFlags & Parameter.Modifier.PARAMS) != 0) {
+ Report.Error (30192, lexer.Location, "ParamArray parameters must be last");
+ non_array_count = 0;
+ array_parameter = null;
+ break;
+ }
+ if (non_array_count > 0) {
+ pars = new Parameter [non_array_count];
+ pars_list.CopyTo (0, pars, 0, non_array_count);
+ }
+ yyVal = new Parameters (pars, array_parameter, lexer.Location);
+ }
+ break;
+case 239:
+#line 2682 "mb-parser.jay"
+ {
+ ArrayList pars = new ArrayList ();
+
+ pars.Add (yyVals[0+yyTop]);
+ yyVal = pars;
+ }
+ break;
+case 240:
+#line 2689 "mb-parser.jay"
+ {
+ ArrayList pars = (ArrayList) yyVals[-2+yyTop];
+
+ pars.Add (yyVals[0+yyTop]);
+ yyVal = yyVals[-2+yyTop];
+ }
+ break;
+case 241:
+#line 2701 "mb-parser.jay"
+ {
+ Parameter.Modifier pm = (Parameter.Modifier)yyVals[-5+yyTop];
+ bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
+ Expression ptype;
+
+ if (opt_parm && (yyVals[0+yyTop] == null))
+ Report.Error (30812, lexer.Location, "Optional parameters must have a default value");
+
+ if (!opt_parm && (yyVals[0+yyTop] != null))
+ Report.Error (32024, lexer.Location, "Non-Optional parameters should not have a default value");
+
+ if ((pm & Parameter.Modifier.PARAMS) != 0) {
+ if ((pm & ~Parameter.Modifier.PARAMS) != 0)
+ Report.Error (30667, lexer.Location, "ParamArray parameters must be ByVal");
+ }
+
+ if ((pm & Parameter.Modifier.REF) !=0)
+ pm |= Parameter.Modifier.ISBYREF;
+
+ if (yyVals[-3+yyTop] != null && yyVals[-1+yyTop] != null && yyVals[-3+yyTop] != yyVals[-1+yyTop])
+ Report.Error (30302, lexer.Location, "Type character conflicts with declared type."); /* TODO: Correct error number and message text*/
+
+ ptype = (Expression)((yyVals[-1+yyTop] == null) ? ((yyVals[-3+yyTop] == null) ? TypeManager.system_object_expr : yyVals[-3+yyTop]) : yyVals[-1+yyTop]);
+ if (yyVals[-2+yyTop] != null) {
+ string t = ptype.ToString ();
+ if (t.IndexOf('[') >= 0)
+ Report.Error (31087, lexer.Location, "Array types specified in too many places");
+ else
+ ptype = DecomposeQI (t + VariableDeclaration.BuildRanks ((ArrayList) yyVals[-2+yyTop], true, lexer.Location), lexer.Location);
+ }
+ if ((pm & Parameter.Modifier.PARAMS) != 0 && ptype.ToString ().IndexOf('[') < 0)
+ Report.Error (30050, lexer.Location, "ParamArray parameters must be an array type");
+ yyVal = new Parameter (ptype, (string) yyVals[-4+yyTop], pm,
+ (Attributes) yyVals[-6+yyTop], (Expression) yyVals[0+yyTop], opt_parm);
+ }
+ break;
+case 242:
+#line 2739 "mb-parser.jay"
+ { yyVal = Parameter.Modifier.VAL; }
+ break;
+case 243:
+#line 2740 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 244:
+#line 2744 "mb-parser.jay"
+ { yyVal = (Parameter.Modifier)yyVals[-1+yyTop] | (Parameter.Modifier)yyVals[0+yyTop]; }
+ break;
+case 245:
+#line 2745 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 246:
+#line 2749 "mb-parser.jay"
+ { yyVal = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
+ break;
+case 247:
+#line 2750 "mb-parser.jay"
+ { yyVal = Parameter.Modifier.VAL; }
+ break;
+case 248:
+#line 2751 "mb-parser.jay"
+ { yyVal = Parameter.Modifier.OPTIONAL; }
+ break;
+case 249:
+#line 2752 "mb-parser.jay"
+ { yyVal = Parameter.Modifier.PARAMS; }
+ break;
+case 254:
+#line 2768 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 255:
+#line 2773 "mb-parser.jay"
+ {
+ if (current_block == null){
+ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location);
+ top_current_block = current_block;
+ } else {
+ current_block = new Block (current_block, current_local_parameters,
+ lexer.Location, Location.Null);
+ }
+ }
+ break;
+case 256:
+#line 2787 "mb-parser.jay"
+ {
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ yyVal = current_block;
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+ if (current_block == null)
+ top_current_block = null;
+ }
+ break;
+case 257:
+#line 2800 "mb-parser.jay"
+ {
+ if (yyVals[0+yyTop] != null && (Block) yyVals[0+yyTop] != current_block){
+ current_block.AddStatement ((Statement) yyVals[0+yyTop]);
+ current_block = (Block) yyVals[0+yyTop];
+ }
+ }
+ break;
+case 258:
+#line 2807 "mb-parser.jay"
+ {
+ Statement s = (Statement) yyVals[0+yyTop];
+
+ current_block.AddStatement ((Statement) yyVals[0+yyTop]);
+ }
+ break;
+case 259:
+#line 2814 "mb-parser.jay"
+ {
+ Location loc = lexer.Location;
+
+ ExpressionStatement expr = new CompoundAssign (Binary.Operator.Addition,
+ (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], loc);
+
+ Statement stmt = new StatementExpression (expr, loc);
+
+ current_block.AddStatement (stmt);
+
+ }
+ break;
+case 260:
+#line 2827 "mb-parser.jay"
+ {
+ Location loc = lexer.Location;
+
+ ExpressionStatement expr = new CompoundAssign (Binary.Operator.Subtraction,
+ (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], loc);
+
+ Statement stmt = new StatementExpression (expr, loc);
+
+ current_block.AddStatement (stmt);
+
+ }
+ break;
+case 261:
+#line 2839 "mb-parser.jay"
+ {
+ Location loc = lexer.Location;
+ MemberName mname = new MemberName ((string) yyVals[-1+yyTop]);
+ Expression expr = mname.GetTypeExpression (loc);
+
+ Invocation inv_expr = new Invocation (expr, (ArrayList) yyVals[0+yyTop], loc);
+ Statement stmt = new StatementExpression (inv_expr, loc);
+ current_block.AddStatement (stmt);
+ }
+ break;
+case 262:
+#line 2860 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 263:
+#line 2862 "mb-parser.jay"
+ {
+ yyVal = yyVals[-1+yyTop];
+ }
+ break;
+case 272:
+#line 3027 "mb-parser.jay"
+ {
+ yyVal = new Goto (current_block, (string) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 273:
+#line 3034 "mb-parser.jay"
+ {
+ yyVal = new Throw ((Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 274:
+#line 3059 "mb-parser.jay"
+ {
+ yyVal = new Return ((Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 275:
+#line 3185 "mb-parser.jay"
+ {
+ yyVal = new Lock ((Expression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], lexer.Location);
+ }
+ break;
+case 278:
+#line 3198 "mb-parser.jay"
+ {
+ Catch g = null;
+
+ ArrayList c = (ArrayList)yyVals[-2+yyTop];
+ for (int i = 0; i < c.Count; ++i) {
+ Catch cc = (Catch) c [i];
+ if (cc.IsGeneral) {
+ if (i != c.Count - 1)
+ Report.Error (1017, cc.loc, "Empty catch block must be the last in a series of catch blocks");
+ g = cc;
+ c.RemoveAt (i);
+ i--;
+ }
+ }
+
+ /* Now s contains the list of specific catch clauses*/
+ /* and g contains the general one.*/
+
+ yyVal = new Try ((Block) yyVals[-3+yyTop], c, g, null, ((Block) yyVals[-3+yyTop]).loc);
+ }
+ break;
+case 279:
+#line 3227 "mb-parser.jay"
+ {
+ Catch g = null;
+ ArrayList s = new ArrayList (4);
+ ArrayList catch_list = (ArrayList) yyVals[-5+yyTop];
+
+ if (catch_list != null){
+ foreach (Catch cc in catch_list) {
+ if (cc.IsGeneral)
+ g = cc;
+ else
+ s.Add (cc);
+ }
+ }
+
+ yyVal = new Try ((Block) yyVals[-6+yyTop], s, g, (Block) yyVals[-2+yyTop], ((Block) yyVals[-6+yyTop]).loc);
+ }
+ break;
+case 280:
+#line 3246 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 282:
+#line 3252 "mb-parser.jay"
+ {
+ ArrayList l = new ArrayList (4);
+
+ l.Add (yyVals[0+yyTop]);
+ yyVal = l;
+ }
+ break;
+case 283:
+#line 3259 "mb-parser.jay"
+ {
+ ArrayList l = (ArrayList) yyVals[-1+yyTop];
+
+ l.Add (yyVals[0+yyTop]);
+ yyVal = l;
+ }
+ break;
+case 284:
+#line 3268 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 286:
+#line 3281 "mb-parser.jay"
+ {
+ /* FIXME: opt_when needs to be hnadled*/
+ Expression type = null;
+ string id = null;
+
+ if (yyVals[-1+yyTop] != null) {
+ DictionaryEntry cc = (DictionaryEntry) yyVals[-1+yyTop];
+ 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, type, loc));
+
+ yyVals[-2+yyTop] = current_block;
+ current_block = new Block (current_block);
+ Block b = declare_local_variables (type, one, loc);
+ current_block = b;
+ }
+ }
+ }
+ break;
+case 287:
+#line 3305 "mb-parser.jay"
+ {
+ Expression type = null;
+ string id = null;
+
+ if (yyVals[-3+yyTop] != null){
+ DictionaryEntry cc = (DictionaryEntry) yyVals[-3+yyTop];
+ type = (Expression) cc.Key;
+ id = (string) cc.Value;
+
+ if (yyVals[-4+yyTop] != null){
+ /**/
+ /* FIXME: I can change this for an assignment.*/
+ /**/
+ while (current_block != (Block) yyVals[-4+yyTop])
+ current_block = current_block.Parent;
+ }
+ }
+
+
+ yyVal = new Catch (type, id , (Block) yyVals[0+yyTop], ((Block) yyVals[0+yyTop]).loc);
+ }
+ break;
+case 288:
+#line 3329 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 290:
+#line 3335 "mb-parser.jay"
+ {
+ yyVal = new DictionaryEntry (yyVals[0+yyTop], yyVals[-2+yyTop]);
+ }
+ break;
+case 291:
+#line 3388 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ }
+ break;
+case 292:
+#line 3396 "mb-parser.jay"
+ {
+ Location l = (Location) oob_stack.Pop ();
+ yyVal = new While ((Expression) yyVals[-6+yyTop], (Statement) yyVals[-2+yyTop], l);
+ }
+ break;
+case 294:
+#line 3471 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-5+yyTop], (Statement) yyVals[-2+yyTop], l);
+
+ if (RootContext.WarningLevel >= 3){
+ if (yyVals[-2+yyTop] == EmptyStatement.Value)
+ Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
+ }
+
+ }
+ break;
+case 295:
+#line 3489 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-8+yyTop], (Statement) yyVals[-5+yyTop], (Statement) yyVals[-2+yyTop], l);
+ }
+ break;
+case 296:
+#line 3499 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-4+yyTop], (Statement) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], l);
+ }
+ break;
+case 297:
+#line 3511 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-5+yyTop], (Statement) yyVals[-2+yyTop], l);
+
+ if (RootContext.WarningLevel >= 3){
+ if (yyVals[-2+yyTop] == EmptyStatement.Value)
+ Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
+ }
+
+ }
+ break;
+case 298:
+#line 3529 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-8+yyTop], (Statement) yyVals[-5+yyTop], (Statement) yyVals[-2+yyTop], l);
+ }
+ break;
+case 299:
+#line 3539 "mb-parser.jay"
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ yyVal = new If ((Expression) yyVals[-4+yyTop], (Statement) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], l);
+ }
+ break;
+case 302:
+#line 3667 "mb-parser.jay"
+ {
+ ArrayList labels = new ArrayList ();
+
+ labels.Add (yyVals[0+yyTop]);
+ yyVal = labels;
+ }
+ break;
+case 303:
+#line 3674 "mb-parser.jay"
+ {
+ ArrayList labels = (ArrayList) (yyVals[-2+yyTop]);
+ labels.Add (yyVals[-1+yyTop]);
+
+ yyVal = labels;
+ }
+ break;
+case 305:
+#line 3685 "mb-parser.jay"
+ {
+ yyVal = new SwitchLabel ((Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 314:
+#line 3710 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 315:
+#line 3717 "mb-parser.jay"
+ { yyVal = new StatementExpression ((ExpressionStatement) yyVals[0+yyTop], lexer.Location); }
+ break;
+case 316:
+#line 3718 "mb-parser.jay"
+ { yyVal = new StatementExpression ((ExpressionStatement) yyVals[0+yyTop], lexer.Location); }
+ break;
+case 317:
+#line 3719 "mb-parser.jay"
+ { yyVal = new StatementExpression ((ExpressionStatement) yyVals[0+yyTop], lexer.Location); }
+ break;
+case 318:
+#line 3724 "mb-parser.jay"
+ {
+ yyVal = new New ((Expression) yyVals[-3+yyTop], (ArrayList) yyVals[-1+yyTop], lexer.Location);
+ }
+ break;
+case 319:
+#line 3728 "mb-parser.jay"
+ {
+ yyVal = new New ((Expression) yyVals[0+yyTop], new ArrayList(), lexer.Location);
+ }
+ break;
+case 321:
+#line 3775 "mb-parser.jay"
+ {
+ if (yyVals[0+yyTop] != null){
+ DictionaryEntry de = (DictionaryEntry) yyVals[0+yyTop];
+
+ yyVal = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+ }
+ }
+ break;
+case 322:
+#line 3783 "mb-parser.jay"
+ {
+ if (yyVals[0+yyTop] != null){
+ DictionaryEntry de = (DictionaryEntry) yyVals[0+yyTop];
+
+ yyVal = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
+ }
+ }
+ break;
+case 323:
+#line 3794 "mb-parser.jay"
+ {
+ yyVal = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), yyVals[0+yyTop]);
+ }
+ break;
+case 324:
+#line 3802 "mb-parser.jay"
+ {
+ if (yyVals[0+yyTop] != null)
+ yyVal = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), yyVals[0+yyTop]);
+ else
+ yyVal = null;
+ }
+ break;
+case 325:
+#line 3812 "mb-parser.jay"
+ {
+ ArrayList decl = new ArrayList ();
+ if (yyVals[0+yyTop] != null)
+ decl.Add (yyVals[0+yyTop]);
+
+ yyVal = decl;
+ }
+ break;
+case 326:
+#line 3820 "mb-parser.jay"
+ {
+ ArrayList decls = (ArrayList) yyVals[-2+yyTop];
+ if (yyVals[0+yyTop] != null)
+ decls.Add (yyVals[0+yyTop]);
+
+ yyVal = yyVals[-2+yyTop];
+ }
+ break;
+case 327:
+#line 3831 "mb-parser.jay"
+ {
+ VarName vname = (VarName) yyVals[-2+yyTop];
+ string varname = (string) vname.Name;
+ current_rank_specifiers = (ArrayList) vname.Rank;
+ object varinit = yyVals[0+yyTop];
+ ArrayList a_dims = null;
+
+ if (varinit == null)
+ Report.Error (
+ 30438, lexer.Location, "Constant should have a value"
+ );
+
+ if (vname.Type != null && yyVals[-1+yyTop] != null)
+ Report.Error (
+ 30302, lexer.Location,
+ "Type character cannot be used with explicit type declaration" );
+
+ Expression vartype = (yyVals[-1+yyTop] == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) yyVals[-1+yyTop];
+
+ if (current_rank_specifiers != null)
+ {
+ Report.Error (30424, lexer.Location, "Constant doesn't support array");
+ yyVal = null;
+ }
+ else
+ yyVal = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
+ }
+ break;
+case 328:
+#line 3862 "mb-parser.jay"
+ {
+ ArrayList decl = new ArrayList ();
+ decl.AddRange ((ArrayList) yyVals[0+yyTop]);
+ yyVal = decl;
+ }
+ break;
+case 329:
+#line 3868 "mb-parser.jay"
+ {
+ ArrayList decls = (ArrayList) yyVals[-2+yyTop];
+ decls.AddRange ((ArrayList) yyVals[0+yyTop]);
+ yyVal = yyVals[-2+yyTop];
+ }
+ break;
+case 330:
+#line 3877 "mb-parser.jay"
+ {
+ ArrayList names = (ArrayList) yyVals[-2+yyTop];
+ object varinit = yyVals[0+yyTop];
+ ArrayList VarDeclarations = new ArrayList();
+ Expression vartype;
+ ArrayList a_dims = null;
+
+ if ((names.Count > 1) && (varinit != null))
+ Report.Error (
+ 30671, lexer.Location,
+ "Multiple variables with single type can not have " +
+ "a explicit initialization" );
+
+
+ foreach (VarName vname in names)
+ {
+ string varname = (string) vname.Name;
+ current_rank_specifiers = (ArrayList) vname.Rank;
+ a_dims = null;
+ varinit = yyVals[0+yyTop];
+
+ if(vname.Type != null && yyVals[-1+yyTop] != null)
+ Report.Error (
+ 30302, lexer.Location,
+ "Type character cannot be used with explicit type declaration" );
+
+ /* Some checking is required for particularly weird declarations*/
+ /* like Dim a As Integer(,)*/
+ if (yyVals[-1+yyTop] is Pair) {
+ vartype = (Expression) ((Pair) yyVals[-1+yyTop]).First;
+
+ /*if ($3 != null && $3 is ArrayList)
+ Report.Error (205, "End of statement expected.");*/
+
+ ArrayList args = (ArrayList) ((Pair) yyVals[-1+yyTop]).Second;
+ if (current_rank_specifiers != null)
+ Report.Error (31087, lexer.Location,
+ "Array types specified in too many places");
+
+ if (VariableDeclaration.IndexesSpecifiedInRank (args))
+ Report.Error (30638, "Array bounds cannot appear in type specifiers.");
+
+ current_rank_specifiers = new ArrayList ();
+ current_rank_specifiers.Add (args);
+ }
+ else
+ vartype = (yyVals[-1+yyTop] == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) yyVals[-1+yyTop];
+
+ /* if the variable is an array with explicit bound*/
+ /* and having explicit initialization throw exception*/
+ if (current_rank_specifiers != null && varinit != null)
+ {
+ bool broken = false;
+ foreach (ArrayList exprs in current_rank_specifiers)
+ {
+ foreach (Expression expr in exprs)
+ {
+ if (!((Expression)expr is EmptyExpression ))
+ {
+ Report.Error (
+ 30672, lexer.Location,
+ "Array declared with explicit bound " +
+ " can not have explicit initialization");
+ broken = true;
+ break;
+ }
+ }
+ if (broken)
+ break;
+ }
+ }
+
+ /*
+ Check for a declaration like Dim a(2) or Dim a(2,3)
+ If this is the case, we must generate an ArrayCreationExpression
+ and, in case, add the initializer after the array has been created.
+ */
+/* if (VariableDeclaration.IsArrayDecl (this)) { */
+/* if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) { */
+/* a_dims = (ArrayList) current_rank_specifiers;*/
+/* VariableDeclaration.VBFixIndexLists (ref a_dims);*/
+/* varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);*/
+/* }*/
+/* vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (current_rank_specifiers, false, lexer.Location), lexer.Location);*/
+/* }*/
+
+ if (vartype is New) {
+ if (varinit != null) {
+ Report.Error (30205, lexer.Location, "End of statement expected");
+ yyVal = null;
+ }
+ else
+ {
+ varinit = vartype;
+ vartype = ((New)vartype).RequestedType;
+ }
+ }
+ VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
+ }/* end of for*/
+ yyVal = VarDeclarations;
+ }
+ break;
+case 331:
+#line 3982 "mb-parser.jay"
+ {
+ ArrayList list = new ArrayList ();
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 332:
+#line 3988 "mb-parser.jay"
+ {
+ ArrayList list = (ArrayList) yyVals[-2+yyTop];
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 333:
+#line 3997 "mb-parser.jay"
+ {
+ yyVal = new VarName (yyVals[-2+yyTop], yyVals[-1+yyTop], yyVals[0+yyTop]);
+ }
+ break;
+case 334:
+#line 4004 "mb-parser.jay"
+ {
+ yyVal = null;
+ }
+ break;
+case 335:
+#line 4008 "mb-parser.jay"
+ {
+ yyVal = (Expression) yyVals[0+yyTop];
+ }
+ break;
+case 337:
+#line 4023 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 338:
+#line 4027 "mb-parser.jay"
+ {
+ New n = new New ((Expression)yyVals[0+yyTop], null, lexer.Location);
+ yyVal = (Expression) n;
+ }
+ break;
+case 339:
+#line 4032 "mb-parser.jay"
+ {
+ New n = new New ((Expression)yyVals[-3+yyTop], (ArrayList) yyVals[-1+yyTop], lexer.Location);
+ yyVal = (Expression) n;
+ }
+ break;
+case 340:
+#line 4048 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 341:
+#line 4057 "mb-parser.jay"
+ { yyVal = null; }
+ break;
+case 342:
+#line 4058 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 343:
+#line 4063 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 344:
+#line 4067 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 345:
+#line 4075 "mb-parser.jay"
+ {
+ ArrayList list = new ArrayList ();
+ yyVal = list;
+ }
+ break;
+case 346:
+#line 4080 "mb-parser.jay"
+ {
+ yyVal = (ArrayList) yyVals[-1+yyTop];
+ }
+ break;
+case 347:
+#line 4087 "mb-parser.jay"
+ {
+ ArrayList list = new ArrayList ();
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 348:
+#line 4093 "mb-parser.jay"
+ {
+ ArrayList list = (ArrayList) yyVals[-2+yyTop];
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 349:
+#line 4102 "mb-parser.jay"
+ {
+ /* $$ = "";*/
+ yyVal = null;
+ }
+ break;
+case 350:
+#line 4107 "mb-parser.jay"
+ {
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 351:
+#line 4114 "mb-parser.jay"
+ {
+ ArrayList rs = new ArrayList();
+ rs.Add (yyVals[0+yyTop]);
+ yyVal = rs;
+ }
+ break;
+case 352:
+#line 4120 "mb-parser.jay"
+ {
+ ArrayList rs = (ArrayList) yyVals[-1+yyTop];
+ rs.Add (yyVals[0+yyTop]);
+ yyVal = rs;
+ }
+ break;
+case 353:
+#line 4129 "mb-parser.jay"
+ {
+ yyVal = yyVals[-1+yyTop];
+ }
+ break;
+case 354:
+#line 4136 "mb-parser.jay"
+ {
+ ArrayList ds = new ArrayList();
+ ds.Add (new EmptyExpression());
+ yyVal = ds;
+ }
+ break;
+case 355:
+#line 4142 "mb-parser.jay"
+ {
+ ArrayList ds = new ArrayList();
+ ds.Add ((Expression) yyVals[0+yyTop]);
+ yyVal = ds;
+ }
+ break;
+case 356:
+#line 4148 "mb-parser.jay"
+ {
+ ArrayList ds = (ArrayList) yyVals[-2+yyTop];
+ ds.Add ((Expression) yyVals[0+yyTop]);
+ yyVal = ds;
+ }
+ break;
+case 357:
+#line 4154 "mb-parser.jay"
+ {
+ ArrayList ds = (ArrayList) yyVals[-1+yyTop];
+ ds.Add (new EmptyExpression());
+ yyVal = ds;
+ }
+ break;
+case 358:
+#line 4184 "mb-parser.jay"
+ {
+ /*TODO*/
+ }
+ break;
+case 362:
+#line 4191 "mb-parser.jay"
+ {
+ yyVal = ((MemberName) yyVals[0+yyTop]).GetTypeExpression (lexer.Location);
+ }
+ break;
+case 371:
+#line 4209 "mb-parser.jay"
+ { yyVal = new CharLiteral ((char) lexer.Value); }
+ break;
+case 372:
+#line 4210 "mb-parser.jay"
+ { yyVal = new StringLiteral ((string) lexer.Value); }
+ break;
+case 373:
+#line 4211 "mb-parser.jay"
+ { yyVal = NullLiteral.Null; }
+ break;
+case 374:
+#line 4215 "mb-parser.jay"
+ { yyVal = new FloatLiteral ((float) lexer.Value); }
+ break;
+case 375:
+#line 4216 "mb-parser.jay"
+ { yyVal = new DoubleLiteral ((double) lexer.Value); }
+ break;
+case 376:
+#line 4217 "mb-parser.jay"
+ { yyVal = new DecimalLiteral ((decimal) lexer.Value); }
+ break;
+case 377:
+#line 4221 "mb-parser.jay"
+ {
+ object v = lexer.Value;
+
+ if (v is int)
+ yyVal = new IntLiteral ((Int32)v);
+/* else if (v is short)*/
+/* $$ = new ShortLiteral ((Int16)v);*/
+ else if (v is long)
+ yyVal = new LongLiteral ((Int64)v);
+ else
+ Console.WriteLine ("OOPS. Unexpected result from scanner");
+
+ }
+ break;
+case 378:
+#line 4237 "mb-parser.jay"
+ { yyVal = new BoolLiteral (true); }
+ break;
+case 379:
+#line 4238 "mb-parser.jay"
+ { yyVal = new BoolLiteral (false); }
+ break;
+case 380:
+#line 4243 "mb-parser.jay"
+ { yyVal = yyVals[-1+yyTop]; }
+ break;
+case 381:
+#line 4248 "mb-parser.jay"
+ {
+ if (yyVals[-2+yyTop] != null) {
+ string id_name = (string)yyVals[0+yyTop];
+ if (id_name.ToUpper() == "NEW")
+ id_name = ".ctor";
+ yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], id_name, lexer.Location);
+ }
+ else
+ {
+/* if (with_stack.Count > 0) {*/
+/* Expression e = (Expression) with_stack.Peek();*/
+/* $$ = new MemberAccess (e, (string) $3, lexer.Location);*/
+/* }*/
+/* else*/
+/* {*/
+/* // OOps*/
+/* }*/
+ }
+ }
+ break;
+case 382:
+#line 4272 "mb-parser.jay"
+ {
+ if (yyVals[-2+yyTop] != null)
+ yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], (string) yyVals[0+yyTop], lexer.Location);
+ else
+ {
+/* if (with_stack.Count > 0) {*/
+/* Expression e = (Expression) with_stack.Peek();*/
+/* $$ = new MemberAccess (e, (string) $3, lexer.Location);*/
+/* }*/
+/* else*/
+/* {*/
+/* // OOps*/
+/* }*/
+ }
+ }
+ break;
+case 384:
+#line 4295 "mb-parser.jay"
+ {
+ if (yyVals[-3+yyTop] == null) {
+ Location l = lexer.Location;
+ Report.Error (1, l, "Parse error");
+ }
+ yyVal = new Invocation ((Expression) yyVals[-3+yyTop], (ArrayList) yyVals[-1+yyTop], lexer.Location);
+ }
+ break;
+case 385:
+#line 4303 "mb-parser.jay"
+ {
+ if (yyVals[-3+yyTop] == null) {
+ Location l = lexer.Location;
+ Report.Error (1, l, "THIS IS CRAZY");
+ }
+ yyVal = new Invocation ((Expression) yyVals[-3+yyTop], (ArrayList) yyVals[-2+yyTop], lexer.Location);
+/* Console.WriteLine ("Invocation: {0} with {1} arguments", $2, ($3 != null) ? ((ArrayList) $3).Count : 0);*/
+ }
+ break;
+case 386:
+#line 4315 "mb-parser.jay"
+ {
+ string id_name = (string) yyVals[0+yyTop];
+ if (id_name.ToUpper() == "NEW")
+ id_name = "New";
+ yyVal = new BaseAccess (id_name, lexer.Location);
+ }
+ break;
+case 387:
+#line 4329 "mb-parser.jay"
+ {
+ /*
+ The 'argument' rule returns an 'empty' argument
+ of type NoArg (used for default arguments in invocations)
+ if no arguments are actually passed.
+
+ If there is only one argument and it is o type NoArg,
+ we return a null (empty) list
+ */
+ ArrayList args = (ArrayList) yyVals[0+yyTop];
+ if (args.Count == 1 &&
+ ((Argument)args[0]).ArgType == Argument.AType.NoArg)
+ yyVal = null;
+ else
+ yyVal = yyVals[0+yyTop];
+ }
+ break;
+case 388:
+#line 4349 "mb-parser.jay"
+ {
+ ArrayList list = new ArrayList ();
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 389:
+#line 4355 "mb-parser.jay"
+ {
+ ArrayList list = (ArrayList) yyVals[-2+yyTop];
+ list.Add (yyVals[0+yyTop]);
+ yyVal = list;
+ }
+ break;
+case 390:
+#line 4364 "mb-parser.jay"
+ {
+ yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Expression);
+ }
+ break;
+case 391:
+#line 4368 "mb-parser.jay"
+ {
+ yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Ref);
+ }
+ break;
+case 392:
+#line 4372 "mb-parser.jay"
+ {
+ yyVal = new Argument (new EmptyExpression (), Argument.AType.NoArg);
+ }
+ break;
+case 393:
+#line 4376 "mb-parser.jay"
+ {
+ yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.AddressOf);
+ }
+ break;
+case 394:
+#line 4382 "mb-parser.jay"
+ {/* note ("section 5.4"); */ yyVal = yyVals[0+yyTop]; }
+ break;
+case 395:
+#line 4387 "mb-parser.jay"
+ { yyVal = yyVals[0+yyTop]; }
+ break;
+case 398:
+#line 4398 "mb-parser.jay"
+ {
+ yyVal = new This (current_block, lexer.Location);
+ }
+ break;
+case 399:
+#line 4402 "mb-parser.jay"
+ {
+ /* FIXME: This is actually somewhat different from Me*/
+ /* because it is for accessing static (classifier) methods/properties/fields*/
+ yyVal = new This (current_block, lexer.Location);
+ }
+ break;
+case 400:
+#line 4411 "mb-parser.jay"
+ {
+ /* TODO*/
+ }
+ break;
+case 401:
+#line 4415 "mb-parser.jay"
+ {
+ yyVal = new Cast ((Expression) yyVals[-1+yyTop], (Expression) yyVals[-3+yyTop], lexer.Location);
+ }
+ break;
+case 402:
+#line 4419 "mb-parser.jay"
+ {
+ yyVal = new Cast ((Expression) yyVals[-3+yyTop], (Expression) yyVals[-1+yyTop], lexer.Location);
+ }
+ break;
+case 403:
+#line 4425 "mb-parser.jay"
+ { yyVal = TypeManager.system_boolean_expr; }
+ break;
+case 404:
+#line 4426 "mb-parser.jay"
+ { yyVal = TypeManager.system_byte_expr; }
+ break;
+case 405:
+#line 4427 "mb-parser.jay"
+ { yyVal = TypeManager.system_char_expr; }
+ break;
+case 406:
+#line 4429 "mb-parser.jay"
+ { yyVal = TypeManager.system_double_expr; }
+ break;
+case 407:
+#line 4430 "mb-parser.jay"
+ { yyVal = TypeManager.system_decimal_expr; }
+ break;
+case 408:
+#line 4431 "mb-parser.jay"
+ { yyVal = TypeManager.system_int32_expr; }
+ break;
+case 409:
+#line 4432 "mb-parser.jay"
+ { yyVal = TypeManager.system_int64_expr; }
+ break;
+case 410:
+#line 4433 "mb-parser.jay"
+ { yyVal = TypeManager.system_object_expr; }
+ break;
+case 411:
+#line 4434 "mb-parser.jay"
+ { yyVal = TypeManager.system_int16_expr; }
+ break;
+case 412:
+#line 4435 "mb-parser.jay"
+ { yyVal = TypeManager.system_single_expr; }
+ break;
+case 413:
+#line 4436 "mb-parser.jay"
+ { yyVal = TypeManager.system_string_expr; }
+ break;
+case 414:
+#line 4441 "mb-parser.jay"
+ {
+ yyVal = new TypeOf ((Expression) yyVals[-1+yyTop], lexer.Location);
+ }
+ break;
+case 416:
+#line 4449 "mb-parser.jay"
+ {
+ /*TODO*/
+ }
+ break;
+case 418:
+#line 4457 "mb-parser.jay"
+ {
+ /*FIXME: Is this rule correctly defined ?*/
+ yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 419:
+#line 4462 "mb-parser.jay"
+ {
+ /*FIXME: Is this rule correctly defined ?*/
+ yyVal = new Unary (Unary.Operator.UnaryNegation, (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 421:
+#line 4471 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Multiply,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 422:
+#line 4476 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Division,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 424:
+#line 4485 "mb-parser.jay"
+ {
+ /*FIXME: Is this right ?*/
+ yyVal = new Binary (Binary.Operator.Division,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 426:
+#line 4495 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Modulus,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 428:
+#line 4504 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Addition,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 429:
+#line 4509 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Subtraction,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 431:
+#line 4518 "mb-parser.jay"
+ {
+ /* FIXME: This should only work for String expressions*/
+ /* We probably need to use something from the runtime*/
+ yyVal = new Binary (Binary.Operator.Addition,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 433:
+#line 4529 "mb-parser.jay"
+ {
+ /* TODO*/
+ }
+ break;
+case 434:
+#line 4533 "mb-parser.jay"
+ {
+ /*TODO*/
+ }
+ break;
+case 436:
+#line 4541 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Equality,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 437:
+#line 4546 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.Inequality,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 438:
+#line 4551 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.LessThan,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 439:
+#line 4556 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.GreaterThan,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 440:
+#line 4561 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.LessThanOrEqual,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 441:
+#line 4566 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.GreaterThanOrEqual,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 442:
+#line 4571 "mb-parser.jay"
+ {
+ /*FIXME: Should be a different op for reference equality but allows tests to use Is*/
+ yyVal = new Binary (Binary.Operator.Equality,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 443:
+#line 4577 "mb-parser.jay"
+ {
+ /*FIXME: Is this rule correctly defined ?*/
+ yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 445:
+#line 4586 "mb-parser.jay"
+ {
+ /*FIXME: Is this rule correctly defined ?*/
+ yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 447:
+#line 4595 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.LogicalAnd,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 448:
+#line 4600 "mb-parser.jay"
+ { /* FIXME: this is likely to be broken*/
+ yyVal = new Binary (Binary.Operator.LogicalAnd,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 450:
+#line 4609 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.LogicalOr,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 451:
+#line 4614 "mb-parser.jay"
+ { /* FIXME: this is likely to be broken*/
+ yyVal = new Binary (Binary.Operator.LogicalOr,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 453:
+#line 4623 "mb-parser.jay"
+ {
+ yyVal = new Binary (Binary.Operator.ExclusiveOr,
+ (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 454:
+#line 4631 "mb-parser.jay"
+ {
+ yyVal = new Assign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 455:
+#line 4635 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.Multiply, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 456:
+#line 4642 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.Division, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 457:
+#line 4649 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.Addition, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 458:
+#line 4656 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.Subtraction, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 459:
+#line 4663 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.LeftShift, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 460:
+#line 4670 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ yyVal = new CompoundAssign (
+ Binary.Operator.RightShift, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 461:
+#line 4677 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ /* FIXME should be strings only*/
+ yyVal = new CompoundAssign (
+ Binary.Operator.Addition, (Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], l);
+ }
+ break;
+case 462:
+#line 4685 "mb-parser.jay"
+ {
+ Location l = lexer.Location;
+
+ /* TODO: $$ = new CompoundAssign (
+ Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $4, l); */
+ }
+ break;
+case 463:
+#line 4692 "mb-parser.jay"
+ {
+/* ArrayList args = new ArrayList();*/
+/* Argument arg = new Argument ((Expression) $4, Argument.AType.Expression);*/
+/* args.Add (arg);*/
+
+/* New n = new New ((Expression) $1, (ArrayList) args, lexer.Location);*/
+/* n.isDelegate = true;*/
+ yyVal = new Assign ((Expression) yyVals[-3+yyTop], (Expression) yyVals[0+yyTop], lexer.Location);
+ }
+ break;
+case 466:
+#line 4713 "mb-parser.jay"
+ {
+ yyVal = ((MemberName) yyVals[0+yyTop]).GetTypeExpression (lexer.Location);
+ }
+ break;
+case 468:
+#line 4722 "mb-parser.jay"
+ {
+ ArrayList types = new ArrayList ();
+
+ types.Add (yyVals[0+yyTop]);
+ yyVal = types;
+ }
+ break;
+case 469:
+#line 4729 "mb-parser.jay"
+ {
+ ArrayList types = (ArrayList) yyVals[-2+yyTop];
+
+ types.Add (yyVals[0+yyTop]);
+ yyVal = types;
+ }
+ break;
+case 471:
+#line 4742 "mb-parser.jay"
+ { yyVal = TypeManager.system_object_expr; }
+ break;
+case 474:
+#line 4748 "mb-parser.jay"
+ { yyVal = TypeManager.system_boolean_expr; }
+ break;
+case 475:
+#line 4750 "mb-parser.jay"
+ { yyVal = TypeManager.system_char_expr; }
+ break;
+case 476:
+#line 4751 "mb-parser.jay"
+ { yyVal = TypeManager.system_string_expr; }
+ break;
+case 479:
+#line 4758 "mb-parser.jay"
+ { yyVal = TypeManager.system_decimal_expr; }
+ break;
+case 481:
+#line 4763 "mb-parser.jay"
+ { yyVal = TypeManager.system_byte_expr; }
+ break;
+case 482:
+#line 4764 "mb-parser.jay"
+ { yyVal = TypeManager.system_int16_expr; }
+ break;
+case 483:
+#line 4765 "mb-parser.jay"
+ { yyVal = TypeManager.system_int32_expr; }
+ break;
+case 484:
+#line 4766 "mb-parser.jay"
+ { yyVal = TypeManager.system_int64_expr; }
+ break;
+case 485:
+#line 4770 "mb-parser.jay"
+ { yyVal = TypeManager.system_single_expr; }
+ break;
+case 486:
+#line 4771 "mb-parser.jay"
+ { yyVal = TypeManager.system_double_expr; }
+ break;
+case 487:
+#line 4776 "mb-parser.jay"
+ {
+/* if(tokenizerController.IsAcceptingTokens)*/
+/* {*/
+/* if(in_external_source) */
+/* Report.Error (30580, lexer.Location, "#ExternalSource directives may not be nested");*/
+/* else {*/
+/* in_external_source = true;*/
+
+/* lexer.EffectiveSource = (string) $4;*/
+/* lexer.EffectiveLine = (int) $6;*/
+/* }*/
+/* }*/
+ }
+ break;
+case 488:
+#line 4790 "mb-parser.jay"
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+ string id = (yyVals[-2+yyTop] as string);
+
+ if(!(yyVals[-2+yyTop] as string).ToLower().Equals("region"))
+ Report.Error (30205, lexer.Location, "Invalid Pre-processor directive");
+ else
+ {
+ ++in_marked_region;
+ }
+ }
+ }
+ break;
+case 489:
+#line 4804 "mb-parser.jay"
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+/* if( ($3 as string).ToLower().Equals("externalsource")) {*/
+/* if(!in_external_source)*/
+/* Report.Error (30578, lexer.Location, "'#End ExternalSource' must be preceded by a matching '#ExternalSource'");*/
+/* else {*/
+/* in_external_source = false;*/
+/* lexer.EffectiveSource = lexer.Source;*/
+/* lexer.EffectiveLine = lexer.Line;*/
+/* }*/
+/* }*/
+ /* else */if((yyVals[-1+yyTop] as string).ToLower().Equals("region")) {
+ if(in_marked_region > 0)
+ --in_marked_region;
+ else
+ Report.Error (30205, lexer.Location, "'#End Region' must be preceded by a matching '#Region'");
+ }
+ else {
+ Report.Error (29999, lexer.Location, "Unrecognized Pre-Processor statement");
+ }
+ }
+ }
+ break;
+case 490:
+#line 4828 "mb-parser.jay"
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+ /*TODO;*/
+ }
+ }
+ break;
+case 491:
+#line 4835 "mb-parser.jay"
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.IF;
+
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ break;
+case 492:
+#line 4846 "mb-parser.jay"
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.IF, (BoolLiteral)yyVals[-2+yyTop]);
+ }
+ break;
+case 493:
+#line 4850 "mb-parser.jay"
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSEIF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ break;
+case 494:
+#line 4860 "mb-parser.jay"
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ELSEIF, (BoolLiteral)yyVals[-2+yyTop]);
+ }
+ break;
+case 495:
+#line 4864 "mb-parser.jay"
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSE;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ break;
+case 496:
+#line 4874 "mb-parser.jay"
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ELSE, new BoolLiteral(true));
+ }
+ break;
+case 497:
+#line 4878 "mb-parser.jay"
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ENDIF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ break;
+case 498:
+#line 4888 "mb-parser.jay"
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ENDIF, new BoolLiteral(false));
+ }
+ break;
+case 499:
+#line 4892 "mb-parser.jay"
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ Report.Error(2999, lexer.Location, "Unrecognized Pre-Processor statement");
+ else
+ Report.Warning (9999, lexer.Location, "Unrecognized Pre-Processor statement");
+ }
+ break;
+#line default
+ }
+ yyTop -= yyLen[yyN];
+ yyState = yyStates[yyTop];
+ int yyM = yyLhs[yyN];
+ if (yyState == 0 && yyM == 0) {
+ if (debug != null) debug.shift(0, yyFinal);
+ yyState = yyFinal;
+ if (yyToken < 0) {
+ yyToken = yyLex.advance() ? yyLex.token() : 0;
+ if (debug != null)
+ debug.lex(yyState, yyToken,yyname(yyToken), yyLex.value());
+ }
+ if (yyToken == 0) {
+ if (debug != null) debug.accept(yyVal);
+ return yyVal;
+ }
+ goto yyLoop;
+ }
+ if (((yyN = yyGindex[yyM]) != 0) && ((yyN += yyState) >= 0)
+ && (yyN < yyTable.Length) && (yyCheck[yyN] == yyState))
+ yyState = yyTable[yyN];
+ else
+ yyState = yyDgoto[yyM];
+ if (debug != null) debug.shift(yyStates[yyTop], yyState);
+ goto yyLoop;
+ }
+ }
+ }
+
+ static short [] yyLhs = { -1,
+ 1, 1, 2, 2, 0, 0, 4, 4, 8, 8,
+ 9, 9, 9, 13, 13, 13, 14, 14, 10, 11,
+ 12, 15, 15, 6, 6, 19, 16, 21, 16, 22,
+ 22, 22, 22, 22, 22, 23, 23, 23, 23, 23,
+ 23, 24, 24, 25, 25, 5, 5, 26, 26, 27,
+ 28, 28, 29, 29, 31, 31, 31, 7, 7, 33,
+ 35, 33, 34, 37, 37, 36, 36, 40, 38, 42,
+ 43, 38, 41, 41, 41, 39, 39, 44, 44, 45,
+ 45, 45, 46, 46, 47, 47, 49, 50, 18, 17,
+ 20, 20, 20, 20, 20, 20, 59, 62, 52, 58,
+ 58, 60, 60, 51, 51, 64, 64, 65, 65, 65,
+ 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 67, 53, 66, 66, 68, 68, 71, 69,
+ 70, 70, 70, 70, 70, 70, 70, 75, 61, 61,
+ 79, 79, 80, 81, 81, 81, 81, 81, 81, 81,
+ 73, 73, 85, 82, 91, 92, 83, 94, 95, 56,
+ 96, 96, 93, 93, 97, 97, 98, 99, 99, 99,
+ 99, 99, 99, 77, 103, 57, 102, 102, 104, 104,
+ 105, 106, 105, 108, 111, 113, 114, 54, 110, 110,
+ 115, 115, 116, 112, 117, 117, 118, 118, 119, 120,
+ 120, 121, 121, 76, 124, 122, 109, 109, 86, 86,
+ 125, 125, 123, 123, 129, 129, 127, 127, 130, 131,
+ 126, 133, 128, 132, 132, 132, 74, 136, 136, 55,
+ 55, 84, 138, 139, 72, 32, 32, 140, 141, 141,
+ 142, 134, 134, 145, 145, 146, 146, 146, 146, 88,
+ 88, 147, 147, 149, 87, 89, 148, 148, 148, 148,
+ 148, 153, 153, 151, 151, 151, 151, 151, 159, 159,
+ 159, 161, 162, 160, 158, 157, 157, 164, 165, 166,
+ 166, 167, 167, 135, 135, 170, 168, 169, 169, 171,
+ 174, 172, 156, 175, 175, 175, 177, 177, 177, 176,
+ 176, 178, 178, 179, 179, 180, 180, 181, 181, 181,
+ 181, 182, 182, 155, 183, 183, 183, 185, 185, 187,
+ 150, 150, 188, 189, 78, 78, 190, 137, 137, 193,
+ 194, 194, 191, 101, 101, 90, 192, 192, 192, 195,
+ 144, 144, 196, 196, 197, 197, 198, 198, 143, 143,
+ 199, 199, 200, 201, 201, 201, 201, 202, 202, 202,
+ 202, 202, 202, 202, 202, 202, 202, 203, 203, 203,
+ 203, 203, 203, 212, 212, 212, 211, 210, 210, 204,
+ 208, 208, 213, 184, 184, 206, 154, 215, 215, 216,
+ 216, 216, 216, 217, 107, 163, 163, 205, 205, 209,
+ 209, 209, 219, 219, 219, 219, 219, 219, 219, 219,
+ 219, 219, 219, 207, 220, 220, 152, 152, 152, 221,
+ 221, 221, 222, 222, 223, 223, 224, 224, 224, 225,
+ 225, 226, 226, 226, 227, 227, 227, 227, 227, 227,
+ 227, 227, 227, 228, 228, 229, 229, 229, 230, 230,
+ 230, 218, 218, 186, 186, 186, 186, 186, 186, 186,
+ 186, 186, 186, 48, 173, 100, 100, 63, 63, 30,
+ 214, 214, 231, 231, 231, 231, 232, 232, 232, 233,
+ 233, 233, 233, 233, 234, 234, 3, 3, 3, 3,
+ 235, 3, 236, 3, 237, 3, 238, 3, 3,
+ };
+ static short [] yyLen = { 2,
+ 1, 1, 1, 2, 5, 5, 0, 1, 1, 2,
+ 1, 1, 1, 0, 1, 1, 1, 1, 4, 4,
+ 4, 0, 1, 1, 2, 0, 3, 0, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 3, 0, 1, 1, 2, 3,
+ 1, 3, 1, 3, 0, 2, 3, 0, 1, 1,
+ 0, 3, 4, 0, 1, 1, 3, 0, 3, 0,
+ 0, 6, 1, 1, 1, 0, 3, 0, 1, 1,
+ 3, 1, 1, 3, 1, 3, 3, 0, 8, 2,
+ 1, 1, 1, 1, 1, 1, 0, 0, 11, 0,
+ 3, 0, 3, 0, 1, 1, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 8, 0, 1, 1, 2, 0, 4,
+ 1, 1, 1, 1, 1, 1, 1, 3, 0, 1,
+ 1, 2, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 13, 0, 0, 15, 0, 0, 10,
+ 0, 1, 0, 1, 1, 2, 2, 1, 1, 1,
+ 1, 1, 1, 6, 0, 9, 0, 1, 1, 2,
+ 3, 0, 6, 6, 0, 0, 0, 11, 0, 1,
+ 1, 2, 3, 1, 0, 1, 1, 2, 3, 1,
+ 1, 4, 6, 1, 0, 12, 0, 3, 0, 2,
+ 1, 3, 2, 2, 0, 1, 0, 1, 0, 0,
+ 11, 0, 11, 0, 2, 5, 3, 0, 1, 7,
+ 8, 0, 0, 0, 12, 0, 1, 1, 1, 3,
+ 7, 0, 1, 2, 1, 1, 1, 1, 1, 0,
+ 2, 1, 3, 3, 0, 0, 1, 1, 5, 5,
+ 3, 0, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 6, 1, 1, 6, 9, 0,
+ 1, 1, 2, 0, 1, 0, 5, 0, 1, 3,
+ 0, 9, 1, 7, 10, 6, 7, 10, 6, 0,
+ 1, 1, 3, 3, 1, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 5, 2, 1,
+ 1, 1, 2, 2, 1, 3, 3, 1, 3, 3,
+ 1, 3, 3, 0, 2, 1, 1, 3, 6, 0,
+ 0, 2, 1, 1, 2, 3, 1, 3, 0, 1,
+ 1, 2, 3, 0, 1, 3, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 3, 3, 1, 4, 5, 3, 1, 1, 3, 1,
+ 2, 0, 2, 1, 1, 0, 1, 1, 1, 6,
+ 6, 4, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 4, 1, 3, 1, 2, 2, 1,
+ 3, 3, 1, 3, 1, 3, 1, 3, 3, 1,
+ 3, 1, 3, 3, 1, 3, 3, 3, 3, 3,
+ 3, 3, 4, 1, 2, 1, 3, 3, 1, 3,
+ 3, 1, 3, 3, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 1, 1, 1, 1, 1, 3, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 8, 4, 4, 6,
+ 0, 6, 0, 6, 0, 4, 0, 5, 3,
+ };
+ static short [] yyDefRed = { 0,
+ 3, 0, 0, 0, 0, 4, 0, 0, 9, 11,
+ 12, 13, 0, 0, 0, 0, 0, 495, 493, 0,
+ 491, 0, 0, 0, 0, 48, 10, 17, 18, 0,
+ 16, 15, 0, 0, 499, 0, 0, 0, 497, 0,
+ 0, 0, 0, 31, 33, 34, 35, 32, 30, 0,
+ 0, 0, 51, 53, 0, 0, 0, 24, 0, 0,
+ 60, 49, 0, 0, 0, 0, 496, 379, 378, 0,
+ 0, 489, 0, 0, 488, 0, 0, 0, 0, 73,
+ 74, 44, 0, 0, 66, 70, 5, 0, 25, 6,
+ 121, 112, 119, 113, 115, 117, 114, 116, 110, 109,
+ 108, 120, 118, 111, 122, 90, 0, 106, 0, 0,
+ 0, 0, 301, 0, 498, 0, 0, 54, 45, 52,
+ 0, 0, 0, 0, 107, 0, 27, 0, 0, 0,
+ 0, 0, 0, 29, 91, 92, 93, 94, 95, 96,
+ 62, 490, 494, 492, 0, 0, 69, 67, 2, 65,
+ 0, 63, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 474, 481, 0, 403, 404, 405, 407, 406,
+ 475, 408, 409, 410, 411, 412, 413, 0, 479, 0,
+ 486, 0, 483, 484, 398, 0, 399, 0, 0, 373,
+ 471, 482, 485, 476, 0, 0, 0, 0, 377, 374,
+ 375, 376, 371, 372, 0, 0, 0, 79, 0, 0,
+ 83, 85, 464, 420, 365, 320, 366, 0, 358, 359,
+ 360, 361, 363, 364, 367, 368, 369, 370, 0, 383,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 446, 0, 0, 472, 473, 477, 478, 71, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 487, 0, 0,
+ 0, 0, 0, 466, 0, 467, 445, 0, 0, 418,
+ 419, 0, 77, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 335, 0, 0, 0,
+ 0, 158, 0, 0, 0, 0, 386, 0, 0, 380,
+ 87, 0, 84, 0, 86, 0, 0, 390, 0, 0,
+ 388, 381, 382, 0, 0, 0, 421, 422, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 447, 448, 0, 0, 72, 0, 0, 0,
+ 0, 0, 0, 237, 0, 239, 0, 0, 175, 0,
+ 179, 0, 186, 0, 191, 0, 0, 0, 127, 0,
+ 0, 0, 0, 0, 0, 414, 0, 443, 393, 394,
+ 391, 384, 0, 402, 0, 0, 468, 0, 98, 246,
+ 247, 248, 249, 0, 0, 245, 0, 0, 0, 0,
+ 0, 180, 0, 0, 192, 129, 0, 128, 0, 0,
+ 159, 0, 165, 0, 0, 0, 318, 389, 0, 0,
+ 0, 0, 0, 0, 244, 0, 336, 240, 0, 0,
+ 0, 0, 0, 0, 187, 194, 0, 197, 0, 0,
+ 0, 0, 229, 0, 0, 0, 173, 170, 171, 168,
+ 169, 172, 151, 152, 167, 0, 0, 166, 401, 400,
+ 0, 469, 0, 0, 0, 0, 141, 36, 37, 38,
+ 39, 40, 41, 43, 0, 0, 0, 0, 0, 0,
+ 198, 0, 137, 130, 131, 132, 133, 134, 135, 136,
+ 204, 0, 0, 0, 325, 0, 0, 0, 0, 0,
+ 0, 331, 328, 0, 0, 0, 0, 142, 0, 0,
+ 0, 351, 0, 0, 0, 0, 0, 201, 199, 200,
+ 0, 0, 340, 0, 0, 0, 337, 0, 0, 0,
+ 0, 0, 153, 0, 0, 0, 0, 0, 150, 147,
+ 146, 144, 145, 148, 149, 143, 0, 355, 0, 0,
+ 352, 0, 0, 0, 0, 0, 0, 333, 326, 0,
+ 0, 327, 0, 0, 56, 0, 0, 232, 329, 332,
+ 330, 0, 0, 353, 0, 241, 0, 0, 0, 0,
+ 0, 0, 0, 0, 343, 342, 344, 0, 155, 57,
+ 255, 0, 356, 0, 0, 0, 0, 0, 0, 345,
+ 347, 0, 0, 0, 0, 0, 0, 0, 208, 0,
+ 0, 346, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 256, 0, 252, 257, 258,
+ 0, 264, 265, 266, 267, 268, 269, 270, 271, 276,
+ 277, 293, 314, 0, 0, 317, 321, 322, 0, 0,
+ 0, 0, 339, 348, 0, 0, 0, 0, 272, 465,
+ 0, 0, 0, 397, 274, 0, 273, 255, 234, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 156, 0, 0, 0, 261, 0, 255, 0, 0,
+ 0, 253, 0, 0, 0, 454, 0, 0, 0, 0,
+ 0, 0, 256, 0, 0, 0, 0, 0, 0, 255,
+ 0, 0, 0, 256, 0, 0, 0, 282, 0, 457,
+ 458, 463, 455, 456, 462, 461, 459, 460, 0, 0,
+ 0, 0, 0, 213, 218, 0, 216, 214, 256, 259,
+ 0, 263, 260, 0, 254, 0, 0, 289, 0, 0,
+ 283, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 296, 275, 0, 286, 278, 255, 0, 0, 255,
+ 225, 0, 0, 0, 0, 255, 0, 294, 290, 255,
+ 0, 0, 220, 285, 0, 255, 0, 0, 0, 287,
+ 0, 0, 0, 0, 0, 0, 255, 279, 256, 226,
+ 256, 295, 0, 0, 0, 0, 0, 299, 0, 0,
+ 255, 297, 0, 0, 0, 0, 0, 0, 298,
+ };
+ protected static short [] yyDgoto = { 2,
+ 150, 151, 6, 7, 24, 56, 362, 8, 9, 10,
+ 11, 12, 33, 30, 359, 58, 59, 127, 109, 134,
+ 110, 82, 484, 485, 206, 25, 26, 52, 53, 264,
+ 542, 363, 60, 61, 111, 84, 152, 85, 147, 121,
+ 86, 124, 302, 207, 208, 209, 210, 211, 212, 303,
+ 106, 135, 136, 137, 138, 139, 140, 361, 304, 399,
+ 475, 433, 396, 107, 108, 377, 310, 378, 379, 494,
+ 449, 458, 459, 460, 461, 499, 462, 504, 476, 477,
+ 556, 463, 464, 602, 578, 312, 699, 636, 679, 537,
+ 614, 718, 421, 382, 467, 0, 422, 423, 465, 397,
+ 437, 369, 411, 370, 371, 441, 328, 528, 592, 373,
+ 309, 445, 414, 490, 374, 375, 446, 447, 448, 529,
+ 530, 501, 715, 691, 381, 716, 744, 717, 748, 780,
+ 802, 766, 796, 404, 795, 466, 511, 601, 701, 364,
+ 365, 366, 520, 572, 405, 406, 637, 638, 700, 639,
+ 640, 214, 696, 329, 642, 643, 644, 645, 646, 647,
+ 648, 649, 675, 650, 651, 726, 727, 728, 757, 790,
+ 758, 0, 671, 0, 652, 114, 772, 0, 0, 0,
+ 0, 0, 653, 215, 216, 656, 217, 657, 658, 505,
+ 506, 538, 513, 514, 568, 596, 597, 612, 521, 522,
+ 559, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 330, 331, 391, 231, 232, 233,
+ 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+ 244, 245, 246, 247, 41, 38, 37, 71,
+ };
+ protected static short [] yySindex = { -277,
+ 0, 0, -42, -263, -240, 0, -236, -244, 0, 0,
+ 0, 0, -254, -100, -100, -207, -165, 0, 0, -312,
+ 0, -383, 9, -51, -236, 0, 0, 0, 0, -277,
+ 0, 0, -277, -277, 0, -33, 92, -274, 0, 100,
+ -274, -41, 125, 0, 0, 0, 0, 0, 0, 29,
+ 59, -250, 0, 0, -230, -247, 3240, 0, 0, 0,
+ 0, 0, 86, 86, 86, -274, 0, 0, 0, 88,
+ 188, 0, 88, 93, 0, 9, 9, 9, 86, 0,
+ 0, 0, 0, -78, 0, 0, 0, 2192, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2192, 0, 177, 736,
+ -51, 223, 0, 243, 0, 256, 119, 0, 0, 0,
+ 165, -230, -223, 179, 0, 9, 0, 9, -72, 9,
+ 9, 9, 9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 187, 3081, 0, 0, 0, 0,
+ 86, 0, 9, -91, -277, 9, 9, 343, -277, -277,
+ -277, 304, 0, 0, 3385, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 206, 0, 231,
+ 0, 258, 0, 0, 0, 248, 0, 1614, 3081, 0,
+ 0, 0, 0, 0, 3233, 3081, 3233, 3233, 0, 0,
+ 0, 0, 0, 0, 238, 59, 265, 0, 270, 277,
+ 0, 0, 0, 0, 0, 0, 0, -354, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 288, 0,
+ 310, 309, 298, -113, 303, 413, 97, 312, 34, 323,
+ 0, 373, 289, 0, 0, 0, 0, 0, 86, 86,
+ 347, 348, 1614, -277, 86, 86, -299, 0, -133, 3081,
+ 3081, 1614, 290, 0, 359, 0, 0, -235, 358, 0,
+ 0, 3081, 0, 3081, 9, 2473, 9, 9, 3081, 3081,
+ 3385, 3233, 3233, 3233, 3233, 3233, 3233, 3233, 3233, 3233,
+ 3233, 3233, 3233, 3233, 3233, 3233, 3233, 3081, 3081, 3081,
+ 3081, 165, -51, 449, -51, -51, 0, -239, 450, -51,
+ 9, 0, 2473, 372, 381, 375, 0, 2473, 1614, 0,
+ 0, 277, 0, 238, 0, 3081, 3081, 0, 386, 385,
+ 0, 0, 0, 289, 390, -354, 0, 0, -113, 303,
+ 413, 413, 97, 312, 312, 34, 34, 34, 34, 34,
+ 34, 34, 0, 0, 373, 373, 0, -51, 500, 1614,
+ 482, 195, 397, 0, 398, 0, 399, 9, 0, -51,
+ 0, 1614, 0, 450, 0, 2192, 517, -51, 0, 59,
+ 417, 2192, 424, 1614, 1614, 0, 438, 0, 0, 0,
+ 0, 0, 2473, 0, 509, -217, 0, 1614, 0, 0,
+ 0, 0, 0, 9, 195, 0, 343, -51, -277, -277,
+ 554, 0, -217, -51, 0, 0, 525, 0, 9, 2149,
+ 0, 2192, 0, 0, 453, 454, 0, 0, -277, 1614,
+ 86, -217, -51, 731, 0, -277, 0, 0, 86, 86,
+ 463, 561, 86, 2192, 0, 0, -51, 0, 1957, -277,
+ 59, 9, 0, 9, 9, -116, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 9, 567, 0, 0, 0,
+ 86, 0, 86, 2192, 574, -51, 0, 0, 0, 0,
+ 0, 0, 0, 0, 478, 86, 3081, -277, 99, 584,
+ 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 86, 731, -184, 0, 625, 629, 731, 488, 488,
+ -161, 0, 0, -252, 518, 1957, 618, 0, 3081, 343,
+ 478, 0, -277, 86, 9, 9, 9, 0, 0, 0,
+ 581, 731, 0, 9, 86, 218, 0, 491, 1614, 488,
+ 87, -277, 0, 9, 86, 9, 491, -277, 0, 0,
+ 0, 0, 0, 0, 0, 0, -277, 0, 114, 491,
+ 0, 86, 731, 731, 488, -277, 503, 0, 0, 1614,
+ 2929, 0, 589, 343, 0, 506, 86, 0, 0, 0,
+ 0, 86, 86, 0, 3081, 0, 488, 503, -277, 86,
+ -51, 343, 519, 2777, 0, 0, 0, -277, 0, 0,
+ 0, 589, 0, 343, 343, 86, 513, 589, 2473, 0,
+ 0, -80, 86, 589, 2321, -277, -277, -277, 0, -277,
+ 514, 0, 2929, -277, 3233, 9, 9, 456, 3081, 9,
+ 3233, 3081, 3081, 3081, -223, 0, -223, 0, 0, 0,
+ 919, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 86, 86,
+ 86, 86, 0, 0, 86, 522, 523, 526, 0, 0,
+ 88, 530, 532, 0, 0, -223, 0, 0, 0, 2321,
+ 538, 541, 2625, 547, 551, 553, 560, 563, 577, 2321,
+ -51, 0, 688, -223, 2473, 0, 712, 0, 2321, 704,
+ 691, 0, 3081, 3081, 3081, 0, 3081, 3081, 3081, 3081,
+ 3081, 3081, 0, -272, 692, -51, -51, 2321, 3081, 0,
+ 591, 3081, 699, 0, 9, 126, 704, 0, 620, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 705, -277,
+ 613, 661, 656, 0, 0, 713, 0, 0, 0, 0,
+ 486, 0, 0, 645, 0, 769, -223, 0, 643, -223,
+ 0, -277, 652, 86, -31, -277, -277, 739, -223, 3081,
+ 718, 0, 0, 1614, 0, 0, 0, 86, -277, 0,
+ 0, 9, 86, 86, 733, 0, 88, 0, 0, 0,
+ 740, 86, 0, 0, 343, 0, -277, 744, -223, 0,
+ 658, 2321, 640, 2321, 86, 737, 0, 0, 0, 0,
+ 0, 0, 516, 749, 757, -223, 741, 0, 745, 693,
+ 0, 0, -277, -277, 767, 86, 86, 753, 0,
+ };
+ protected static short [] yyRindex = { 0,
+ 0, 0, 7141, 0, 0, 0, 7429, 7213, 0, 0,
+ 0, 0, 0, 772, 772, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3449, 7501, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -288,
+ 5251, 0, 0, 0, 0, 8024, 728, 0, 732, 730,
+ 0, 0, 6925, 6997, 7069, 0, 0, 0, 0, 774,
+ 0, 0, 774, 0, 0, 0, 0, 0, 7285, 0,
+ 0, 0, 468, 0, 0, 0, 0, 728, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -19, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 44, 0, 840, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 252, 0, 0, 0, 0,
+ 557, 0, 0, 0, 0, 0, 0, 775, 0, 0,
+ 0, 0, 0, 0, 664, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5324, 664, 0,
+ 0, 0, 0, 0, 664, 664, 664, 664, 0, 0,
+ 0, 0, 0, 0, 5776, 5447, 0, 0, 673, 674,
+ 0, 0, 0, 0, 0, 0, 0, 5582, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 403, 0, 5729, 5826, 5948, 6043, 6212, 6331, 6468, 360,
+ 0, 333, 189, 0, 0, 0, 0, 0, 7573, 3558,
+ 0, 0, 122, 0, 7602, 3807, 5253, 0, 0, 664,
+ 664, 679, 0, 0, 5544, 0, 0, 0, 0, 0,
+ 0, 664, 0, 664, 0, 539, 0, 0, 664, 664,
+ 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
+ 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
+ 664, 44, 7912, 3640, 91, 91, 0, -122, 7697, 4834,
+ 0, 0, 539, 0, 0, 0, 0, 539, 6503, 0,
+ 0, 686, 0, 0, 0, 664, 664, 0, 0, 687,
+ 0, 0, 0, 389, 0, 5679, 0, 0, 5876, 5991,
+ 6093, 6162, 6262, 6381, 6431, 6540, 6590, 6627, 6640, 6706,
+ 6749, 6819, 0, 0, 1572, 1686, 0, 7952, 0, -159,
+ 3892, 60, 0, 0, 689, 0, 0, 0, 0, -117,
+ 0, -159, 0, 7732, 0, 395, 0, 4919, 0, 3974,
+ 5001, 422, 0, 679, 679, 0, 0, 0, 0, 0,
+ 0, 0, 539, 0, 0, 0, 0, -159, 0, 0,
+ 0, 0, 0, 0, -246, 0, 775, 103, 0, 682,
+ 0, 0, 0, 1808, 0, 0, 0, 0, 0, 71,
+ 0, 670, 0, 5374, 0, 0, 0, 0, 0, -159,
+ 3725, 0, 5086, -233, 0, 0, 0, 0, 925, -206,
+ 0, 0, 7667, 152, 0, 0, 2000, 0, 71, 0,
+ 4084, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 7357, 0, 4166, 395, 0, 5168, 0, 0, 0, 0,
+ 0, 0, 0, 0, -181, 1009, 664, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1093, -88, 0, 0, -38, 0, -186, 794, -65,
+ 0, 0, 0, -114, 0, 71, 0, 0, 550, 286,
+ -112, 0, 0, 1177, 0, 0, 0, 0, 0, 0,
+ 0, -186, 0, 0, 4251, -23, 0, -189, 30, 319,
+ 103, 0, 0, 0, 4333, 0, -189, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 207,
+ 0, -195, -218, -218, 794, 0, 461, 0, 0, 10,
+ 664, 0, 795, 90, 0, 0, 1553, 0, 0, 0,
+ 0, 1261, 1345, 0, 571, 0, -237, 48, 0, 1429,
+ 91, 90, 80, 664, 0, 0, 0, 0, 0, 0,
+ 0, 795, 0, 775, 775, 7762, 0, 795, 539, 0,
+ 0, 0, 4418, 795, -282, 0, 0, 0, 0, 0,
+ 0, 0, 664, 0, 664, 0, 0, 0, 664, 0,
+ 664, -151, 664, -151, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 216, 835, 0, 0, 0, 1745, 7797,
+ 7827, 25, 0, 0, 1745, 0, -90, -45, 0, 0,
+ -14, -13, 0, 0, 0, 0, 0, 0, 0, 268,
+ 0, 0, 664, 0, 0, 0, 0, 0, 0, -282,
+ -262, 0, 0, 0, 539, 0, 0, 0, 371, 240,
+ 0, 0, 664, 664, 664, 0, 664, 664, 664, 664,
+ 664, 664, 0, 0, 0, -251, 156, -282, 664, 0,
+ 0, 664, 0, 0, 8, 0, 245, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 799, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1937, -215, 0, 0, 0, 0, 664,
+ 0, 0, 0, 12, 0, 0, 0, 4500, 0, 0,
+ 0, -249, 2129, 4585, 0, 0, -14, 0, 0, 0,
+ 0, 4667, 0, 0, 697, 0, 0, 0, 0, 0,
+ 0, -282, 0, -282, 4752, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -287, -278, 0, 0,
+ };
+ protected static short [] yyGindex = { 0,
+ -394, 1, 0, 0, 0, 809, -20, 0, 1107, 0,
+ 0, 0, 1105, 0, 0, -50, 0, 0, 0, -136,
+ 0, -16, 0, 192, 23, 0, 1096, 0, 1045, 462,
+ 139, -304, 0, 1013, 0, 0, 0, 1004, 825, 0,
+ 0, 0, 0, 0, 0, 0, 856, 355, 857, 0,
+ 580, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -327, 0, 1024, 0, 0, 0, 758, 0,
+ 0, -419, -411, -210, -200, 619, -198, 515, 0, 666,
+ 0, 0, 0, 0, 0, 181, -590, -216, -137, -389,
+ 0, 0, 0, 0, 0, 0, 0, 721, 0, -183,
+ 982, 0, 0, 0, 776, 0, -52, 0, 559, 0,
+ 0, 0, 0, 0, 0, 771, 0, 0, 702, 0,
+ 0, 0, 0, 0, 0, 435, 0, 439, 0, 0,
+ 0, 0, 0, 391, 0, 0, 527, 0, 0, 0,
+ 0, 759, 0, -211, 0, 761, 0, 489, -229, 0,
+ 0, -154, 0, -305, 0, 0, 0, 0, 0, 0,
+ 0, 0, 534, 0, 0, 0, 0, 444, 0, 0,
+ 0, 0, 402, 0, 0, -73, 361, 0, 0, 0,
+ 0, 0, 0, -511, -196, 0, 0, 0, 0, 639,
+ -457, 662, 631, 0, 0, -542, 0, 0, 0, 657,
+ 0, -143, 0, 0, 0, 0, 0, 0, 0, 416,
+ 0, 0, 0, -185, 0, 784, 0, 0, 0, 0,
+ 897, 898, 401, 899, 442, 698, 0, -94, 436, 906,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ protected static short [] yyTable = { 116,
+ 3, 367, 266, 57, 265, 89, 50, 383, 512, 87,
+ 615, 39, 387, 536, 28, 16, 284, 436, 221, 243,
+ 44, 259, 243, 250, 13, 311, 42, 223, 55, 495,
+ 63, 1, 42, 64, 65, 88, 80, 496, 44, 68,
+ 223, 243, 270, 271, 413, 51, 740, 42, 17, 14,
+ 242, 611, 79, 242, 217, 276, 58, 45, 1, 277,
+ 119, 50, 181, 18, 19, 20, 243, 266, 690, 307,
+ 432, 55, 242, 183, 692, 43, 266, 51, 316, 42,
+ 664, 181, 46, 21, 349, 1, 512, 221, 580, 23,
+ 42, 1, 183, 213, 267, 319, 550, 242, 51, 181,
+ 51, 35, 741, 654, 551, 243, 181, 5, 81, 4,
+ 183, 155, 58, 158, 159, 160, 161, 183, 69, 341,
+ 15, 47, 42, 58, 1, 44, 44, 337, 338, 205,
+ 560, 480, 221, 266, 29, 388, 242, 336, 42, 251,
+ 252, 223, 243, 269, 51, 181, 58, 1, 154, 480,
+ 40, 58, 44, 350, 249, 250, 183, 396, 48, 255,
+ 256, 257, 546, 284, 78, 58, 243, 5, 654, 512,
+ 58, 45, 55, 242, 266, 51, 42, 42, 654, 42,
+ 55, 42, 181, 177, 599, 42, 266, 654, 178, 793,
+ 58, 42, 149, 183, 334, 58, 46, 430, 266, 266,
+ 425, 426, 608, 353, 354, 804, 654, 314, 315, 289,
+ 51, 290, 266, 181, 617, 618, 243, 1, 324, 213,
+ 42, 213, 22, 42, 183, 341, 341, 335, 509, 58,
+ 534, 349, 49, 349, 58, 47, 576, 349, 497, 400,
+ 678, 401, 680, 55, 266, 156, 472, 242, 498, 105,
+ 500, 31, 32, 544, 308, 480, 181, 205, 324, 55,
+ 332, 333, 480, 323, 396, 105, 58, 183, 105, 105,
+ 334, 58, 48, 389, 390, 51, 313, 44, 105, 105,
+ 277, 698, 88, 457, 51, 480, 607, 368, 105, 376,
+ 654, 105, 654, 105, 300, 262, 45, 36, 105, 720,
+ 350, 334, 350, 621, 334, 552, 350, 89, 282, 283,
+ 105, 4, 493, 207, 157, 553, 288, 555, 480, 105,
+ 480, 46, 77, 402, 105, 324, 42, 42, 242, 403,
+ 42, 622, 105, 380, 623, 581, 122, 88, 480, 228,
+ 58, 51, 123, 205, 105, 58, 49, 242, 586, 368,
+ 266, 410, 307, 266, 480, 573, 207, 376, 228, 58,
+ 47, 58, 775, 58, 5, 777, 105, 105, 55, 105,
+ 323, 58, 242, 58, 786, 58, 334, 334, 58, 549,
+ 334, 781, 51, 228, 266, 66, 593, 434, 338, 721,
+ 58, 480, 480, 444, 51, 480, 431, 48, 334, 205,
+ 67, 300, 262, 58, 807, 803, 51, 51, 72, 439,
+ 440, 242, 474, 443, 334, 58, 525, 74, 655, 480,
+ 51, 821, 228, 288, 480, 480, 444, 480, 480, 471,
+ 480, 759, 473, 75, 523, 503, 486, 507, 508, 510,
+ 760, 451, 58, 105, 205, 58, 480, 76, 242, 503,
+ 502, 58, 51, 70, 58, 474, 73, 58, 76, 228,
+ 641, 215, 526, 58, 76, 400, 558, 401, 723, 104,
+ 666, 49, 77, 713, 58, 532, 673, 113, 289, 58,
+ 290, 112, 724, 655, 54, 527, 44, 163, 524, 164,
+ 751, 58, 5, 655, 338, 338, 115, 452, 338, 575,
+ 171, 749, 655, 236, 535, 45, 55, 117, 563, 564,
+ 565, 545, 179, 286, 287, 104, 83, 503, 595, 181,
+ 126, 655, 242, 562, 315, 641, 584, 503, 585, 503,
+ 46, 142, 603, 228, 480, 641, 480, 118, 104, 54,
+ 480, 595, 577, 251, 641, 280, 183, 791, 582, 402,
+ 281, 143, 184, 58, 280, 403, 798, 583, 51, 281,
+ 800, 51, 570, 641, 144, 58, 590, 145, 191, 47,
+ 595, 251, 251, 251, 146, 739, 670, 813, 452, 674,
+ 676, 674, 251, 83, 55, 809, 755, 811, 266, 606,
+ 789, 825, 51, 452, 153, 192, 193, 694, 613, 162,
+ 452, 452, 194, 452, 452, 655, 48, 655, 253, 503,
+ 503, 768, 258, 672, 248, 260, 659, 660, 661, 341,
+ 662, 341, 444, 444, 665, 365, 321, 55, 323, 365,
+ 706, 315, 365, 365, 365, 298, 299, 365, 365, 365,
+ 261, 449, 365, 55, 300, 301, 250, 641, 543, 641,
+ 730, 731, 732, 291, 733, 734, 735, 736, 737, 738,
+ 365, 263, 365, 104, 78, 480, 750, 262, 444, 753,
+ 714, 814, 272, 815, 250, 250, 250, 273, 574, 104,
+ 49, 480, 104, 104, 274, 250, 341, 342, 449, 449,
+ 104, 275, 104, 104, 533, 743, 746, 453, 334, 540,
+ 334, 278, 104, 589, 334, 104, 104, 104, 756, 104,
+ 104, 395, 104, 799, 279, 444, 444, 670, 280, 104,
+ 104, 281, 449, 567, 104, 604, 207, 163, 284, 104,
+ 344, 345, 104, 104, 104, 355, 356, 449, 288, 104,
+ 764, 292, 293, 294, 449, 449, 104, 449, 449, 444,
+ 285, 104, 317, 598, 587, 588, 305, 306, 104, 295,
+ 104, 296, 778, 297, 444, 794, 783, 784, 318, 207,
+ 320, 444, 444, 104, 444, 444, 360, 372, 453, 792,
+ 104, 104, 616, 104, 480, 207, 384, 386, 620, 769,
+ 770, 771, 395, 453, 624, 385, 51, 805, 392, 393,
+ 453, 453, 394, 453, 453, 395, 398, 104, 104, 407,
+ 104, 409, 408, 1, 395, 395, 1, 395, 395, 816,
+ 770, 817, 417, 826, 827, 1, 1, 1, 1, 1,
+ 1, 419, 1, 1, 1, 1, 424, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 427, 1, 429, 1, 1, 1, 1, 104, 1, 442,
+ 1, 1, 1, 450, 1, 469, 470, 1, 488, 1,
+ 1, 1, 515, 1, 1, 1, 1, 68, 1, 517,
+ 1, 487, 68, 75, 104, 1, 1, 519, 68, 531,
+ 536, 1, 268, 1, 539, 1, 1, 541, 1, 1,
+ 1, 1, 557, 548, 1, 1, 1, 1, 1, 571,
+ 566, 1, 591, 311, 1, 1, 1, 1, 600, 1,
+ 1, 1, 1, 1, 1, 619, 663, 1, 609, 1,
+ 669, 1, 1, 1, 1, 1, 693, 534, 104, 695,
+ 544, 1, 1, 1, 1, 1, 697, 1, 719, 1,
+ 1, 392, 480, 392, 104, 416, 703, 104, 104, 704,
+ 1, 420, 354, 480, 354, 707, 1, 104, 104, 708,
+ 1, 709, 722, 1, 1, 164, 1, 104, 710, 725,
+ 104, 711, 104, 357, 480, 357, 59, 104, 346, 347,
+ 348, 349, 350, 351, 352, 712, 729, 742, 59, 104,
+ 59, 420, 59, 752, 754, 1, 762, 1, 104, 1,
+ 763, 1, 104, 1, 59, 1, 28, 59, 59, 1,
+ 128, 104, 765, 489, 767, 104, 59, 59, 59, 28,
+ 741, 740, 773, 129, 774, 104, 776, 59, 779, 28,
+ 59, 788, 59, 130, 785, 801, 59, 59, 59, 806,
+ 797, 808, 810, 516, 819, 104, 104, 104, 104, 59,
+ 812, 28, 820, 823, 822, 131, 104, 824, 59, 59,
+ 28, 104, 828, 59, 132, 26, 829, 480, 59, 59,
+ 14, 59, 300, 334, 59, 80, 82, 59, 59, 59,
+ 59, 480, 59, 59, 59, 59, 64, 59, 81, 387,
+ 182, 238, 55, 209, 59, 59, 59, 224, 64, 334,
+ 64, 358, 64, 104, 27, 59, 59, 28, 59, 34,
+ 62, 133, 120, 141, 64, 148, 357, 64, 64, 322,
+ 125, 325, 104, 59, 554, 418, 64, 64, 64, 254,
+ 667, 518, 468, 316, 415, 412, 605, 64, 491, 61,
+ 64, 747, 64, 668, 745, 782, 64, 64, 64, 478,
+ 479, 480, 481, 482, 483, 435, 438, 677, 702, 64,
+ 761, 787, 569, 818, 579, 547, 428, 561, 64, 64,
+ 339, 230, 340, 64, 334, 0, 343, 0, 64, 64,
+ 0, 64, 59, 230, 64, 0, 0, 64, 64, 64,
+ 64, 0, 64, 64, 64, 64, 0, 64, 0, 230,
+ 0, 0, 230, 230, 64, 64, 64, 0, 0, 0,
+ 0, 230, 230, 230, 0, 64, 64, 0, 64, 0,
+ 230, 0, 230, 0, 0, 230, 0, 230, 0, 0,
+ 0, 230, 230, 64, 320, 0, 0, 0, 320, 0,
+ 316, 320, 320, 320, 230, 0, 320, 320, 320, 64,
+ 0, 320, 0, 230, 230, 231, 0, 0, 230, 0,
+ 0, 0, 0, 230, 230, 0, 230, 231, 0, 320,
+ 0, 320, 230, 230, 230, 0, 0, 230, 230, 230,
+ 230, 0, 230, 231, 0, 0, 231, 231, 0, 0,
+ 230, 230, 64, 0, 0, 231, 231, 231, 0, 0,
+ 230, 230, 0, 230, 231, 0, 231, 0, 0, 231,
+ 0, 231, 0, 0, 0, 231, 231, 0, 230, 0,
+ 0, 0, 0, 0, 0, 681, 682, 683, 231, 0,
+ 684, 685, 686, 0, 230, 687, 0, 231, 231, 124,
+ 0, 0, 231, 0, 0, 0, 0, 231, 231, 0,
+ 231, 124, 0, 688, 0, 689, 231, 231, 231, 0,
+ 0, 231, 231, 231, 231, 0, 231, 124, 0, 0,
+ 124, 124, 0, 0, 231, 231, 0, 230, 0, 124,
+ 124, 124, 0, 0, 231, 231, 0, 231, 124, 0,
+ 124, 0, 0, 124, 0, 124, 0, 0, 0, 124,
+ 124, 0, 231, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 124, 0, 0, 0, 0, 0, 231, 0,
+ 0, 124, 124, 176, 0, 0, 124, 0, 0, 0,
+ 0, 124, 124, 0, 124, 176, 0, 0, 0, 0,
+ 124, 124, 124, 0, 0, 124, 124, 124, 124, 0,
+ 124, 176, 0, 0, 176, 176, 0, 0, 124, 124,
+ 0, 231, 0, 176, 176, 176, 0, 0, 124, 124,
+ 0, 124, 176, 0, 176, 0, 0, 176, 0, 176,
+ 0, 0, 0, 176, 176, 0, 124, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 176, 0, 0, 0,
+ 0, 0, 124, 0, 0, 176, 176, 160, 0, 0,
+ 176, 0, 0, 0, 0, 176, 176, 0, 176, 160,
+ 0, 0, 0, 0, 176, 176, 176, 0, 0, 176,
+ 176, 176, 176, 0, 176, 160, 0, 0, 160, 160,
+ 0, 0, 176, 176, 0, 124, 0, 160, 160, 160,
+ 0, 0, 176, 176, 0, 176, 160, 0, 160, 0,
+ 0, 160, 0, 160, 0, 0, 0, 160, 160, 0,
+ 176, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 160, 0, 0, 0, 0, 0, 176, 0, 0, 160,
+ 160, 99, 0, 0, 160, 0, 0, 0, 0, 160,
+ 160, 0, 160, 99, 0, 0, 0, 0, 160, 160,
+ 160, 0, 0, 160, 160, 160, 160, 0, 160, 99,
+ 0, 0, 99, 99, 0, 0, 160, 160, 0, 176,
+ 0, 99, 99, 99, 0, 0, 160, 160, 0, 160,
+ 99, 0, 99, 0, 0, 99, 0, 99, 0, 0,
+ 0, 99, 99, 0, 160, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 99, 0, 0, 0, 0, 0,
+ 160, 0, 0, 99, 99, 188, 0, 0, 99, 0,
+ 0, 0, 0, 99, 99, 0, 99, 188, 0, 0,
+ 0, 0, 99, 99, 99, 0, 0, 99, 99, 99,
+ 99, 0, 99, 188, 0, 0, 188, 188, 0, 0,
+ 99, 99, 0, 160, 0, 188, 188, 188, 0, 0,
+ 99, 99, 0, 99, 188, 0, 188, 0, 0, 188,
+ 0, 188, 0, 0, 0, 188, 188, 0, 99, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 188, 0,
+ 0, 0, 0, 0, 99, 0, 0, 188, 188, 0,
+ 0, 0, 188, 0, 0, 0, 0, 188, 188, 0,
+ 188, 0, 0, 0, 0, 0, 188, 188, 188, 0,
+ 0, 188, 188, 188, 188, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 188, 188, 0, 99, 0, 0,
+ 0, 0, 233, 0, 188, 188, 0, 188, 0, 0,
+ 0, 233, 233, 0, 233, 0, 233, 0, 0, 233,
+ 233, 233, 188, 233, 233, 233, 233, 0, 233, 233,
+ 233, 233, 233, 233, 233, 233, 0, 233, 188, 0,
+ 0, 233, 233, 0, 233, 0, 0, 0, 233, 0,
+ 0, 0, 0, 0, 0, 233, 233, 0, 0, 0,
+ 0, 0, 233, 0, 233, 0, 233, 0, 0, 0,
+ 450, 233, 44, 163, 0, 164, 0, 233, 0, 233,
+ 0, 188, 0, 0, 233, 233, 171, 233, 0, 0,
+ 233, 45, 0, 233, 233, 0, 0, 0, 179, 0,
+ 0, 0, 0, 0, 0, 181, 0, 0, 0, 233,
+ 0, 0, 0, 233, 0, 233, 46, 450, 450, 0,
+ 233, 233, 0, 0, 0, 0, 0, 233, 0, 0,
+ 233, 233, 183, 233, 0, 233, 233, 0, 184, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 450, 233, 0, 191, 47, 233, 0, 0, 233,
+ 233, 0, 0, 0, 0, 0, 450, 0, 0, 0,
+ 0, 0, 0, 450, 450, 0, 450, 450, 0, 0,
+ 0, 192, 193, 0, 451, 0, 0, 0, 194, 0,
+ 0, 233, 48, 233, 255, 233, 0, 233, 0, 233,
+ 0, 233, 0, 255, 255, 233, 255, 0, 255, 0,
+ 0, 255, 255, 255, 0, 255, 255, 255, 255, 0,
+ 255, 255, 255, 255, 255, 255, 255, 255, 0, 255,
+ 0, 451, 451, 255, 255, 0, 255, 0, 0, 0,
+ 255, 0, 0, 0, 0, 0, 0, 255, 255, 0,
+ 0, 0, 0, 0, 255, 0, 255, 0, 255, 0,
+ 0, 0, 0, 255, 0, 451, 49, 0, 0, 255,
+ 0, 255, 0, 0, 0, 0, 255, 255, 0, 255,
+ 451, 0, 255, 0, 0, 255, 255, 451, 451, 0,
+ 451, 451, 0, 0, 58, 0, 0, 0, 0, 0,
+ 0, 255, 0, 195, 0, 255, 0, 255, 0, 0,
+ 0, 0, 255, 255, 58, 58, 0, 0, 0, 255,
+ 0, 0, 255, 255, 0, 255, 0, 255, 255, 0,
+ 0, 0, 0, 0, 0, 0, 0, 58, 0, 0,
+ 0, 0, 0, 0, 255, 0, 58, 58, 255, 0,
+ 0, 255, 255, 0, 0, 58, 58, 58, 0, 0,
+ 58, 58, 58, 58, 0, 58, 0, 0, 0, 0,
+ 0, 0, 0, 58, 58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 255, 58, 255, 219, 255, 0, 255,
+ 0, 255, 0, 255, 0, 219, 219, 255, 219, 0,
+ 219, 58, 0, 219, 219, 219, 0, 219, 219, 219,
+ 219, 0, 219, 219, 219, 219, 219, 219, 219, 219,
+ 0, 219, 0, 0, 0, 219, 219, 0, 219, 0,
+ 0, 128, 219, 0, 0, 452, 0, 0, 0, 219,
+ 219, 0, 0, 0, 129, 453, 219, 0, 219, 0,
+ 219, 0, 0, 0, 130, 219, 0, 454, 0, 0,
+ 0, 219, 0, 219, 455, 0, 0, 0, 219, 219,
+ 0, 219, 0, 0, 219, 0, 131, 219, 219, 0,
+ 0, 0, 0, 0, 0, 132, 58, 0, 0, 0,
+ 0, 0, 0, 219, 0, 196, 0, 219, 0, 219,
+ 0, 0, 0, 0, 219, 219, 58, 58, 0, 0,
+ 492, 219, 0, 0, 219, 219, 0, 219, 0, 219,
+ 219, 0, 0, 0, 0, 0, 0, 0, 0, 58,
+ 0, 0, 133, 456, 0, 0, 219, 0, 58, 58,
+ 219, 0, 0, 219, 219, 0, 0, 58, 58, 58,
+ 0, 0, 58, 58, 58, 58, 0, 58, 0, 0,
+ 0, 0, 0, 0, 0, 58, 58, 0, 0, 0,
+ 0, 0, 0, 0, 0, 219, 58, 219, 222, 219,
+ 0, 219, 0, 219, 0, 219, 0, 222, 222, 219,
+ 222, 0, 222, 58, 0, 222, 222, 222, 0, 222,
+ 222, 222, 222, 0, 222, 222, 222, 222, 222, 222,
+ 222, 222, 0, 222, 0, 0, 0, 222, 222, 0,
+ 222, 0, 0, 128, 222, 0, 0, 452, 0, 0,
+ 0, 222, 222, 0, 0, 0, 129, 453, 222, 0,
+ 222, 0, 222, 0, 0, 0, 130, 222, 0, 454,
+ 0, 0, 0, 222, 0, 222, 455, 0, 0, 0,
+ 222, 222, 0, 222, 0, 0, 222, 0, 131, 222,
+ 222, 0, 0, 0, 0, 0, 0, 132, 91, 0,
+ 0, 0, 0, 0, 0, 222, 0, 0, 0, 222,
+ 0, 222, 0, 0, 0, 0, 222, 222, 92, 0,
+ 0, 0, 0, 222, 0, 0, 222, 222, 0, 222,
+ 0, 222, 222, 0, 0, 0, 0, 0, 0, 0,
+ 0, 93, 0, 0, 133, 456, 0, 0, 222, 0,
+ 94, 95, 222, 0, 0, 222, 222, 0, 0, 96,
+ 97, 98, 0, 0, 99, 0, 100, 101, 0, 102,
+ 0, 0, 0, 0, 0, 0, 0, 103, 104, 0,
+ 0, 0, 0, 0, 0, 0, 0, 222, 0, 222,
+ 625, 222, 0, 222, 0, 222, 0, 222, 0, 44,
+ 163, 222, 164, 0, 165, 105, 0, 166, 167, 168,
+ 0, 169, 170, 171, 172, 0, 173, 174, 45, 626,
+ 175, 176, 177, 178, 0, 179, 0, 0, 0, 627,
+ 180, 0, 181, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 46, 68, 0, 0, 0, 0, 0,
+ 182, 0, 628, 0, 629, 0, 0, 0, 0, 183,
+ 0, 0, 0, 0, 0, 184, 0, 185, 0, 0,
+ 0, 0, 186, 187, 0, 188, 0, 0, 190, 0,
+ 0, 191, 47, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 630, 0, 0,
+ 0, 631, 0, 632, 0, 0, 0, 0, 192, 193,
+ 0, 0, 0, 0, 0, 194, 0, 0, 633, 48,
+ 0, 634, 0, 69, 635, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 196, 0, 0, 326, 0, 0, 0, 197, 198, 0,
+ 0, 44, 163, 327, 164, 0, 165, 0, 0, 166,
+ 167, 168, 0, 169, 170, 171, 172, 0, 173, 174,
+ 45, 0, 175, 176, 177, 178, 0, 179, 0, 199,
+ 0, 200, 180, 201, 181, 202, 0, 203, 0, 204,
+ 0, 0, 0, 49, 0, 46, 68, 0, 0, 0,
+ 0, 0, 182, 0, 0, 0, 0, 0, 0, 0,
+ 0, 183, 0, 0, 0, 0, 0, 184, 0, 185,
+ 0, 0, 0, 0, 186, 187, 0, 188, 0, 189,
+ 190, 0, 0, 191, 47, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 192, 193, 0, 0, 0, 0, 0, 194, 0, 0,
+ 0, 48, 0, 0, 0, 69, 0, 195, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 196, 0, 0, 705, 0, 0, 0, 197,
+ 198, 0, 0, 44, 163, 0, 164, 0, 165, 0,
+ 0, 166, 167, 168, 0, 169, 170, 171, 172, 0,
+ 173, 174, 45, 0, 175, 176, 177, 178, 0, 179,
+ 0, 199, 0, 200, 180, 201, 181, 202, 0, 203,
+ 0, 204, 0, 0, 0, 49, 0, 46, 68, 0,
+ 0, 0, 0, 0, 182, 0, 0, 0, 0, 0,
+ 0, 0, 0, 183, 0, 0, 0, 0, 0, 184,
+ 0, 185, 0, 0, 0, 0, 186, 187, 0, 188,
+ 0, 189, 190, 0, 0, 191, 47, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 192, 193, 0, 0, 0, 0, 0, 194,
+ 0, 0, 0, 48, 0, 0, 0, 69, 0, 195,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 196, 0, 0, 0, 0, 0,
+ 0, 197, 198, 0, 0, 44, 163, 0, 164, 0,
+ 165, 0, 0, 166, 167, 168, 0, 169, 170, 171,
+ 172, 0, 173, 174, 45, 0, 175, 176, 177, 178,
+ 0, 179, 0, 199, 0, 200, 180, 201, 181, 202,
+ 0, 203, 0, 204, 0, 0, 0, 49, 0, 46,
+ 68, 0, 0, 0, 0, 0, 182, 0, 0, 0,
+ 0, 0, 0, 0, 0, 183, 0, 0, 0, 0,
+ 0, 184, 0, 185, 0, 0, 0, 0, 186, 187,
+ 0, 188, 0, 189, 190, 0, 0, 191, 47, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 192, 193, 0, 0, 0, 0,
+ 0, 194, 0, 0, 0, 48, 0, 0, 0, 69,
+ 0, 195, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 196, 594, 610, 0,
+ 0, 0, 0, 197, 198, 0, 0, 44, 163, 0,
+ 164, 0, 165, 0, 0, 166, 167, 168, 0, 169,
+ 170, 171, 172, 0, 173, 174, 45, 0, 175, 176,
+ 177, 178, 0, 179, 0, 199, 0, 200, 180, 201,
+ 181, 202, 0, 203, 0, 204, 0, 0, 0, 49,
+ 0, 46, 68, 0, 0, 0, 0, 0, 182, 0,
+ 0, 0, 0, 0, 0, 0, 0, 183, 0, 0,
+ 0, 0, 0, 184, 0, 185, 0, 0, 0, 0,
+ 186, 187, 0, 188, 0, 189, 190, 0, 0, 191,
+ 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 192, 193, 0, 0,
+ 0, 0, 0, 194, 0, 0, 0, 48, 0, 0,
+ 0, 69, 0, 195, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 196, 594,
+ 0, 0, 0, 0, 0, 197, 198, 0, 0, 44,
+ 163, 0, 164, 0, 165, 0, 0, 166, 167, 168,
+ 0, 169, 170, 171, 172, 0, 173, 174, 45, 0,
+ 175, 176, 177, 178, 0, 179, 0, 199, 0, 200,
+ 180, 201, 181, 202, 0, 203, 0, 204, 0, 0,
+ 0, 49, 0, 46, 68, 0, 0, 0, 0, 0,
+ 182, 0, 0, 0, 0, 0, 0, 0, 0, 183,
+ 0, 0, 0, 0, 0, 184, 0, 185, 0, 0,
+ 0, 0, 186, 187, 0, 188, 0, 189, 190, 0,
+ 0, 191, 47, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 192, 193,
+ 0, 0, 0, 0, 0, 194, 0, 0, 0, 48,
+ 0, 0, 0, 69, 0, 195, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 196, 0, 0, 0, 0, 0, 90, 197, 198, 0,
+ 0, 44, 163, 0, 164, 0, 165, 0, 0, 166,
+ 167, 168, 0, 169, 170, 171, 172, 0, 173, 174,
+ 45, 0, 175, 176, 177, 178, 0, 179, 0, 199,
+ 0, 200, 180, 201, 181, 202, 91, 203, 0, 204,
+ 0, 0, 0, 49, 0, 46, 68, 0, 0, 0,
+ 0, 0, 182, 0, 0, 0, 92, 0, 0, 0,
+ 0, 183, 0, 0, 0, 0, 0, 184, 0, 185,
+ 0, 0, 0, 0, 186, 187, 0, 188, 0, 93,
+ 190, 0, 0, 191, 47, 0, 0, 0, 94, 95,
+ 0, 0, 0, 0, 0, 0, 0, 96, 97, 98,
+ 0, 0, 99, 0, 100, 101, 0, 102, 0, 0,
+ 192, 193, 0, 0, 0, 103, 104, 194, 0, 0,
+ 0, 48, 0, 0, 0, 69, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 196, 105, 0, 0, 0, 0, 0, 197,
+ 198, 0, 0, 44, 163, 0, 164, 0, 165, 0,
+ 0, 166, 167, 168, 0, 169, 170, 171, 172, 0,
+ 173, 174, 45, 0, 175, 176, 177, 178, 0, 179,
+ 0, 199, 0, 200, 180, 201, 181, 202, 0, 203,
+ 0, 204, 0, 0, 0, 49, 0, 46, 68, 0,
+ 0, 0, 0, 0, 182, 58, 0, 0, 0, 0,
+ 0, 0, 0, 183, 0, 0, 0, 0, 0, 184,
+ 0, 185, 0, 0, 0, 0, 186, 187, 0, 188,
+ 0, 0, 190, 58, 0, 191, 47, 0, 0, 0,
+ 0, 0, 0, 0, 0, 58, 58, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 58, 0, 0, 0,
+ 0, 0, 192, 193, 0, 58, 0, 0, 0, 194,
+ 0, 0, 0, 48, 0, 0, 0, 69, 58, 0,
+ 0, 0, 0, 0, 0, 0, 0, 58, 58, 0,
+ 0, 0, 58, 0, 196, 0, 0, 58, 58, 0,
+ 0, 0, 0, 0, 0, 0, 58, 58, 58, 0,
+ 0, 58, 0, 58, 58, 0, 58, 0, 0, 0,
+ 0, 0, 0, 0, 58, 58, 97, 0, 0, 0,
+ 0, 0, 0, 199, 58, 200, 0, 201, 0, 202,
+ 0, 203, 97, 204, 0, 97, 97, 49, 0, 0,
+ 0, 0, 58, 0, 97, 97, 97, 0, 0, 0,
+ 0, 0, 0, 97, 0, 97, 0, 0, 97, 0,
+ 97, 0, 0, 0, 97, 97, 0, 0, 0, 0,
+ 0, 0, 97, 0, 0, 97, 0, 97, 0, 0,
+ 0, 0, 0, 0, 0, 0, 97, 97, 0, 0,
+ 0, 0, 0, 0, 0, 0, 97, 97, 100, 97,
+ 0, 0, 0, 0, 0, 97, 97, 97, 0, 0,
+ 97, 97, 97, 97, 100, 97, 0, 100, 100, 0,
+ 0, 0, 0, 97, 97, 0, 100, 100, 100, 0,
+ 0, 0, 0, 97, 97, 100, 97, 100, 0, 0,
+ 100, 0, 100, 0, 0, 0, 100, 100, 0, 0,
+ 0, 97, 0, 0, 100, 0, 0, 0, 0, 100,
+ 0, 0, 0, 0, 0, 0, 0, 97, 100, 100,
+ 0, 0, 0, 0, 0, 0, 0, 0, 100, 100,
+ 0, 100, 0, 101, 0, 0, 0, 100, 100, 100,
+ 0, 0, 100, 100, 100, 100, 0, 100, 0, 101,
+ 0, 0, 101, 101, 0, 100, 100, 0, 0, 0,
+ 97, 101, 101, 101, 0, 100, 100, 0, 100, 0,
+ 101, 0, 101, 0, 0, 101, 0, 101, 0, 0,
+ 0, 101, 101, 100, 0, 0, 0, 0, 0, 101,
+ 0, 0, 0, 0, 101, 0, 0, 0, 0, 100,
+ 0, 0, 0, 101, 101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 101, 101, 123, 101, 0, 0, 0,
+ 0, 0, 101, 101, 101, 0, 0, 101, 101, 101,
+ 101, 123, 101, 0, 123, 123, 0, 0, 0, 0,
+ 101, 101, 100, 123, 123, 123, 0, 0, 0, 0,
+ 101, 101, 123, 101, 123, 0, 0, 123, 0, 123,
+ 0, 0, 0, 123, 123, 0, 0, 0, 101, 0,
+ 0, 0, 0, 0, 0, 0, 123, 0, 0, 0,
+ 0, 0, 0, 0, 101, 123, 123, 0, 0, 0,
+ 0, 0, 0, 0, 0, 123, 123, 0, 123, 0,
+ 102, 0, 0, 0, 123, 123, 123, 0, 0, 123,
+ 123, 123, 123, 0, 123, 0, 102, 0, 0, 102,
+ 102, 0, 123, 123, 0, 0, 0, 101, 102, 102,
+ 102, 0, 123, 123, 0, 123, 0, 102, 0, 102,
+ 0, 0, 102, 0, 102, 0, 0, 0, 102, 102,
+ 123, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 102, 0, 0, 0, 0, 123, 0, 0, 0,
+ 102, 102, 0, 0, 0, 0, 0, 0, 0, 0,
+ 102, 102, 211, 102, 0, 0, 0, 0, 0, 102,
+ 102, 102, 0, 0, 102, 102, 102, 102, 211, 102,
+ 0, 211, 211, 0, 0, 0, 0, 102, 102, 123,
+ 211, 211, 211, 0, 0, 0, 0, 102, 102, 211,
+ 102, 211, 211, 0, 211, 0, 211, 0, 0, 0,
+ 211, 211, 0, 0, 0, 102, 0, 0, 0, 0,
+ 0, 0, 0, 211, 0, 0, 0, 0, 0, 0,
+ 0, 102, 211, 211, 0, 0, 0, 0, 0, 0,
+ 0, 0, 211, 211, 0, 211, 0, 0, 0, 0,
+ 0, 211, 211, 211, 0, 0, 211, 0, 211, 211,
+ 0, 211, 0, 0, 0, 0, 0, 0, 0, 211,
+ 211, 0, 212, 0, 102, 0, 0, 0, 0, 211,
+ 211, 0, 211, 0, 0, 0, 0, 0, 212, 0,
+ 0, 212, 212, 0, 0, 0, 0, 211, 0, 0,
+ 212, 212, 212, 0, 0, 0, 0, 0, 211, 212,
+ 0, 212, 212, 0, 212, 0, 212, 0, 0, 0,
+ 212, 212, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 212, 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 212, 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 212, 103, 212, 211, 0, 0, 0,
+ 0, 212, 212, 212, 0, 0, 212, 0, 212, 212,
+ 103, 212, 0, 103, 103, 0, 0, 0, 0, 212,
+ 212, 0, 103, 103, 103, 0, 0, 0, 0, 212,
+ 212, 103, 212, 103, 0, 0, 103, 0, 103, 0,
+ 0, 0, 103, 103, 0, 0, 0, 212, 0, 0,
+ 0, 0, 0, 0, 0, 103, 0, 0, 212, 0,
+ 0, 0, 0, 0, 103, 103, 0, 0, 0, 0,
+ 0, 0, 0, 0, 103, 103, 0, 103, 0, 138,
+ 0, 0, 0, 103, 103, 103, 0, 0, 103, 103,
+ 103, 103, 0, 103, 0, 138, 0, 0, 138, 138,
+ 0, 103, 103, 0, 0, 0, 212, 138, 138, 138,
+ 0, 103, 103, 0, 103, 0, 138, 0, 138, 0,
+ 0, 138, 0, 138, 0, 0, 0, 138, 138, 103,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 138, 0, 0, 0, 0, 103, 0, 0, 0, 138,
+ 138, 0, 0, 0, 0, 0, 0, 0, 0, 138,
+ 138, 227, 138, 0, 0, 0, 0, 0, 138, 138,
+ 138, 0, 0, 138, 138, 138, 138, 227, 138, 0,
+ 227, 227, 0, 0, 0, 0, 138, 138, 103, 227,
+ 227, 227, 0, 0, 0, 0, 138, 138, 227, 138,
+ 227, 0, 0, 227, 0, 227, 0, 0, 0, 227,
+ 227, 0, 0, 0, 138, 0, 0, 0, 0, 0,
+ 0, 0, 227, 0, 0, 0, 0, 0, 0, 0,
+ 138, 227, 227, 0, 0, 0, 0, 0, 0, 0,
+ 0, 227, 227, 0, 227, 0, 174, 0, 0, 0,
+ 227, 227, 227, 0, 0, 227, 227, 227, 227, 0,
+ 227, 0, 174, 0, 0, 174, 174, 0, 227, 227,
+ 0, 0, 0, 138, 174, 174, 174, 0, 227, 227,
+ 0, 227, 0, 174, 0, 174, 0, 0, 174, 0,
+ 174, 0, 0, 0, 174, 174, 227, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 174, 0, 0,
+ 0, 0, 227, 0, 0, 0, 174, 174, 0, 0,
+ 0, 0, 0, 0, 0, 0, 174, 174, 235, 174,
+ 0, 0, 0, 0, 0, 174, 174, 174, 0, 0,
+ 174, 174, 174, 174, 235, 174, 0, 235, 235, 0,
+ 0, 0, 0, 174, 174, 227, 235, 235, 235, 0,
+ 0, 0, 0, 174, 174, 235, 174, 235, 0, 0,
+ 235, 0, 235, 0, 0, 0, 235, 235, 0, 0,
+ 0, 174, 0, 0, 0, 0, 0, 0, 0, 235,
+ 0, 0, 0, 0, 0, 0, 0, 174, 235, 235,
+ 0, 0, 0, 0, 0, 0, 0, 0, 235, 235,
+ 0, 235, 0, 206, 0, 0, 0, 235, 235, 235,
+ 0, 0, 235, 235, 235, 235, 0, 235, 0, 206,
+ 0, 0, 206, 206, 0, 235, 235, 0, 0, 0,
+ 174, 206, 206, 206, 0, 235, 235, 0, 235, 0,
+ 206, 0, 206, 0, 0, 206, 0, 206, 0, 0,
+ 0, 206, 206, 235, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 206, 0, 0, 0, 0, 235,
+ 0, 0, 0, 206, 206, 0, 0, 0, 0, 0,
+ 0, 0, 0, 206, 206, 154, 206, 0, 0, 0,
+ 0, 0, 206, 206, 206, 0, 0, 206, 206, 206,
+ 206, 154, 206, 0, 154, 154, 0, 0, 0, 0,
+ 206, 206, 235, 154, 154, 154, 0, 0, 0, 0,
+ 206, 206, 154, 206, 154, 0, 0, 154, 0, 154,
+ 0, 0, 0, 154, 154, 0, 0, 0, 206, 0,
+ 0, 0, 0, 0, 0, 0, 154, 0, 0, 0,
+ 0, 0, 0, 0, 206, 154, 154, 0, 0, 0,
+ 0, 0, 0, 0, 0, 154, 154, 0, 154, 0,
+ 157, 0, 0, 0, 154, 154, 154, 0, 0, 154,
+ 154, 154, 154, 0, 154, 0, 157, 0, 0, 157,
+ 157, 0, 154, 154, 0, 0, 0, 206, 157, 157,
+ 157, 0, 154, 154, 0, 154, 0, 157, 0, 157,
+ 0, 0, 157, 0, 157, 0, 0, 0, 157, 157,
+ 154, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 157, 0, 0, 0, 0, 154, 0, 0, 0,
+ 157, 157, 0, 0, 0, 0, 0, 0, 0, 0,
+ 157, 157, 58, 157, 0, 0, 0, 0, 0, 157,
+ 157, 157, 0, 0, 157, 157, 157, 157, 58, 157,
+ 0, 58, 58, 0, 0, 0, 0, 157, 157, 154,
+ 58, 58, 58, 0, 0, 0, 0, 157, 157, 125,
+ 157, 58, 0, 0, 58, 0, 58, 0, 0, 0,
+ 58, 58, 0, 0, 0, 157, 0, 0, 0, 0,
+ 0, 0, 0, 58, 0, 0, 0, 0, 0, 0,
+ 0, 157, 58, 58, 0, 0, 0, 0, 0, 0,
+ 0, 0, 58, 58, 0, 58, 0, 58, 0, 0,
+ 0, 58, 58, 58, 0, 0, 58, 58, 58, 58,
+ 0, 58, 0, 58, 0, 0, 58, 58, 0, 58,
+ 58, 0, 0, 0, 157, 58, 58, 58, 0, 58,
+ 58, 0, 58, 0, 126, 0, 58, 0, 0, 58,
+ 0, 58, 0, 0, 0, 58, 58, 58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 58, 0,
+ 0, 0, 0, 0, 0, 0, 0, 58, 58, 0,
+ 0, 0, 0, 0, 0, 0, 0, 58, 58, 210,
+ 58, 0, 0, 0, 0, 0, 58, 58, 58, 0,
+ 0, 58, 58, 58, 58, 210, 58, 0, 210, 210,
+ 0, 0, 0, 0, 58, 58, 58, 210, 210, 210,
+ 0, 0, 0, 0, 58, 58, 210, 58, 210, 210,
+ 0, 210, 0, 210, 0, 0, 0, 210, 210, 0,
+ 0, 0, 58, 0, 0, 0, 0, 0, 0, 0,
+ 210, 0, 0, 0, 0, 0, 0, 0, 0, 210,
+ 210, 0, 0, 0, 0, 0, 0, 0, 0, 210,
+ 210, 0, 210, 0, 58, 0, 0, 0, 210, 210,
+ 210, 0, 0, 210, 0, 210, 210, 0, 210, 0,
+ 58, 0, 0, 58, 58, 0, 210, 210, 0, 0,
+ 0, 58, 58, 58, 58, 0, 210, 210, 0, 210,
+ 0, 139, 0, 58, 0, 0, 58, 0, 58, 0,
+ 0, 0, 58, 58, 210, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 58, 0, 0, 0, 0,
+ 0, 0, 0, 0, 58, 58, 0, 0, 0, 0,
+ 0, 0, 0, 0, 58, 58, 58, 58, 0, 0,
+ 0, 0, 0, 58, 58, 58, 0, 0, 58, 58,
+ 58, 58, 58, 58, 0, 58, 58, 0, 0, 0,
+ 0, 58, 58, 210, 58, 58, 58, 0, 0, 0,
+ 0, 58, 58, 140, 58, 58, 0, 0, 58, 0,
+ 58, 0, 0, 0, 58, 58, 0, 0, 0, 58,
+ 0, 0, 0, 0, 0, 0, 0, 58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 58, 58, 0, 0,
+ 0, 0, 0, 470, 470, 0, 58, 58, 0, 58,
+ 0, 209, 0, 0, 0, 58, 58, 58, 0, 0,
+ 58, 58, 58, 58, 0, 58, 0, 209, 0, 0,
+ 209, 209, 0, 58, 58, 0, 0, 0, 58, 209,
+ 209, 209, 0, 58, 58, 0, 58, 0, 209, 470,
+ 209, 0, 0, 209, 0, 209, 0, 0, 0, 209,
+ 209, 58, 0, 0, 0, 470, 0, 0, 0, 0,
+ 0, 470, 209, 0, 0, 0, 480, 480, 470, 0,
+ 0, 209, 209, 0, 0, 0, 0, 0, 0, 0,
+ 0, 209, 209, 0, 209, 0, 470, 470, 0, 0,
+ 209, 209, 209, 0, 0, 209, 0, 209, 209, 0,
+ 209, 0, 0, 0, 0, 0, 0, 0, 209, 209,
+ 58, 0, 480, 0, 0, 0, 385, 385, 209, 209,
+ 470, 209, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 480, 470, 209, 0, 0, 0,
+ 470, 480, 470, 470, 0, 470, 470, 470, 470, 470,
+ 470, 470, 470, 470, 470, 0, 470, 470, 0, 480,
+ 480, 0, 385, 0, 0, 0, 0, 470, 0, 470,
+ 0, 470, 0, 0, 0, 470, 0, 470, 0, 0,
+ 0, 0, 0, 0, 385, 0, 0, 0, 0, 362,
+ 362, 385, 0, 480, 0, 209, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 480, 385,
+ 385, 0, 0, 480, 0, 480, 480, 480, 480, 480,
+ 480, 480, 480, 480, 480, 480, 480, 480, 0, 480,
+ 480, 0, 0, 0, 0, 362, 0, 0, 0, 0,
+ 480, 0, 480, 385, 480, 0, 0, 0, 480, 0,
+ 480, 0, 0, 0, 0, 0, 0, 362, 385, 0,
+ 0, 0, 0, 384, 362, 385, 385, 384, 385, 385,
+ 385, 385, 385, 385, 385, 385, 385, 385, 0, 385,
+ 385, 0, 362, 362, 0, 0, 319, 319, 0, 0,
+ 385, 0, 385, 0, 385, 0, 0, 0, 385, 0,
+ 385, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 362, 0, 0, 0,
+ 0, 0, 0, 0, 415, 415, 0, 0, 0, 0,
+ 0, 362, 319, 0, 0, 0, 362, 0, 362, 362,
+ 0, 362, 362, 362, 362, 362, 362, 362, 362, 362,
+ 362, 0, 362, 362, 319, 0, 0, 0, 0, 0,
+ 0, 319, 0, 362, 0, 362, 0, 362, 0, 0,
+ 415, 362, 0, 362, 0, 0, 0, 0, 0, 319,
+ 319, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 415, 0, 0, 0, 0, 0, 0, 415,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 319, 0, 0, 0, 415, 415, 0,
+ 0, 416, 416, 0, 0, 0, 0, 0, 319, 0,
+ 0, 0, 0, 0, 0, 319, 319, 319, 319, 319,
+ 319, 319, 319, 319, 319, 319, 319, 319, 0, 319,
+ 319, 415, 0, 0, 0, 0, 0, 0, 0, 0,
+ 319, 0, 319, 0, 319, 0, 415, 416, 319, 0,
+ 319, 417, 417, 415, 415, 0, 415, 415, 415, 415,
+ 415, 415, 415, 415, 415, 415, 0, 415, 415, 416,
+ 0, 0, 0, 0, 0, 0, 416, 0, 415, 0,
+ 415, 0, 415, 0, 0, 0, 415, 0, 415, 0,
+ 0, 0, 0, 0, 416, 416, 0, 417, 44, 44,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 417,
+ 0, 0, 0, 0, 0, 0, 417, 0, 416, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 416, 417, 417, 0, 0, 423, 423,
+ 416, 416, 0, 416, 416, 416, 416, 416, 416, 416,
+ 416, 416, 416, 0, 416, 416, 44, 0, 0, 0,
+ 0, 0, 0, 44, 0, 416, 0, 416, 417, 416,
+ 0, 0, 0, 416, 0, 416, 0, 0, 0, 0,
+ 0, 44, 44, 417, 423, 0, 0, 0, 424, 424,
+ 417, 417, 0, 417, 417, 417, 417, 417, 417, 417,
+ 417, 417, 0, 0, 417, 417, 423, 0, 0, 0,
+ 0, 0, 0, 423, 0, 417, 0, 417, 0, 417,
+ 0, 0, 0, 417, 0, 417, 0, 0, 0, 0,
+ 44, 423, 423, 0, 424, 44, 0, 0, 44, 44,
+ 44, 0, 44, 44, 44, 44, 44, 44, 44, 44,
+ 0, 44, 44, 0, 0, 0, 424, 0, 0, 0,
+ 425, 425, 44, 424, 44, 423, 44, 0, 0, 0,
+ 44, 0, 44, 0, 0, 0, 0, 0, 0, 0,
+ 423, 424, 424, 0, 0, 0, 0, 423, 423, 0,
+ 423, 423, 423, 423, 423, 423, 423, 0, 0, 0,
+ 0, 423, 423, 426, 426, 0, 425, 0, 0, 0,
+ 0, 0, 423, 0, 423, 424, 423, 0, 0, 0,
+ 423, 0, 423, 0, 0, 0, 0, 0, 425, 0,
+ 424, 0, 0, 0, 0, 425, 0, 424, 424, 0,
+ 424, 424, 424, 424, 424, 424, 424, 0, 0, 426,
+ 0, 424, 424, 425, 425, 427, 427, 0, 0, 0,
+ 0, 0, 424, 0, 424, 0, 424, 0, 0, 0,
+ 424, 426, 424, 0, 0, 0, 0, 0, 426, 0,
+ 0, 0, 0, 0, 0, 0, 0, 425, 0, 0,
+ 0, 0, 0, 0, 0, 0, 426, 426, 0, 0,
+ 0, 427, 425, 0, 0, 428, 428, 0, 0, 425,
+ 425, 0, 425, 425, 425, 425, 425, 425, 425, 0,
+ 0, 0, 0, 427, 425, 0, 0, 0, 0, 0,
+ 426, 0, 0, 0, 425, 0, 425, 0, 425, 0,
+ 0, 0, 425, 0, 425, 426, 0, 0, 427, 427,
+ 0, 428, 426, 426, 0, 426, 426, 426, 426, 426,
+ 426, 426, 0, 0, 0, 0, 0, 426, 0, 0,
+ 0, 0, 0, 428, 429, 429, 0, 426, 0, 426,
+ 0, 426, 427, 0, 0, 426, 0, 426, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 427, 428, 428,
+ 0, 0, 0, 0, 427, 427, 0, 427, 427, 427,
+ 427, 427, 427, 427, 0, 0, 0, 0, 0, 427,
+ 429, 0, 0, 0, 430, 430, 0, 0, 0, 427,
+ 0, 427, 428, 427, 0, 0, 0, 427, 0, 427,
+ 0, 0, 429, 0, 0, 0, 0, 428, 0, 0,
+ 0, 0, 0, 0, 428, 428, 0, 428, 428, 428,
+ 428, 428, 428, 428, 0, 0, 0, 429, 429, 428,
+ 430, 0, 0, 0, 431, 431, 0, 0, 0, 428,
+ 0, 428, 0, 428, 0, 0, 0, 428, 0, 428,
+ 0, 0, 430, 0, 0, 0, 0, 0, 0, 0,
+ 0, 429, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 429, 430, 430, 0,
+ 431, 0, 0, 429, 429, 0, 429, 429, 429, 429,
+ 429, 429, 429, 0, 0, 0, 0, 0, 429, 0,
+ 0, 0, 431, 432, 432, 0, 0, 0, 429, 0,
+ 429, 430, 429, 0, 0, 0, 429, 0, 429, 0,
+ 0, 0, 0, 0, 0, 0, 430, 431, 431, 0,
+ 0, 0, 0, 430, 430, 0, 430, 430, 0, 0,
+ 430, 430, 430, 0, 0, 0, 0, 0, 430, 432,
+ 0, 0, 0, 433, 433, 0, 0, 0, 430, 0,
+ 430, 431, 430, 0, 0, 0, 430, 0, 430, 0,
+ 0, 432, 0, 0, 0, 0, 431, 0, 0, 0,
+ 0, 0, 0, 431, 431, 0, 431, 431, 0, 0,
+ 431, 431, 431, 0, 0, 0, 432, 432, 431, 433,
+ 0, 0, 0, 434, 434, 0, 0, 0, 431, 0,
+ 431, 0, 431, 0, 0, 0, 431, 0, 431, 0,
+ 0, 433, 0, 0, 0, 0, 0, 0, 0, 0,
+ 432, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 435, 435, 0, 0, 0, 432, 433, 433, 0, 434,
+ 0, 0, 432, 432, 0, 432, 432, 0, 0, 432,
+ 432, 432, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 434, 0, 0, 0, 480, 480, 432, 0, 432,
+ 433, 432, 0, 0, 0, 432, 435, 432, 0, 0,
+ 0, 0, 0, 0, 0, 433, 434, 434, 0, 0,
+ 0, 0, 433, 433, 0, 433, 433, 0, 435, 433,
+ 433, 433, 442, 442, 0, 0, 0, 0, 0, 0,
+ 0, 480, 0, 0, 0, 0, 0, 433, 0, 433,
+ 434, 433, 0, 435, 435, 433, 0, 433, 0, 0,
+ 0, 0, 0, 480, 0, 434, 0, 0, 0, 0,
+ 0, 0, 434, 434, 0, 434, 434, 0, 442, 434,
+ 434, 434, 436, 436, 0, 0, 0, 435, 480, 480,
+ 0, 0, 0, 0, 0, 0, 0, 434, 0, 434,
+ 442, 434, 435, 0, 0, 434, 0, 434, 0, 435,
+ 435, 0, 435, 435, 0, 0, 435, 435, 435, 438,
+ 438, 0, 480, 0, 0, 442, 442, 0, 436, 0,
+ 0, 0, 439, 439, 435, 0, 435, 480, 435, 0,
+ 0, 0, 0, 0, 480, 480, 0, 480, 480, 0,
+ 436, 480, 480, 480, 0, 0, 0, 0, 0, 442,
+ 0, 0, 0, 0, 0, 438, 0, 0, 0, 480,
+ 0, 480, 0, 480, 442, 436, 436, 0, 439, 0,
+ 0, 442, 442, 0, 442, 442, 0, 438, 442, 442,
+ 442, 0, 0, 0, 0, 0, 0, 0, 440, 440,
+ 439, 0, 0, 0, 0, 0, 442, 0, 442, 436,
+ 442, 0, 438, 438, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 436, 439, 439, 0, 0, 0,
+ 0, 436, 436, 0, 436, 436, 0, 0, 436, 436,
+ 436, 441, 441, 0, 440, 0, 438, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 436, 0, 436, 439,
+ 436, 438, 0, 0, 0, 0, 440, 0, 438, 438,
+ 0, 438, 438, 0, 439, 438, 438, 438, 0, 0,
+ 0, 439, 439, 0, 439, 439, 0, 441, 439, 439,
+ 439, 440, 440, 438, 0, 438, 0, 438, 0, 0,
+ 0, 0, 0, 0, 0, 0, 439, 0, 439, 441,
+ 439, 437, 437, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 440, 0, 0, 0, 0,
+ 0, 0, 0, 0, 441, 441, 0, 0, 0, 0,
+ 440, 0, 0, 0, 0, 0, 0, 440, 440, 0,
+ 440, 440, 0, 0, 440, 440, 440, 437, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 441, 0,
+ 0, 0, 440, 0, 440, 0, 440, 0, 0, 437,
+ 0, 0, 0, 441, 0, 0, 0, 0, 0, 0,
+ 441, 441, 0, 441, 441, 0, 0, 441, 441, 441,
+ 0, 0, 0, 0, 437, 437, 0, 0, 0, 0,
+ 0, 21, 0, 0, 0, 441, 0, 441, 0, 441,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 437, 21,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 21, 21, 437, 0, 0, 0, 0, 0, 0,
+ 437, 437, 21, 437, 437, 0, 0, 437, 437, 437,
+ 0, 21, 0, 0, 0, 0, 0, 0, 0, 0,
+ 21, 0, 0, 19, 21, 437, 0, 437, 0, 437,
+ 0, 0, 0, 21, 21, 0, 0, 0, 21, 0,
+ 0, 0, 0, 21, 21, 0, 0, 0, 21, 0,
+ 0, 19, 21, 21, 21, 0, 0, 21, 0, 21,
+ 21, 0, 21, 19, 19, 0, 0, 0, 0, 0,
+ 21, 21, 0, 0, 19, 0, 0, 0, 0, 0,
+ 21, 0, 0, 19, 0, 0, 0, 0, 0, 0,
+ 0, 0, 19, 0, 0, 20, 19, 0, 21, 0,
+ 0, 0, 0, 0, 0, 19, 19, 0, 0, 0,
+ 19, 0, 0, 0, 21, 19, 19, 0, 0, 0,
+ 19, 0, 0, 20, 19, 19, 19, 0, 0, 19,
+ 0, 19, 19, 0, 19, 20, 20, 0, 0, 0,
+ 0, 0, 19, 19, 0, 0, 20, 0, 0, 0,
+ 0, 0, 19, 0, 0, 20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 20, 0, 0, 7, 20, 0,
+ 19, 0, 0, 0, 0, 0, 0, 20, 20, 0,
+ 0, 0, 20, 0, 0, 0, 19, 20, 20, 0,
+ 0, 0, 20, 0, 0, 7, 20, 20, 20, 0,
+ 0, 20, 0, 20, 20, 0, 20, 7, 7, 0,
+ 0, 0, 0, 0, 20, 20, 0, 0, 7, 0,
+ 0, 0, 0, 0, 20, 0, 0, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 7, 0, 0, 8,
+ 7, 0, 20, 0, 0, 0, 0, 0, 0, 7,
+ 7, 0, 0, 0, 7, 0, 0, 0, 20, 7,
+ 7, 0, 0, 0, 0, 0, 0, 8, 7, 7,
+ 7, 0, 0, 7, 0, 7, 7, 0, 7, 8,
+ 8, 0, 0, 0, 0, 0, 7, 7, 0, 0,
+ 8, 0, 0, 0, 0, 0, 7, 0, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0,
+ 0, 50, 8, 0, 7, 0, 0, 0, 0, 0,
+ 0, 8, 8, 0, 0, 0, 8, 0, 0, 0,
+ 7, 8, 8, 0, 0, 0, 0, 0, 0, 50,
+ 8, 8, 8, 0, 0, 8, 0, 8, 8, 0,
+ 8, 50, 50, 0, 0, 0, 0, 0, 8, 8,
+ 0, 0, 50, 0, 0, 0, 0, 0, 8, 0,
+ 0, 50, 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 0, 0, 89, 50, 0, 8, 0, 0, 0,
+ 0, 0, 0, 50, 50, 0, 0, 0, 50, 0,
+ 0, 0, 8, 50, 50, 0, 0, 0, 0, 0,
+ 0, 89, 50, 50, 50, 0, 0, 50, 0, 50,
+ 50, 0, 50, 89, 89, 0, 0, 0, 0, 0,
+ 50, 50, 89, 0, 89, 0, 0, 0, 0, 0,
+ 50, 0, 0, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 46, 89, 0, 50, 0,
+ 0, 0, 0, 0, 0, 89, 89, 0, 0, 0,
+ 89, 0, 0, 0, 50, 89, 89, 0, 0, 0,
+ 0, 0, 0, 46, 89, 89, 89, 0, 0, 89,
+ 0, 89, 89, 0, 89, 46, 46, 0, 0, 0,
+ 0, 0, 89, 89, 0, 0, 46, 0, 0, 0,
+ 0, 0, 89, 0, 0, 46, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 47, 46, 0,
+ 89, 0, 0, 0, 0, 0, 0, 46, 46, 0,
+ 0, 0, 46, 0, 0, 0, 89, 46, 46, 0,
+ 0, 0, 0, 0, 0, 47, 46, 46, 46, 0,
+ 0, 46, 0, 46, 46, 0, 46, 47, 47, 0,
+ 0, 0, 0, 0, 46, 46, 0, 0, 47, 0,
+ 0, 0, 0, 0, 46, 0, 0, 47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 47, 0, 46, 0, 0, 0, 0, 0, 0, 47,
+ 47, 0, 0, 0, 47, 0, 0, 0, 46, 47,
+ 47, 0, 0, 0, 0, 0, 0, 88, 47, 47,
+ 47, 0, 0, 47, 0, 47, 47, 0, 47, 88,
+ 88, 0, 0, 0, 0, 0, 47, 47, 88, 0,
+ 88, 0, 0, 0, 0, 0, 47, 0, 0, 88,
+ 0, 0, 0, 0, 0, 0, 0, 0, 185, 0,
+ 0, 0, 88, 0, 47, 0, 0, 185, 0, 0,
+ 0, 88, 88, 0, 0, 0, 88, 0, 185, 185,
+ 47, 88, 88, 0, 0, 0, 0, 0, 0, 185,
+ 88, 88, 88, 0, 0, 88, 0, 88, 88, 0,
+ 88, 185, 0, 0, 0, 0, 0, 0, 88, 88,
+ 185, 185, 0, 0, 0, 0, 0, 0, 88, 185,
+ 185, 185, 0, 193, 185, 185, 185, 185, 0, 185,
+ 0, 0, 193, 0, 0, 0, 88, 185, 185, 0,
+ 0, 0, 0, 193, 193, 0, 0, 0, 185, 0,
+ 0, 0, 88, 189, 193, 0, 0, 0, 0, 0,
+ 0, 0, 189, 0, 0, 185, 193, 0, 0, 0,
+ 0, 0, 0, 189, 189, 193, 193, 0, 0, 0,
+ 0, 185, 0, 0, 193, 193, 193, 0, 190, 193,
+ 193, 193, 193, 0, 193, 0, 189, 190, 0, 0,
+ 0, 0, 193, 193, 0, 189, 189, 0, 190, 190,
+ 0, 0, 0, 193, 189, 189, 189, 0, 202, 189,
+ 189, 189, 189, 0, 189, 0, 0, 202, 0, 0,
+ 193, 190, 189, 189, 0, 0, 0, 0, 202, 202,
+ 190, 190, 0, 189, 0, 0, 193, 0, 0, 190,
+ 190, 190, 0, 203, 190, 190, 190, 190, 0, 190,
+ 189, 202, 203, 0, 0, 0, 0, 190, 190, 0,
+ 202, 202, 0, 203, 203, 0, 189, 0, 190, 202,
+ 202, 202, 0, 184, 202, 202, 202, 202, 0, 202,
+ 0, 0, 184, 0, 0, 190, 203, 202, 202, 0,
+ 0, 0, 0, 184, 184, 203, 203, 0, 202, 0,
+ 0, 190, 0, 0, 203, 203, 203, 0, 0, 203,
+ 203, 203, 203, 0, 203, 202, 184, 0, 0, 0,
+ 0, 0, 203, 203, 0, 184, 184, 0, 0, 0,
+ 0, 202, 0, 203, 184, 184, 184, 0, 0, 184,
+ 184, 184, 184, 0, 184, 0, 58, 0, 0, 0,
+ 203, 0, 184, 184, 0, 0, 0, 0, 58, 58,
+ 0, 0, 0, 184, 0, 0, 203, 22, 0, 58,
+ 0, 0, 0, 0, 0, 0, 0, 0, 58, 0,
+ 184, 0, 0, 0, 0, 0, 58, 0, 0, 0,
+ 0, 58, 0, 0, 0, 0, 184, 0, 58, 58,
+ 58, 58, 0, 0, 0, 58, 0, 23, 0, 58,
+ 58, 58, 0, 0, 0, 0, 0, 0, 58, 58,
+ 58, 58, 0, 0, 58, 0, 58, 58, 0, 58,
+ 0, 58, 0, 0, 0, 0, 0, 58, 58, 0,
+ 58, 58, 0, 0, 0, 58, 0, 58, 0, 0,
+ 58, 58, 0, 0, 0, 0, 0, 0, 58, 58,
+ 58, 58, 0, 0, 58, 58, 58, 58, 0, 58,
+ 58, 58, 0, 0, 0, 0, 0, 58, 58, 0,
+ 0, 58, 0, 0, 0, 0, 0, 58, 0, 0,
+ 58, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 58, 0, 58, 0, 0, 0, 0,
+ 0, 0, 58, 58, 0, 0, 0, 58, 0, 0,
+ 0, 0, 58, 58, 0, 0, 0, 0, 0, 0,
+ 0, 58, 58, 58, 0, 0, 58, 0, 58, 58,
+ 0, 58, 0, 0, 0, 0, 0, 0, 0, 58,
+ 58, 0, 0, 0, 0, 0, 0, 0, 0, 58,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 58,
+ };
+ protected static short [] yyCheck = { 73,
+ 0, 306, 188, 24, 188, 56, 23, 313, 466, 257,
+ 601, 324, 318, 266, 269, 256, 266, 407, 306, 266,
+ 309, 165, 269, 306, 288, 325, 410, 306, 266, 449,
+ 30, 309, 266, 33, 34, 56, 267, 449, 269, 314,
+ 319, 288, 197, 198, 372, 23, 319, 266, 289, 313,
+ 266, 594, 52, 269, 306, 410, 319, 288, 309, 414,
+ 77, 78, 269, 304, 305, 306, 313, 253, 659, 253,
+ 398, 309, 288, 269, 665, 459, 262, 55, 262, 266,
+ 623, 288, 313, 324, 266, 309, 544, 375, 546, 326,
+ 309, 309, 288, 146, 189, 331, 516, 313, 76, 306,
+ 78, 309, 375, 615, 516, 352, 313, 407, 339, 354,
+ 306, 128, 375, 130, 131, 132, 133, 313, 393, 309,
+ 384, 352, 309, 375, 309, 414, 415, 282, 283, 146,
+ 520, 414, 420, 319, 389, 319, 352, 281, 325, 156,
+ 157, 420, 389, 196, 122, 352, 269, 309, 126, 309,
+ 463, 269, 269, 266, 154, 155, 352, 309, 389, 159,
+ 160, 161, 415, 413, 415, 288, 413, 407, 680, 627,
+ 288, 288, 420, 389, 360, 153, 410, 266, 690, 413,
+ 420, 415, 389, 306, 574, 419, 372, 699, 306, 780,
+ 313, 410, 416, 389, 309, 313, 313, 415, 384, 385,
+ 384, 385, 592, 298, 299, 796, 718, 260, 261, 445,
+ 188, 447, 398, 420, 604, 605, 463, 309, 309, 272,
+ 309, 274, 463, 410, 420, 415, 416, 280, 345, 352,
+ 415, 413, 463, 415, 352, 352, 541, 419, 449, 271,
+ 635, 273, 637, 309, 430, 318, 430, 463, 449, 269,
+ 449, 352, 353, 415, 254, 415, 463, 274, 275, 325,
+ 277, 278, 414, 309, 416, 285, 389, 463, 288, 289,
+ 309, 389, 389, 326, 327, 253, 410, 269, 298, 299,
+ 414, 676, 303, 420, 262, 309, 591, 308, 308, 310,
+ 802, 311, 804, 313, 309, 309, 288, 463, 318, 694,
+ 413, 416, 415, 609, 419, 516, 419, 358, 422, 423,
+ 330, 354, 449, 266, 387, 516, 309, 516, 309, 339,
+ 309, 313, 414, 355, 344, 416, 415, 416, 269, 361,
+ 419, 412, 352, 311, 415, 547, 415, 358, 309, 269,
+ 463, 319, 421, 319, 364, 463, 463, 288, 560, 370,
+ 536, 368, 536, 539, 325, 539, 309, 378, 288, 269,
+ 352, 271, 757, 273, 407, 760, 386, 387, 420, 389,
+ 416, 269, 313, 271, 769, 273, 415, 416, 288, 516,
+ 419, 413, 360, 313, 570, 419, 570, 404, 309, 695,
+ 288, 415, 416, 414, 372, 419, 396, 389, 309, 375,
+ 309, 416, 416, 313, 799, 795, 384, 385, 309, 409,
+ 410, 352, 433, 413, 325, 313, 318, 459, 615, 410,
+ 398, 816, 352, 416, 415, 416, 447, 416, 419, 429,
+ 309, 306, 432, 309, 487, 452, 436, 454, 455, 456,
+ 315, 419, 352, 463, 420, 355, 325, 419, 389, 466,
+ 450, 361, 430, 38, 352, 476, 41, 355, 415, 389,
+ 615, 306, 364, 361, 421, 271, 519, 273, 698, 318,
+ 625, 463, 414, 690, 319, 492, 631, 390, 445, 389,
+ 447, 66, 699, 680, 23, 387, 269, 270, 488, 272,
+ 720, 389, 407, 690, 415, 416, 309, 309, 419, 413,
+ 283, 718, 699, 413, 504, 288, 420, 415, 525, 526,
+ 527, 511, 295, 417, 418, 364, 55, 534, 571, 302,
+ 344, 718, 463, 523, 309, 680, 413, 544, 415, 546,
+ 313, 309, 585, 463, 413, 690, 415, 76, 387, 78,
+ 419, 594, 542, 276, 699, 306, 329, 777, 548, 355,
+ 306, 309, 335, 463, 315, 361, 786, 557, 536, 315,
+ 790, 539, 345, 718, 309, 463, 566, 449, 351, 352,
+ 623, 304, 305, 306, 410, 713, 629, 807, 390, 632,
+ 633, 634, 315, 122, 266, 802, 724, 804, 774, 589,
+ 774, 821, 570, 405, 416, 378, 379, 671, 598, 413,
+ 412, 413, 385, 415, 416, 802, 389, 804, 266, 626,
+ 627, 749, 309, 630, 153, 410, 616, 617, 618, 413,
+ 620, 415, 263, 264, 624, 410, 272, 309, 274, 414,
+ 683, 416, 417, 418, 419, 263, 264, 422, 423, 424,
+ 410, 309, 427, 325, 356, 357, 276, 802, 510, 804,
+ 703, 704, 705, 331, 707, 708, 709, 710, 711, 712,
+ 445, 414, 447, 269, 413, 414, 719, 410, 309, 722,
+ 691, 809, 435, 811, 304, 305, 306, 413, 540, 285,
+ 463, 414, 288, 289, 415, 315, 286, 287, 356, 357,
+ 269, 415, 298, 299, 503, 716, 717, 309, 413, 508,
+ 415, 414, 308, 565, 419, 311, 285, 313, 725, 288,
+ 289, 309, 318, 787, 405, 356, 357, 770, 410, 298,
+ 299, 424, 390, 532, 330, 587, 266, 306, 426, 308,
+ 289, 290, 311, 339, 313, 300, 301, 405, 427, 318,
+ 740, 419, 420, 421, 412, 413, 352, 415, 416, 390,
+ 338, 330, 463, 573, 563, 564, 410, 410, 364, 437,
+ 339, 439, 762, 441, 405, 782, 766, 767, 410, 309,
+ 413, 412, 413, 352, 415, 416, 328, 328, 390, 779,
+ 386, 387, 602, 389, 414, 325, 415, 413, 608, 304,
+ 305, 306, 390, 405, 614, 415, 774, 797, 413, 415,
+ 412, 413, 413, 415, 416, 306, 325, 386, 387, 413,
+ 389, 413, 415, 257, 412, 413, 260, 415, 416, 304,
+ 305, 306, 306, 823, 824, 269, 270, 271, 272, 273,
+ 274, 415, 276, 277, 278, 279, 413, 281, 282, 283,
+ 284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
+ 413, 295, 344, 297, 298, 299, 300, 463, 302, 306,
+ 304, 305, 306, 339, 308, 413, 413, 311, 308, 313,
+ 314, 315, 306, 317, 318, 319, 320, 410, 322, 306,
+ 324, 419, 415, 416, 463, 329, 330, 410, 421, 306,
+ 266, 335, 195, 337, 266, 339, 340, 410, 342, 343,
+ 344, 345, 285, 386, 348, 349, 350, 351, 352, 419,
+ 330, 355, 410, 325, 358, 359, 360, 361, 413, 363,
+ 364, 365, 366, 367, 368, 413, 413, 371, 410, 373,
+ 475, 375, 376, 377, 378, 379, 415, 415, 269, 410,
+ 415, 385, 386, 387, 388, 389, 415, 391, 261, 393,
+ 394, 413, 414, 415, 285, 376, 419, 288, 289, 419,
+ 404, 382, 413, 414, 415, 419, 410, 298, 299, 419,
+ 414, 419, 261, 417, 418, 306, 420, 308, 419, 276,
+ 311, 419, 313, 413, 414, 415, 257, 318, 291, 292,
+ 293, 294, 295, 296, 297, 419, 306, 306, 269, 330,
+ 271, 422, 273, 413, 306, 449, 387, 451, 339, 453,
+ 306, 455, 285, 457, 285, 459, 285, 288, 289, 463,
+ 285, 352, 410, 444, 364, 298, 297, 298, 299, 298,
+ 375, 319, 388, 298, 266, 308, 394, 308, 387, 308,
+ 311, 324, 313, 308, 306, 306, 317, 318, 319, 306,
+ 318, 394, 413, 474, 306, 386, 387, 330, 389, 330,
+ 324, 330, 306, 319, 324, 330, 339, 375, 339, 340,
+ 339, 344, 306, 344, 339, 344, 324, 414, 349, 350,
+ 309, 352, 309, 309, 355, 413, 413, 358, 359, 360,
+ 361, 413, 363, 364, 365, 366, 257, 368, 413, 413,
+ 419, 413, 309, 309, 375, 376, 377, 309, 269, 413,
+ 271, 303, 273, 386, 8, 386, 387, 386, 389, 15,
+ 25, 386, 78, 111, 285, 122, 302, 288, 289, 274,
+ 107, 275, 463, 404, 516, 378, 297, 298, 299, 158,
+ 626, 476, 422, 309, 374, 370, 588, 308, 447, 420,
+ 311, 717, 313, 627, 716, 765, 317, 318, 319, 429,
+ 430, 431, 432, 433, 434, 405, 408, 634, 680, 330,
+ 727, 770, 534, 813, 544, 514, 393, 521, 339, 340,
+ 284, 257, 285, 344, 279, -1, 288, -1, 349, 350,
+ -1, 352, 463, 269, 355, -1, -1, 358, 359, 360,
+ 361, -1, 363, 364, 365, 366, -1, 368, -1, 285,
+ -1, -1, 288, 289, 375, 376, 377, -1, -1, -1,
+ -1, 297, 298, 299, -1, 386, 387, -1, 389, -1,
+ 306, -1, 308, -1, -1, 311, -1, 313, -1, -1,
+ -1, 317, 318, 404, 410, -1, -1, -1, 414, -1,
+ 416, 417, 418, 419, 330, -1, 422, 423, 424, 420,
+ -1, 427, -1, 339, 340, 257, -1, -1, 344, -1,
+ -1, -1, -1, 349, 350, -1, 352, 269, -1, 445,
+ -1, 447, 358, 359, 360, -1, -1, 363, 364, 365,
+ 366, -1, 368, 285, -1, -1, 288, 289, -1, -1,
+ 376, 377, 463, -1, -1, 297, 298, 299, -1, -1,
+ 386, 387, -1, 389, 306, -1, 308, -1, -1, 311,
+ -1, 313, -1, -1, -1, 317, 318, -1, 404, -1,
+ -1, -1, -1, -1, -1, 417, 418, 419, 330, -1,
+ 422, 423, 424, -1, 420, 427, -1, 339, 340, 257,
+ -1, -1, 344, -1, -1, -1, -1, 349, 350, -1,
+ 352, 269, -1, 445, -1, 447, 358, 359, 360, -1,
+ -1, 363, 364, 365, 366, -1, 368, 285, -1, -1,
+ 288, 289, -1, -1, 376, 377, -1, 463, -1, 297,
+ 298, 299, -1, -1, 386, 387, -1, 389, 306, -1,
+ 308, -1, -1, 311, -1, 313, -1, -1, -1, 317,
+ 318, -1, 404, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 330, -1, -1, -1, -1, -1, 420, -1,
+ -1, 339, 340, 257, -1, -1, 344, -1, -1, -1,
+ -1, 349, 350, -1, 352, 269, -1, -1, -1, -1,
+ 358, 359, 360, -1, -1, 363, 364, 365, 366, -1,
+ 368, 285, -1, -1, 288, 289, -1, -1, 376, 377,
+ -1, 463, -1, 297, 298, 299, -1, -1, 386, 387,
+ -1, 389, 306, -1, 308, -1, -1, 311, -1, 313,
+ -1, -1, -1, 317, 318, -1, 404, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 330, -1, -1, -1,
+ -1, -1, 420, -1, -1, 339, 340, 257, -1, -1,
+ 344, -1, -1, -1, -1, 349, 350, -1, 352, 269,
+ -1, -1, -1, -1, 358, 359, 360, -1, -1, 363,
+ 364, 365, 366, -1, 368, 285, -1, -1, 288, 289,
+ -1, -1, 376, 377, -1, 463, -1, 297, 298, 299,
+ -1, -1, 386, 387, -1, 389, 306, -1, 308, -1,
+ -1, 311, -1, 313, -1, -1, -1, 317, 318, -1,
+ 404, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 330, -1, -1, -1, -1, -1, 420, -1, -1, 339,
+ 340, 257, -1, -1, 344, -1, -1, -1, -1, 349,
+ 350, -1, 352, 269, -1, -1, -1, -1, 358, 359,
+ 360, -1, -1, 363, 364, 365, 366, -1, 368, 285,
+ -1, -1, 288, 289, -1, -1, 376, 377, -1, 463,
+ -1, 297, 298, 299, -1, -1, 386, 387, -1, 389,
+ 306, -1, 308, -1, -1, 311, -1, 313, -1, -1,
+ -1, 317, 318, -1, 404, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 330, -1, -1, -1, -1, -1,
+ 420, -1, -1, 339, 340, 257, -1, -1, 344, -1,
+ -1, -1, -1, 349, 350, -1, 352, 269, -1, -1,
+ -1, -1, 358, 359, 360, -1, -1, 363, 364, 365,
+ 366, -1, 368, 285, -1, -1, 288, 289, -1, -1,
+ 376, 377, -1, 463, -1, 297, 298, 299, -1, -1,
+ 386, 387, -1, 389, 306, -1, 308, -1, -1, 311,
+ -1, 313, -1, -1, -1, 317, 318, -1, 404, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 330, -1,
+ -1, -1, -1, -1, 420, -1, -1, 339, 340, -1,
+ -1, -1, 344, -1, -1, -1, -1, 349, 350, -1,
+ 352, -1, -1, -1, -1, -1, 358, 359, 360, -1,
+ -1, 363, 364, 365, 366, -1, 368, -1, -1, -1,
+ -1, -1, -1, -1, 376, 377, -1, 463, -1, -1,
+ -1, -1, 260, -1, 386, 387, -1, 389, -1, -1,
+ -1, 269, 270, -1, 272, -1, 274, -1, -1, 277,
+ 278, 279, 404, 281, 282, 283, 284, -1, 286, 287,
+ 288, 289, 290, 291, 292, 293, -1, 295, 420, -1,
+ -1, 299, 300, -1, 302, -1, -1, -1, 306, -1,
+ -1, -1, -1, -1, -1, 313, 314, -1, -1, -1,
+ -1, -1, 320, -1, 322, -1, 324, -1, -1, -1,
+ 309, 329, 269, 270, -1, 272, -1, 335, -1, 337,
+ -1, 463, -1, -1, 342, 343, 283, 345, -1, -1,
+ 348, 288, -1, 351, 352, -1, -1, -1, 295, -1,
+ -1, -1, -1, -1, -1, 302, -1, -1, -1, 367,
+ -1, -1, -1, 371, -1, 373, 313, 356, 357, -1,
+ 378, 379, -1, -1, -1, -1, -1, 385, -1, -1,
+ 388, 389, 329, 391, -1, 393, 394, -1, 335, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 390, 410, -1, 351, 352, 414, -1, -1, 417,
+ 418, -1, -1, -1, -1, -1, 405, -1, -1, -1,
+ -1, -1, -1, 412, 413, -1, 415, 416, -1, -1,
+ -1, 378, 379, -1, 309, -1, -1, -1, 385, -1,
+ -1, 449, 389, 451, 260, 453, -1, 455, -1, 457,
+ -1, 459, -1, 269, 270, 463, 272, -1, 274, -1,
+ -1, 277, 278, 279, -1, 281, 282, 283, 284, -1,
+ 286, 287, 288, 289, 290, 291, 292, 293, -1, 295,
+ -1, 356, 357, 299, 300, -1, 302, -1, -1, -1,
+ 306, -1, -1, -1, -1, -1, -1, 313, 314, -1,
+ -1, -1, -1, -1, 320, -1, 322, -1, 324, -1,
+ -1, -1, -1, 329, -1, 390, 463, -1, -1, 335,
+ -1, 337, -1, -1, -1, -1, 342, 343, -1, 345,
+ 405, -1, 348, -1, -1, 351, 352, 412, 413, -1,
+ 415, 416, -1, -1, 297, -1, -1, -1, -1, -1,
+ -1, 367, -1, 306, -1, 371, -1, 373, -1, -1,
+ -1, -1, 378, 379, 317, 318, -1, -1, -1, 385,
+ -1, -1, 388, 389, -1, 391, -1, 393, 394, -1,
+ -1, -1, -1, -1, -1, -1, -1, 340, -1, -1,
+ -1, -1, -1, -1, 410, -1, 349, 350, 414, -1,
+ -1, 417, 418, -1, -1, 358, 359, 360, -1, -1,
+ 363, 364, 365, 366, -1, 368, -1, -1, -1, -1,
+ -1, -1, -1, 376, 377, -1, -1, -1, -1, -1,
+ -1, -1, -1, 449, 387, 451, 260, 453, -1, 455,
+ -1, 457, -1, 459, -1, 269, 270, 463, 272, -1,
+ 274, 404, -1, 277, 278, 279, -1, 281, 282, 283,
+ 284, -1, 286, 287, 288, 289, 290, 291, 292, 293,
+ -1, 295, -1, -1, -1, 299, 300, -1, 302, -1,
+ -1, 285, 306, -1, -1, 289, -1, -1, -1, 313,
+ 314, -1, -1, -1, 298, 299, 320, -1, 322, -1,
+ 324, -1, -1, -1, 308, 329, -1, 311, -1, -1,
+ -1, 335, -1, 337, 318, -1, -1, -1, 342, 343,
+ -1, 345, -1, -1, 348, -1, 330, 351, 352, -1,
+ -1, -1, -1, -1, -1, 339, 297, -1, -1, -1,
+ -1, -1, -1, 367, -1, 306, -1, 371, -1, 373,
+ -1, -1, -1, -1, 378, 379, 317, 318, -1, -1,
+ 364, 385, -1, -1, 388, 389, -1, 391, -1, 393,
+ 394, -1, -1, -1, -1, -1, -1, -1, -1, 340,
+ -1, -1, 386, 387, -1, -1, 410, -1, 349, 350,
+ 414, -1, -1, 417, 418, -1, -1, 358, 359, 360,
+ -1, -1, 363, 364, 365, 366, -1, 368, -1, -1,
+ -1, -1, -1, -1, -1, 376, 377, -1, -1, -1,
+ -1, -1, -1, -1, -1, 449, 387, 451, 260, 453,
+ -1, 455, -1, 457, -1, 459, -1, 269, 270, 463,
+ 272, -1, 274, 404, -1, 277, 278, 279, -1, 281,
+ 282, 283, 284, -1, 286, 287, 288, 289, 290, 291,
+ 292, 293, -1, 295, -1, -1, -1, 299, 300, -1,
+ 302, -1, -1, 285, 306, -1, -1, 289, -1, -1,
+ -1, 313, 314, -1, -1, -1, 298, 299, 320, -1,
+ 322, -1, 324, -1, -1, -1, 308, 329, -1, 311,
+ -1, -1, -1, 335, -1, 337, 318, -1, -1, -1,
+ 342, 343, -1, 345, -1, -1, 348, -1, 330, 351,
+ 352, -1, -1, -1, -1, -1, -1, 339, 297, -1,
+ -1, -1, -1, -1, -1, 367, -1, -1, -1, 371,
+ -1, 373, -1, -1, -1, -1, 378, 379, 317, -1,
+ -1, -1, -1, 385, -1, -1, 388, 389, -1, 391,
+ -1, 393, 394, -1, -1, -1, -1, -1, -1, -1,
+ -1, 340, -1, -1, 386, 387, -1, -1, 410, -1,
+ 349, 350, 414, -1, -1, 417, 418, -1, -1, 358,
+ 359, 360, -1, -1, 363, -1, 365, 366, -1, 368,
+ -1, -1, -1, -1, -1, -1, -1, 376, 377, -1,
+ -1, -1, -1, -1, -1, -1, -1, 449, -1, 451,
+ 260, 453, -1, 455, -1, 457, -1, 459, -1, 269,
+ 270, 463, 272, -1, 274, 404, -1, 277, 278, 279,
+ -1, 281, 282, 283, 284, -1, 286, 287, 288, 289,
+ 290, 291, 292, 293, -1, 295, -1, -1, -1, 299,
+ 300, -1, 302, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 313, 314, -1, -1, -1, -1, -1,
+ 320, -1, 322, -1, 324, -1, -1, -1, -1, 329,
+ -1, -1, -1, -1, -1, 335, -1, 337, -1, -1,
+ -1, -1, 342, 343, -1, 345, -1, -1, 348, -1,
+ -1, 351, 352, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 367, -1, -1,
+ -1, 371, -1, 373, -1, -1, -1, -1, 378, 379,
+ -1, -1, -1, -1, -1, 385, -1, -1, 388, 389,
+ -1, 391, -1, 393, 394, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 410, -1, -1, 261, -1, -1, -1, 417, 418, -1,
+ -1, 269, 270, 271, 272, -1, 274, -1, -1, 277,
+ 278, 279, -1, 281, 282, 283, 284, -1, 286, 287,
+ 288, -1, 290, 291, 292, 293, -1, 295, -1, 449,
+ -1, 451, 300, 453, 302, 455, -1, 457, -1, 459,
+ -1, -1, -1, 463, -1, 313, 314, -1, -1, -1,
+ -1, -1, 320, -1, -1, -1, -1, -1, -1, -1,
+ -1, 329, -1, -1, -1, -1, -1, 335, -1, 337,
+ -1, -1, -1, -1, 342, 343, -1, 345, -1, 347,
+ 348, -1, -1, 351, 352, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 378, 379, -1, -1, -1, -1, -1, 385, -1, -1,
+ -1, 389, -1, -1, -1, 393, -1, 395, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 410, -1, -1, 261, -1, -1, -1, 417,
+ 418, -1, -1, 269, 270, -1, 272, -1, 274, -1,
+ -1, 277, 278, 279, -1, 281, 282, 283, 284, -1,
+ 286, 287, 288, -1, 290, 291, 292, 293, -1, 295,
+ -1, 449, -1, 451, 300, 453, 302, 455, -1, 457,
+ -1, 459, -1, -1, -1, 463, -1, 313, 314, -1,
+ -1, -1, -1, -1, 320, -1, -1, -1, -1, -1,
+ -1, -1, -1, 329, -1, -1, -1, -1, -1, 335,
+ -1, 337, -1, -1, -1, -1, 342, 343, -1, 345,
+ -1, 347, 348, -1, -1, 351, 352, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 378, 379, -1, -1, -1, -1, -1, 385,
+ -1, -1, -1, 389, -1, -1, -1, 393, -1, 395,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 410, -1, -1, -1, -1, -1,
+ -1, 417, 418, -1, -1, 269, 270, -1, 272, -1,
+ 274, -1, -1, 277, 278, 279, -1, 281, 282, 283,
+ 284, -1, 286, 287, 288, -1, 290, 291, 292, 293,
+ -1, 295, -1, 449, -1, 451, 300, 453, 302, 455,
+ -1, 457, -1, 459, -1, -1, -1, 463, -1, 313,
+ 314, -1, -1, -1, -1, -1, 320, -1, -1, -1,
+ -1, -1, -1, -1, -1, 329, -1, -1, -1, -1,
+ -1, 335, -1, 337, -1, -1, -1, -1, 342, 343,
+ -1, 345, -1, 347, 348, -1, -1, 351, 352, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 378, 379, -1, -1, -1, -1,
+ -1, 385, -1, -1, -1, 389, -1, -1, -1, 393,
+ -1, 395, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 410, 411, 412, -1,
+ -1, -1, -1, 417, 418, -1, -1, 269, 270, -1,
+ 272, -1, 274, -1, -1, 277, 278, 279, -1, 281,
+ 282, 283, 284, -1, 286, 287, 288, -1, 290, 291,
+ 292, 293, -1, 295, -1, 449, -1, 451, 300, 453,
+ 302, 455, -1, 457, -1, 459, -1, -1, -1, 463,
+ -1, 313, 314, -1, -1, -1, -1, -1, 320, -1,
+ -1, -1, -1, -1, -1, -1, -1, 329, -1, -1,
+ -1, -1, -1, 335, -1, 337, -1, -1, -1, -1,
+ 342, 343, -1, 345, -1, 347, 348, -1, -1, 351,
+ 352, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 378, 379, -1, -1,
+ -1, -1, -1, 385, -1, -1, -1, 389, -1, -1,
+ -1, 393, -1, 395, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 410, 411,
+ -1, -1, -1, -1, -1, 417, 418, -1, -1, 269,
+ 270, -1, 272, -1, 274, -1, -1, 277, 278, 279,
+ -1, 281, 282, 283, 284, -1, 286, 287, 288, -1,
+ 290, 291, 292, 293, -1, 295, -1, 449, -1, 451,
+ 300, 453, 302, 455, -1, 457, -1, 459, -1, -1,
+ -1, 463, -1, 313, 314, -1, -1, -1, -1, -1,
+ 320, -1, -1, -1, -1, -1, -1, -1, -1, 329,
+ -1, -1, -1, -1, -1, 335, -1, 337, -1, -1,
+ -1, -1, 342, 343, -1, 345, -1, 347, 348, -1,
+ -1, 351, 352, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 378, 379,
+ -1, -1, -1, -1, -1, 385, -1, -1, -1, 389,
+ -1, -1, -1, 393, -1, 395, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 410, -1, -1, -1, -1, -1, 257, 417, 418, -1,
+ -1, 269, 270, -1, 272, -1, 274, -1, -1, 277,
+ 278, 279, -1, 281, 282, 283, 284, -1, 286, 287,
+ 288, -1, 290, 291, 292, 293, -1, 295, -1, 449,
+ -1, 451, 300, 453, 302, 455, 297, 457, -1, 459,
+ -1, -1, -1, 463, -1, 313, 314, -1, -1, -1,
+ -1, -1, 320, -1, -1, -1, 317, -1, -1, -1,
+ -1, 329, -1, -1, -1, -1, -1, 335, -1, 337,
+ -1, -1, -1, -1, 342, 343, -1, 345, -1, 340,
+ 348, -1, -1, 351, 352, -1, -1, -1, 349, 350,
+ -1, -1, -1, -1, -1, -1, -1, 358, 359, 360,
+ -1, -1, 363, -1, 365, 366, -1, 368, -1, -1,
+ 378, 379, -1, -1, -1, 376, 377, 385, -1, -1,
+ -1, 389, -1, -1, -1, 393, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 410, 404, -1, -1, -1, -1, -1, 417,
+ 418, -1, -1, 269, 270, -1, 272, -1, 274, -1,
+ -1, 277, 278, 279, -1, 281, 282, 283, 284, -1,
+ 286, 287, 288, -1, 290, 291, 292, 293, -1, 295,
+ -1, 449, -1, 451, 300, 453, 302, 455, -1, 457,
+ -1, 459, -1, -1, -1, 463, -1, 313, 314, -1,
+ -1, -1, -1, -1, 320, 257, -1, -1, -1, -1,
+ -1, -1, -1, 329, -1, -1, -1, -1, -1, 335,
+ -1, 337, -1, -1, -1, -1, 342, 343, -1, 345,
+ -1, -1, 348, 285, -1, 351, 352, -1, -1, -1,
+ -1, -1, -1, -1, -1, 297, 298, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 308, -1, -1, -1,
+ -1, -1, 378, 379, -1, 317, -1, -1, -1, 385,
+ -1, -1, -1, 389, -1, -1, -1, 393, 330, -1,
+ -1, -1, -1, -1, -1, -1, -1, 339, 340, -1,
+ -1, -1, 344, -1, 410, -1, -1, 349, 350, -1,
+ -1, -1, -1, -1, -1, -1, 358, 359, 360, -1,
+ -1, 363, -1, 365, 366, -1, 368, -1, -1, -1,
+ -1, -1, -1, -1, 376, 377, 269, -1, -1, -1,
+ -1, -1, -1, 449, 386, 451, -1, 453, -1, 455,
+ -1, 457, 285, 459, -1, 288, 289, 463, -1, -1,
+ -1, -1, 404, -1, 297, 298, 299, -1, -1, -1,
+ -1, -1, -1, 306, -1, 308, -1, -1, 311, -1,
+ 313, -1, -1, -1, 317, 318, -1, -1, -1, -1,
+ -1, -1, 325, -1, -1, 328, -1, 330, -1, -1,
+ -1, -1, -1, -1, -1, -1, 339, 340, -1, -1,
+ -1, -1, -1, -1, -1, -1, 349, 350, 269, 352,
+ -1, -1, -1, -1, -1, 358, 359, 360, -1, -1,
+ 363, 364, 365, 366, 285, 368, -1, 288, 289, -1,
+ -1, -1, -1, 376, 377, -1, 297, 298, 299, -1,
+ -1, -1, -1, 386, 387, 306, 389, 308, -1, -1,
+ 311, -1, 313, -1, -1, -1, 317, 318, -1, -1,
+ -1, 404, -1, -1, 325, -1, -1, -1, -1, 330,
+ -1, -1, -1, -1, -1, -1, -1, 420, 339, 340,
+ -1, -1, -1, -1, -1, -1, -1, -1, 349, 350,
+ -1, 352, -1, 269, -1, -1, -1, 358, 359, 360,
+ -1, -1, 363, 364, 365, 366, -1, 368, -1, 285,
+ -1, -1, 288, 289, -1, 376, 377, -1, -1, -1,
+ 463, 297, 298, 299, -1, 386, 387, -1, 389, -1,
+ 306, -1, 308, -1, -1, 311, -1, 313, -1, -1,
+ -1, 317, 318, 404, -1, -1, -1, -1, -1, 325,
+ -1, -1, -1, -1, 330, -1, -1, -1, -1, 420,
+ -1, -1, -1, 339, 340, -1, -1, -1, -1, -1,
+ -1, -1, -1, 349, 350, 269, 352, -1, -1, -1,
+ -1, -1, 358, 359, 360, -1, -1, 363, 364, 365,
+ 366, 285, 368, -1, 288, 289, -1, -1, -1, -1,
+ 376, 377, 463, 297, 298, 299, -1, -1, -1, -1,
+ 386, 387, 306, 389, 308, -1, -1, 311, -1, 313,
+ -1, -1, -1, 317, 318, -1, -1, -1, 404, -1,
+ -1, -1, -1, -1, -1, -1, 330, -1, -1, -1,
+ -1, -1, -1, -1, 420, 339, 340, -1, -1, -1,
+ -1, -1, -1, -1, -1, 349, 350, -1, 352, -1,
+ 269, -1, -1, -1, 358, 359, 360, -1, -1, 363,
+ 364, 365, 366, -1, 368, -1, 285, -1, -1, 288,
+ 289, -1, 376, 377, -1, -1, -1, 463, 297, 298,
+ 299, -1, 386, 387, -1, 389, -1, 306, -1, 308,
+ -1, -1, 311, -1, 313, -1, -1, -1, 317, 318,
+ 404, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 330, -1, -1, -1, -1, 420, -1, -1, -1,
+ 339, 340, -1, -1, -1, -1, -1, -1, -1, -1,
+ 349, 350, 269, 352, -1, -1, -1, -1, -1, 358,
+ 359, 360, -1, -1, 363, 364, 365, 366, 285, 368,
+ -1, 288, 289, -1, -1, -1, -1, 376, 377, 463,
+ 297, 298, 299, -1, -1, -1, -1, 386, 387, 306,
+ 389, 308, 309, -1, 311, -1, 313, -1, -1, -1,
+ 317, 318, -1, -1, -1, 404, -1, -1, -1, -1,
+ -1, -1, -1, 330, -1, -1, -1, -1, -1, -1,
+ -1, 420, 339, 340, -1, -1, -1, -1, -1, -1,
+ -1, -1, 349, 350, -1, 352, -1, -1, -1, -1,
+ -1, 358, 359, 360, -1, -1, 363, -1, 365, 366,
+ -1, 368, -1, -1, -1, -1, -1, -1, -1, 376,
+ 377, -1, 269, -1, 463, -1, -1, -1, -1, 386,
+ 387, -1, 389, -1, -1, -1, -1, -1, 285, -1,
+ -1, 288, 289, -1, -1, -1, -1, 404, -1, -1,
+ 297, 298, 299, -1, -1, -1, -1, -1, 415, 306,
+ -1, 308, 309, -1, 311, -1, 313, -1, -1, -1,
+ 317, 318, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 330, -1, -1, -1, -1, -1, -1,
+ -1, -1, 339, 340, -1, -1, -1, -1, -1, -1,
+ -1, -1, 349, 350, 269, 352, 463, -1, -1, -1,
+ -1, 358, 359, 360, -1, -1, 363, -1, 365, 366,
+ 285, 368, -1, 288, 289, -1, -1, -1, -1, 376,
+ 377, -1, 297, 298, 299, -1, -1, -1, -1, 386,
+ 387, 306, 389, 308, -1, -1, 311, -1, 313, -1,
+ -1, -1, 317, 318, -1, -1, -1, 404, -1, -1,
+ -1, -1, -1, -1, -1, 330, -1, -1, 415, -1,
+ -1, -1, -1, -1, 339, 340, -1, -1, -1, -1,
+ -1, -1, -1, -1, 349, 350, -1, 352, -1, 269,
+ -1, -1, -1, 358, 359, 360, -1, -1, 363, 364,
+ 365, 366, -1, 368, -1, 285, -1, -1, 288, 289,
+ -1, 376, 377, -1, -1, -1, 463, 297, 298, 299,
+ -1, 386, 387, -1, 389, -1, 306, -1, 308, -1,
+ -1, 311, -1, 313, -1, -1, -1, 317, 318, 404,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 330, -1, -1, -1, -1, 420, -1, -1, -1, 339,
+ 340, -1, -1, -1, -1, -1, -1, -1, -1, 349,
+ 350, 269, 352, -1, -1, -1, -1, -1, 358, 359,
+ 360, -1, -1, 363, 364, 365, 366, 285, 368, -1,
+ 288, 289, -1, -1, -1, -1, 376, 377, 463, 297,
+ 298, 299, -1, -1, -1, -1, 386, 387, 306, 389,
+ 308, -1, -1, 311, -1, 313, -1, -1, -1, 317,
+ 318, -1, -1, -1, 404, -1, -1, -1, -1, -1,
+ -1, -1, 330, -1, -1, -1, -1, -1, -1, -1,
+ 420, 339, 340, -1, -1, -1, -1, -1, -1, -1,
+ -1, 349, 350, -1, 352, -1, 269, -1, -1, -1,
+ 358, 359, 360, -1, -1, 363, 364, 365, 366, -1,
+ 368, -1, 285, -1, -1, 288, 289, -1, 376, 377,
+ -1, -1, -1, 463, 297, 298, 299, -1, 386, 387,
+ -1, 389, -1, 306, -1, 308, -1, -1, 311, -1,
+ 313, -1, -1, -1, 317, 318, 404, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 330, -1, -1,
+ -1, -1, 420, -1, -1, -1, 339, 340, -1, -1,
+ -1, -1, -1, -1, -1, -1, 349, 350, 269, 352,
+ -1, -1, -1, -1, -1, 358, 359, 360, -1, -1,
+ 363, 364, 365, 366, 285, 368, -1, 288, 289, -1,
+ -1, -1, -1, 376, 377, 463, 297, 298, 299, -1,
+ -1, -1, -1, 386, 387, 306, 389, 308, -1, -1,
+ 311, -1, 313, -1, -1, -1, 317, 318, -1, -1,
+ -1, 404, -1, -1, -1, -1, -1, -1, -1, 330,
+ -1, -1, -1, -1, -1, -1, -1, 420, 339, 340,
+ -1, -1, -1, -1, -1, -1, -1, -1, 349, 350,
+ -1, 352, -1, 269, -1, -1, -1, 358, 359, 360,
+ -1, -1, 363, 364, 365, 366, -1, 368, -1, 285,
+ -1, -1, 288, 289, -1, 376, 377, -1, -1, -1,
+ 463, 297, 298, 299, -1, 386, 387, -1, 389, -1,
+ 306, -1, 308, -1, -1, 311, -1, 313, -1, -1,
+ -1, 317, 318, 404, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 330, -1, -1, -1, -1, 420,
+ -1, -1, -1, 339, 340, -1, -1, -1, -1, -1,
+ -1, -1, -1, 349, 350, 269, 352, -1, -1, -1,
+ -1, -1, 358, 359, 360, -1, -1, 363, 364, 365,
+ 366, 285, 368, -1, 288, 289, -1, -1, -1, -1,
+ 376, 377, 463, 297, 298, 299, -1, -1, -1, -1,
+ 386, 387, 306, 389, 308, -1, -1, 311, -1, 313,
+ -1, -1, -1, 317, 318, -1, -1, -1, 404, -1,
+ -1, -1, -1, -1, -1, -1, 330, -1, -1, -1,
+ -1, -1, -1, -1, 420, 339, 340, -1, -1, -1,
+ -1, -1, -1, -1, -1, 349, 350, -1, 352, -1,
+ 269, -1, -1, -1, 358, 359, 360, -1, -1, 363,
+ 364, 365, 366, -1, 368, -1, 285, -1, -1, 288,
+ 289, -1, 376, 377, -1, -1, -1, 463, 297, 298,
+ 299, -1, 386, 387, -1, 389, -1, 306, -1, 308,
+ -1, -1, 311, -1, 313, -1, -1, -1, 317, 318,
+ 404, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 330, -1, -1, -1, -1, 420, -1, -1, -1,
+ 339, 340, -1, -1, -1, -1, -1, -1, -1, -1,
+ 349, 350, 269, 352, -1, -1, -1, -1, -1, 358,
+ 359, 360, -1, -1, 363, 364, 365, 366, 285, 368,
+ -1, 288, 289, -1, -1, -1, -1, 376, 377, 463,
+ 297, 298, 299, -1, -1, -1, -1, 386, 387, 306,
+ 389, 308, -1, -1, 311, -1, 313, -1, -1, -1,
+ 317, 318, -1, -1, -1, 404, -1, -1, -1, -1,
+ -1, -1, -1, 330, -1, -1, -1, -1, -1, -1,
+ -1, 420, 339, 340, -1, -1, -1, -1, -1, -1,
+ -1, -1, 349, 350, -1, 352, -1, 269, -1, -1,
+ -1, 358, 359, 360, -1, -1, 363, 364, 365, 366,
+ -1, 368, -1, 285, -1, -1, 288, 289, -1, 376,
+ 377, -1, -1, -1, 463, 297, 298, 299, -1, 386,
+ 387, -1, 389, -1, 306, -1, 308, -1, -1, 311,
+ -1, 313, -1, -1, -1, 317, 318, 404, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 330, -1,
+ -1, -1, -1, -1, -1, -1, -1, 339, 340, -1,
+ -1, -1, -1, -1, -1, -1, -1, 349, 350, 269,
+ 352, -1, -1, -1, -1, -1, 358, 359, 360, -1,
+ -1, 363, 364, 365, 366, 285, 368, -1, 288, 289,
+ -1, -1, -1, -1, 376, 377, 463, 297, 298, 299,
+ -1, -1, -1, -1, 386, 387, 306, 389, 308, 309,
+ -1, 311, -1, 313, -1, -1, -1, 317, 318, -1,
+ -1, -1, 404, -1, -1, -1, -1, -1, -1, -1,
+ 330, -1, -1, -1, -1, -1, -1, -1, -1, 339,
+ 340, -1, -1, -1, -1, -1, -1, -1, -1, 349,
+ 350, -1, 352, -1, 269, -1, -1, -1, 358, 359,
+ 360, -1, -1, 363, -1, 365, 366, -1, 368, -1,
+ 285, -1, -1, 288, 289, -1, 376, 377, -1, -1,
+ -1, 463, 297, 298, 299, -1, 386, 387, -1, 389,
+ -1, 306, -1, 308, -1, -1, 311, -1, 313, -1,
+ -1, -1, 317, 318, 404, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 330, -1, -1, -1, -1,
+ -1, -1, -1, -1, 339, 340, -1, -1, -1, -1,
+ -1, -1, -1, -1, 349, 350, 269, 352, -1, -1,
+ -1, -1, -1, 358, 359, 360, -1, -1, 363, 364,
+ 365, 366, 285, 368, -1, 288, 289, -1, -1, -1,
+ -1, 376, 377, 463, 297, 298, 299, -1, -1, -1,
+ -1, 386, 387, 306, 389, 308, -1, -1, 311, -1,
+ 313, -1, -1, -1, 317, 318, -1, -1, -1, 404,
+ -1, -1, -1, -1, -1, -1, -1, 330, -1, -1,
+ -1, -1, -1, -1, -1, -1, 339, 340, -1, -1,
+ -1, -1, -1, 263, 264, -1, 349, 350, -1, 352,
+ -1, 269, -1, -1, -1, 358, 359, 360, -1, -1,
+ 363, 364, 365, 366, -1, 368, -1, 285, -1, -1,
+ 288, 289, -1, 376, 377, -1, -1, -1, 463, 297,
+ 298, 299, -1, 386, 387, -1, 389, -1, 306, 309,
+ 308, -1, -1, 311, -1, 313, -1, -1, -1, 317,
+ 318, 404, -1, -1, -1, 325, -1, -1, -1, -1,
+ -1, 331, 330, -1, -1, -1, 263, 264, 338, -1,
+ -1, 339, 340, -1, -1, -1, -1, -1, -1, -1,
+ -1, 349, 350, -1, 352, -1, 356, 357, -1, -1,
+ 358, 359, 360, -1, -1, 363, -1, 365, 366, -1,
+ 368, -1, -1, -1, -1, -1, -1, -1, 376, 377,
+ 463, -1, 309, -1, -1, -1, 263, 264, 386, 387,
+ 390, 389, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 331, 405, 404, -1, -1, -1,
+ 410, 338, 412, 413, -1, 415, 416, 417, 418, 419,
+ 420, 421, 422, 423, 424, -1, 426, 427, -1, 356,
+ 357, -1, 309, -1, -1, -1, -1, 437, -1, 439,
+ -1, 441, -1, -1, -1, 445, -1, 447, -1, -1,
+ -1, -1, -1, -1, 331, -1, -1, -1, -1, 263,
+ 264, 338, -1, 390, -1, 463, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 405, 356,
+ 357, -1, -1, 410, -1, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, -1, 426,
+ 427, -1, -1, -1, -1, 309, -1, -1, -1, -1,
+ 437, -1, 439, 390, 441, -1, -1, -1, 445, -1,
+ 447, -1, -1, -1, -1, -1, -1, 331, 405, -1,
+ -1, -1, -1, 410, 338, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, -1, 426,
+ 427, -1, 356, 357, -1, -1, 263, 264, -1, -1,
+ 437, -1, 439, -1, 441, -1, -1, -1, 445, -1,
+ 447, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 390, -1, -1, -1,
+ -1, -1, -1, -1, 263, 264, -1, -1, -1, -1,
+ -1, 405, 309, -1, -1, -1, 410, -1, 412, 413,
+ -1, 415, 416, 417, 418, 419, 420, 421, 422, 423,
+ 424, -1, 426, 427, 331, -1, -1, -1, -1, -1,
+ -1, 338, -1, 437, -1, 439, -1, 441, -1, -1,
+ 309, 445, -1, 447, -1, -1, -1, -1, -1, 356,
+ 357, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 331, -1, -1, -1, -1, -1, -1, 338,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 390, -1, -1, -1, 356, 357, -1,
+ -1, 263, 264, -1, -1, -1, -1, -1, 405, -1,
+ -1, -1, -1, -1, -1, 412, 413, 414, 415, 416,
+ 417, 418, 419, 420, 421, 422, 423, 424, -1, 426,
+ 427, 390, -1, -1, -1, -1, -1, -1, -1, -1,
+ 437, -1, 439, -1, 441, -1, 405, 309, 445, -1,
+ 447, 263, 264, 412, 413, -1, 415, 416, 417, 418,
+ 419, 420, 421, 422, 423, 424, -1, 426, 427, 331,
+ -1, -1, -1, -1, -1, -1, 338, -1, 437, -1,
+ 439, -1, 441, -1, -1, -1, 445, -1, 447, -1,
+ -1, -1, -1, -1, 356, 357, -1, 309, 263, 264,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 331,
+ -1, -1, -1, -1, -1, -1, 338, -1, 390, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 405, 356, 357, -1, -1, 263, 264,
+ 412, 413, -1, 415, 416, 417, 418, 419, 420, 421,
+ 422, 423, 424, -1, 426, 427, 331, -1, -1, -1,
+ -1, -1, -1, 338, -1, 437, -1, 439, 390, 441,
+ -1, -1, -1, 445, -1, 447, -1, -1, -1, -1,
+ -1, 356, 357, 405, 309, -1, -1, -1, 263, 264,
+ 412, 413, -1, 415, 416, 417, 418, 419, 420, 421,
+ 422, 423, -1, -1, 426, 427, 331, -1, -1, -1,
+ -1, -1, -1, 338, -1, 437, -1, 439, -1, 441,
+ -1, -1, -1, 445, -1, 447, -1, -1, -1, -1,
+ 405, 356, 357, -1, 309, 410, -1, -1, 413, 414,
+ 415, -1, 417, 418, 419, 420, 421, 422, 423, 424,
+ -1, 426, 427, -1, -1, -1, 331, -1, -1, -1,
+ 263, 264, 437, 338, 439, 390, 441, -1, -1, -1,
+ 445, -1, 447, -1, -1, -1, -1, -1, -1, -1,
+ 405, 356, 357, -1, -1, -1, -1, 412, 413, -1,
+ 415, 416, 417, 418, 419, 420, 421, -1, -1, -1,
+ -1, 426, 427, 263, 264, -1, 309, -1, -1, -1,
+ -1, -1, 437, -1, 439, 390, 441, -1, -1, -1,
+ 445, -1, 447, -1, -1, -1, -1, -1, 331, -1,
+ 405, -1, -1, -1, -1, 338, -1, 412, 413, -1,
+ 415, 416, 417, 418, 419, 420, 421, -1, -1, 309,
+ -1, 426, 427, 356, 357, 263, 264, -1, -1, -1,
+ -1, -1, 437, -1, 439, -1, 441, -1, -1, -1,
+ 445, 331, 447, -1, -1, -1, -1, -1, 338, -1,
+ -1, -1, -1, -1, -1, -1, -1, 390, -1, -1,
+ -1, -1, -1, -1, -1, -1, 356, 357, -1, -1,
+ -1, 309, 405, -1, -1, 263, 264, -1, -1, 412,
+ 413, -1, 415, 416, 417, 418, 419, 420, 421, -1,
+ -1, -1, -1, 331, 427, -1, -1, -1, -1, -1,
+ 390, -1, -1, -1, 437, -1, 439, -1, 441, -1,
+ -1, -1, 445, -1, 447, 405, -1, -1, 356, 357,
+ -1, 309, 412, 413, -1, 415, 416, 417, 418, 419,
+ 420, 421, -1, -1, -1, -1, -1, 427, -1, -1,
+ -1, -1, -1, 331, 263, 264, -1, 437, -1, 439,
+ -1, 441, 390, -1, -1, 445, -1, 447, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 405, 356, 357,
+ -1, -1, -1, -1, 412, 413, -1, 415, 416, 417,
+ 418, 419, 420, 421, -1, -1, -1, -1, -1, 427,
+ 309, -1, -1, -1, 263, 264, -1, -1, -1, 437,
+ -1, 439, 390, 441, -1, -1, -1, 445, -1, 447,
+ -1, -1, 331, -1, -1, -1, -1, 405, -1, -1,
+ -1, -1, -1, -1, 412, 413, -1, 415, 416, 417,
+ 418, 419, 420, 421, -1, -1, -1, 356, 357, 427,
+ 309, -1, -1, -1, 263, 264, -1, -1, -1, 437,
+ -1, 439, -1, 441, -1, -1, -1, 445, -1, 447,
+ -1, -1, 331, -1, -1, -1, -1, -1, -1, -1,
+ -1, 390, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 405, 356, 357, -1,
+ 309, -1, -1, 412, 413, -1, 415, 416, 417, 418,
+ 419, 420, 421, -1, -1, -1, -1, -1, 427, -1,
+ -1, -1, 331, 263, 264, -1, -1, -1, 437, -1,
+ 439, 390, 441, -1, -1, -1, 445, -1, 447, -1,
+ -1, -1, -1, -1, -1, -1, 405, 356, 357, -1,
+ -1, -1, -1, 412, 413, -1, 415, 416, -1, -1,
+ 419, 420, 421, -1, -1, -1, -1, -1, 427, 309,
+ -1, -1, -1, 263, 264, -1, -1, -1, 437, -1,
+ 439, 390, 441, -1, -1, -1, 445, -1, 447, -1,
+ -1, 331, -1, -1, -1, -1, 405, -1, -1, -1,
+ -1, -1, -1, 412, 413, -1, 415, 416, -1, -1,
+ 419, 420, 421, -1, -1, -1, 356, 357, 427, 309,
+ -1, -1, -1, 263, 264, -1, -1, -1, 437, -1,
+ 439, -1, 441, -1, -1, -1, 445, -1, 447, -1,
+ -1, 331, -1, -1, -1, -1, -1, -1, -1, -1,
+ 390, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 263, 264, -1, -1, -1, 405, 356, 357, -1, 309,
+ -1, -1, 412, 413, -1, 415, 416, -1, -1, 419,
+ 420, 421, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 331, -1, -1, -1, 263, 264, 437, -1, 439,
+ 390, 441, -1, -1, -1, 445, 309, 447, -1, -1,
+ -1, -1, -1, -1, -1, 405, 356, 357, -1, -1,
+ -1, -1, 412, 413, -1, 415, 416, -1, 331, 419,
+ 420, 421, 263, 264, -1, -1, -1, -1, -1, -1,
+ -1, 309, -1, -1, -1, -1, -1, 437, -1, 439,
+ 390, 441, -1, 356, 357, 445, -1, 447, -1, -1,
+ -1, -1, -1, 331, -1, 405, -1, -1, -1, -1,
+ -1, -1, 412, 413, -1, 415, 416, -1, 309, 419,
+ 420, 421, 263, 264, -1, -1, -1, 390, 356, 357,
+ -1, -1, -1, -1, -1, -1, -1, 437, -1, 439,
+ 331, 441, 405, -1, -1, 445, -1, 447, -1, 412,
+ 413, -1, 415, 416, -1, -1, 419, 420, 421, 263,
+ 264, -1, 390, -1, -1, 356, 357, -1, 309, -1,
+ -1, -1, 263, 264, 437, -1, 439, 405, 441, -1,
+ -1, -1, -1, -1, 412, 413, -1, 415, 416, -1,
+ 331, 419, 420, 421, -1, -1, -1, -1, -1, 390,
+ -1, -1, -1, -1, -1, 309, -1, -1, -1, 437,
+ -1, 439, -1, 441, 405, 356, 357, -1, 309, -1,
+ -1, 412, 413, -1, 415, 416, -1, 331, 419, 420,
+ 421, -1, -1, -1, -1, -1, -1, -1, 263, 264,
+ 331, -1, -1, -1, -1, -1, 437, -1, 439, 390,
+ 441, -1, 356, 357, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 405, 356, 357, -1, -1, -1,
+ -1, 412, 413, -1, 415, 416, -1, -1, 419, 420,
+ 421, 263, 264, -1, 309, -1, 390, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 437, -1, 439, 390,
+ 441, 405, -1, -1, -1, -1, 331, -1, 412, 413,
+ -1, 415, 416, -1, 405, 419, 420, 421, -1, -1,
+ -1, 412, 413, -1, 415, 416, -1, 309, 419, 420,
+ 421, 356, 357, 437, -1, 439, -1, 441, -1, -1,
+ -1, -1, -1, -1, -1, -1, 437, -1, 439, 331,
+ 441, 263, 264, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 390, -1, -1, -1, -1,
+ -1, -1, -1, -1, 356, 357, -1, -1, -1, -1,
+ 405, -1, -1, -1, -1, -1, -1, 412, 413, -1,
+ 415, 416, -1, -1, 419, 420, 421, 309, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 390, -1,
+ -1, -1, 437, -1, 439, -1, 441, -1, -1, 331,
+ -1, -1, -1, 405, -1, -1, -1, -1, -1, -1,
+ 412, 413, -1, 415, 416, -1, -1, 419, 420, 421,
+ -1, -1, -1, -1, 356, 357, -1, -1, -1, -1,
+ -1, 257, -1, -1, -1, 437, -1, 439, -1, 441,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 390, 285,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 297, 298, 405, -1, -1, -1, -1, -1, -1,
+ 412, 413, 308, 415, 416, -1, -1, 419, 420, 421,
+ -1, 317, -1, -1, -1, -1, -1, -1, -1, -1,
+ 326, -1, -1, 257, 330, 437, -1, 439, -1, 441,
+ -1, -1, -1, 339, 340, -1, -1, -1, 344, -1,
+ -1, -1, -1, 349, 350, -1, -1, -1, 354, -1,
+ -1, 285, 358, 359, 360, -1, -1, 363, -1, 365,
+ 366, -1, 368, 297, 298, -1, -1, -1, -1, -1,
+ 376, 377, -1, -1, 308, -1, -1, -1, -1, -1,
+ 386, -1, -1, 317, -1, -1, -1, -1, -1, -1,
+ -1, -1, 326, -1, -1, 257, 330, -1, 404, -1,
+ -1, -1, -1, -1, -1, 339, 340, -1, -1, -1,
+ 344, -1, -1, -1, 420, 349, 350, -1, -1, -1,
+ 354, -1, -1, 285, 358, 359, 360, -1, -1, 363,
+ -1, 365, 366, -1, 368, 297, 298, -1, -1, -1,
+ -1, -1, 376, 377, -1, -1, 308, -1, -1, -1,
+ -1, -1, 386, -1, -1, 317, -1, -1, -1, -1,
+ -1, -1, -1, -1, 326, -1, -1, 257, 330, -1,
+ 404, -1, -1, -1, -1, -1, -1, 339, 340, -1,
+ -1, -1, 344, -1, -1, -1, 420, 349, 350, -1,
+ -1, -1, 354, -1, -1, 285, 358, 359, 360, -1,
+ -1, 363, -1, 365, 366, -1, 368, 297, 298, -1,
+ -1, -1, -1, -1, 376, 377, -1, -1, 308, -1,
+ -1, -1, -1, -1, 386, -1, -1, 317, -1, -1,
+ -1, -1, -1, -1, -1, -1, 326, -1, -1, 257,
+ 330, -1, 404, -1, -1, -1, -1, -1, -1, 339,
+ 340, -1, -1, -1, 344, -1, -1, -1, 420, 349,
+ 350, -1, -1, -1, -1, -1, -1, 285, 358, 359,
+ 360, -1, -1, 363, -1, 365, 366, -1, 368, 297,
+ 298, -1, -1, -1, -1, -1, 376, 377, -1, -1,
+ 308, -1, -1, -1, -1, -1, 386, -1, -1, 317,
+ -1, -1, -1, -1, -1, -1, -1, -1, 326, -1,
+ -1, 257, 330, -1, 404, -1, -1, -1, -1, -1,
+ -1, 339, 340, -1, -1, -1, 344, -1, -1, -1,
+ 420, 349, 350, -1, -1, -1, -1, -1, -1, 285,
+ 358, 359, 360, -1, -1, 363, -1, 365, 366, -1,
+ 368, 297, 298, -1, -1, -1, -1, -1, 376, 377,
+ -1, -1, 308, -1, -1, -1, -1, -1, 386, -1,
+ -1, 317, -1, -1, -1, -1, -1, -1, -1, -1,
+ 326, -1, -1, 257, 330, -1, 404, -1, -1, -1,
+ -1, -1, -1, 339, 340, -1, -1, -1, 344, -1,
+ -1, -1, 420, 349, 350, -1, -1, -1, -1, -1,
+ -1, 285, 358, 359, 360, -1, -1, 363, -1, 365,
+ 366, -1, 368, 297, 298, -1, -1, -1, -1, -1,
+ 376, 377, 306, -1, 308, -1, -1, -1, -1, -1,
+ 386, -1, -1, 317, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 330, -1, 404, -1,
+ -1, -1, -1, -1, -1, 339, 340, -1, -1, -1,
+ 344, -1, -1, -1, 420, 349, 350, -1, -1, -1,
+ -1, -1, -1, 285, 358, 359, 360, -1, -1, 363,
+ -1, 365, 366, -1, 368, 297, 298, -1, -1, -1,
+ -1, -1, 376, 377, -1, -1, 308, -1, -1, -1,
+ -1, -1, 386, -1, -1, 317, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 330, -1,
+ 404, -1, -1, -1, -1, -1, -1, 339, 340, -1,
+ -1, -1, 344, -1, -1, -1, 420, 349, 350, -1,
+ -1, -1, -1, -1, -1, 285, 358, 359, 360, -1,
+ -1, 363, -1, 365, 366, -1, 368, 297, 298, -1,
+ -1, -1, -1, -1, 376, 377, -1, -1, 308, -1,
+ -1, -1, -1, -1, 386, -1, -1, 317, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 330, -1, 404, -1, -1, -1, -1, -1, -1, 339,
+ 340, -1, -1, -1, 344, -1, -1, -1, 420, 349,
+ 350, -1, -1, -1, -1, -1, -1, 285, 358, 359,
+ 360, -1, -1, 363, -1, 365, 366, -1, 368, 297,
+ 298, -1, -1, -1, -1, -1, 376, 377, 306, -1,
+ 308, -1, -1, -1, -1, -1, 386, -1, -1, 317,
+ -1, -1, -1, -1, -1, -1, -1, -1, 297, -1,
+ -1, -1, 330, -1, 404, -1, -1, 306, -1, -1,
+ -1, 339, 340, -1, -1, -1, 344, -1, 317, 318,
+ 420, 349, 350, -1, -1, -1, -1, -1, -1, 328,
+ 358, 359, 360, -1, -1, 363, -1, 365, 366, -1,
+ 368, 340, -1, -1, -1, -1, -1, -1, 376, 377,
+ 349, 350, -1, -1, -1, -1, -1, -1, 386, 358,
+ 359, 360, -1, 297, 363, 364, 365, 366, -1, 368,
+ -1, -1, 306, -1, -1, -1, 404, 376, 377, -1,
+ -1, -1, -1, 317, 318, -1, -1, -1, 387, -1,
+ -1, -1, 420, 297, 328, -1, -1, -1, -1, -1,
+ -1, -1, 306, -1, -1, 404, 340, -1, -1, -1,
+ -1, -1, -1, 317, 318, 349, 350, -1, -1, -1,
+ -1, 420, -1, -1, 358, 359, 360, -1, 297, 363,
+ 364, 365, 366, -1, 368, -1, 340, 306, -1, -1,
+ -1, -1, 376, 377, -1, 349, 350, -1, 317, 318,
+ -1, -1, -1, 387, 358, 359, 360, -1, 297, 363,
+ 364, 365, 366, -1, 368, -1, -1, 306, -1, -1,
+ 404, 340, 376, 377, -1, -1, -1, -1, 317, 318,
+ 349, 350, -1, 387, -1, -1, 420, -1, -1, 358,
+ 359, 360, -1, 297, 363, 364, 365, 366, -1, 368,
+ 404, 340, 306, -1, -1, -1, -1, 376, 377, -1,
+ 349, 350, -1, 317, 318, -1, 420, -1, 387, 358,
+ 359, 360, -1, 297, 363, 364, 365, 366, -1, 368,
+ -1, -1, 306, -1, -1, 404, 340, 376, 377, -1,
+ -1, -1, -1, 317, 318, 349, 350, -1, 387, -1,
+ -1, 420, -1, -1, 358, 359, 360, -1, -1, 363,
+ 364, 365, 366, -1, 368, 404, 340, -1, -1, -1,
+ -1, -1, 376, 377, -1, 349, 350, -1, -1, -1,
+ -1, 420, -1, 387, 358, 359, 360, -1, -1, 363,
+ 364, 365, 366, -1, 368, -1, 285, -1, -1, -1,
+ 404, -1, 376, 377, -1, -1, -1, -1, 297, 298,
+ -1, -1, -1, 387, -1, -1, 420, 306, -1, 308,
+ -1, -1, -1, -1, -1, -1, -1, -1, 317, -1,
+ 404, -1, -1, -1, -1, -1, 285, -1, -1, -1,
+ -1, 330, -1, -1, -1, -1, 420, -1, 297, 298,
+ 339, 340, -1, -1, -1, 344, -1, 306, -1, 308,
+ 349, 350, -1, -1, -1, -1, -1, -1, 317, 358,
+ 359, 360, -1, -1, 363, -1, 365, 366, -1, 368,
+ -1, 330, -1, -1, -1, -1, -1, 376, 377, -1,
+ 339, 340, -1, -1, -1, 344, -1, 386, -1, -1,
+ 349, 350, -1, -1, -1, -1, -1, -1, 285, 358,
+ 359, 360, -1, -1, 363, 404, 365, 366, -1, 368,
+ 297, 298, -1, -1, -1, -1, -1, 376, 377, -1,
+ -1, 308, -1, -1, -1, -1, -1, 386, -1, -1,
+ 317, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 330, -1, 404, -1, -1, -1, -1,
+ -1, -1, 339, 340, -1, -1, -1, 344, -1, -1,
+ -1, -1, 349, 350, -1, -1, -1, -1, -1, -1,
+ -1, 358, 359, 360, -1, -1, 363, -1, 365, 366,
+ -1, 368, -1, -1, -1, -1, -1, -1, -1, 376,
+ 377, -1, -1, -1, -1, -1, -1, -1, -1, 386,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 404,
+ };
+
+#line 4902 "mb-parser.jay"
+
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+ get {
+ return lexer;
+ }
+}
+
+public static 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);
+ }
+}
+
+Block declare_local_variables (Expression dummy_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;
+ //
+
+ VariableDeclaration.FixupTypes (variable_declarators);
+ // FIXME: Should VariableDeclaration.FixupArrayTypes be called here
+
+ if (current_block.Used)
+ implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
+ else
+ implicit_block = current_block;
+
+
+ foreach (VariableDeclaration decl in variable_declarators){
+ Expression type = decl.type;
+ 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 ();
+ inits.Add (decl);
+ }
+ }
+ }
+
+ if (inits == null)
+ return implicit_block;
+
+ foreach (VariableDeclaration decl in inits){
+ Assign assign;
+ Expression expr;
+ Expression type = decl.type;
+
+ if ((decl.expression_or_array_initializer is Expression) ||
+ (decl.expression_or_array_initializer is New)) {
+ 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 dummy_type, ArrayList variable_declarators)
+{
+ Block implicit_block;
+ VariableDeclaration.FixupTypes (variable_declarators);
+
+ if (current_block.Used)
+ implicit_block = new Block (current_block, Block.Flags.Implicit);
+ else
+ implicit_block = current_block;
+
+ foreach (VariableDeclaration decl in variable_declarators){
+ Expression type = decl.type;
+ implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
+ current_local_parameters, decl.Location);
+ }
+
+ return implicit_block;
+}
+
+
+
+struct VarName {
+ public object Name;
+ public object Type;
+ public object Rank;
+
+ public VarName (object n, object t, object r)
+ {
+ Name = n;
+ Type = t;
+ Rank = r;
+ }
+ }
+
+
+// <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 string DocComment;
+ public Expression type;
+ public ArrayList dims;
+
+ public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
+ {
+ this.identifier = id;
+ this.expression_or_array_initializer = eoai;
+ this.Location = l;
+ this.OptAttributes = opt_attrs;
+ this.type = t;
+ this.dims = null;
+ }
+
+ public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
+ {
+ }
+
+ public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
+ {
+ }
+
+ public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
+ (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
+ {
+ }
+
+ public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
+ {
+ // FIXME : This is broken: only the first rank is parsed
+ return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
+ }
+
+ public static void FixupTypes (ArrayList vars)
+ {
+ int varcount = vars.Count;
+ VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
+
+ if (last_var.type == null)
+ last_var.type = TypeManager.system_object_expr;
+
+ Expression cur_type = last_var.type;
+ int n = varcount - 1;
+
+ while (n >= 0) {
+ VariableDeclaration var = (VariableDeclaration) vars[n--];
+ if (var.type == null)
+ var.type = cur_type;
+ else
+ cur_type = var.type;
+ }
+ }
+
+ public static bool IndexesSpecifiedInRank (ArrayList IndexList)
+ {
+ bool res = false;
+
+ if (IndexList != null) {
+ foreach (Expression e in IndexList)
+ if (!(e is EmptyExpression)) {
+ res = true;
+ break;
+ }
+ }
+ return (res);
+ }
+
+
+ public static bool IndexesSpecified (ArrayList ranks)
+ {
+ bool res = false;
+
+ if (ranks != null) {
+ foreach (ArrayList IndexList in ranks) {
+ if (IndexesSpecifiedInRank (IndexList)) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return (res);
+ }
+
+ public static string StripDims (string varname, ref string d)
+ {
+ string res = varname;
+ string dres = "";
+
+ if (varname.IndexOf("[") >= 0) {
+ dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
+ res = varname.Substring(0, varname.IndexOf("["));
+ }
+ d = dres;
+ return (res);
+ }
+
+ public static string StripDims (string varname)
+ {
+ string dres = "";
+
+ return (StripDims(varname, ref dres));
+ }
+
+ public static string StripIndexesFromDims (string dims)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (char c in dims)
+ if (c == ',' || c == ']' || c == '[')
+ sb.Append (c);
+
+ return sb.ToString();
+ }
+
+ public static string BuildRank (ArrayList rank)
+ {
+ bool allEmpty;
+ return BuildRank(rank, out allEmpty);
+ }
+
+ public static string BuildRank (ArrayList rank, out bool allEmpty)
+ {
+ string res = "";
+
+ res += "[";
+ allEmpty = true;
+ bool first = true;
+ foreach (object e in rank) {
+ if (!(e is EmptyExpression))
+ allEmpty = false;
+ if (!first)
+ res += ",";
+ first = false;
+ }
+
+ res += "]";
+ return res;
+ }
+
+ public static string BuildRanks (ArrayList rank_specifiers, bool mustBeEmpty, Location loc)
+ {
+ string res = "";
+
+ bool allEmpty = true;
+ foreach (ArrayList rank in rank_specifiers) {
+ bool tmp;
+ res = BuildRank (rank, out tmp) + res;
+ if (!tmp)
+ allEmpty = false;
+ }
+ if (!allEmpty && mustBeEmpty)
+ Report.Error (30638, loc, "Array bounds cannot appear in type specifiers.");
+
+ return res;
+ }
+
+ public static void VBFixIndexList (ref ArrayList IndexList)
+ {
+ if (IndexList != null) {
+ for (int x = 0; x < IndexList.Count; x++) {
+ Expression e = (Expression) IndexList[x];
+ if (!(e is EmptyExpression)) {
+ IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
+ }
+ }
+ }
+ }
+
+// public static bool IsArrayDecl (Parser t)
+// {
+// // return (varname.IndexOf("[") >= 0);
+// return (t.current_rank_specifiers != null);
+// }
+
+ public static void VBFixIndexLists (ref ArrayList ranks)
+ {
+ if (ranks != null) {
+ for (int x = 0; x < ranks.Count; x++) {
+ ArrayList IndexList = (ArrayList) ranks[x];
+ VBFixIndexList (ref IndexList);
+ }
+ }
+ }
+
+ public static void FixupArrayTypes (ArrayList vars)
+ {
+ int varcount = vars.Count;
+ string dims;
+
+ foreach (VariableDeclaration var in vars) {
+ if (var.identifier.EndsWith(",")) {
+ dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
+ var.identifier.LastIndexOf(",")) + "]";
+ var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
+ var.type = new ComposedCast (var.type, (string) dims, var.Location);
+ }
+ }
+ }
+}
+
+
+// public Property BuildSimpleProperty (Expression p_type, string name,
+// Field p_fld, int mod_flags,
+// Attributes attrs, Location loc)
+// {
+// Property p;
+// Block get_block, set_block;
+// Accessor acc_set, acc_get;
+// StatementExpression a_set;
+// Statement a_get;
+// Parameter [] args;
+
+// // Build SET Block
+// Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
+// args = new Parameter [1];
+// args [0] = implicit_value_parameter;
+
+// Parameters set_params = new Parameters (args, null, loc);
+// a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
+// (Expression) new SimpleName("value", loc), loc), loc);
+
+// set_block = new Block (current_block, set_params, loc, Location.Null);
+// set_block.AddStatement ((Statement) a_set);
+// acc_set = new Accessor (set_block, attrs);
+
+// // Build GET Block
+// a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
+// get_block = new Block (current_block, null, loc, Location.Null);
+// get_block.AddStatement ((Statement) a_get);
+// acc_get = new Accessor (get_block, attrs);
+
+// p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
+
+// return (p);
+// }
+
+void start_block ()
+{
+ if (current_block == null){
+ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block,
+ current_local_parameters, lexer.Location);
+ top_current_block = current_block;
+ } else {
+ current_block = new Block (current_block, current_local_parameters,
+ lexer.Location, Location.Null);
+ }
+}
+
+
+Block end_block ()
+{
+ Block res;
+
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ res = current_block;
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+ if (current_block == null)
+ top_current_block = null;
+
+ return res;
+}
+
+// private void AddHandler (Expression evt_definition, Expression handler_exp)
+// {
+// AddHandler (current_block, evt_definition, handler_exp);
+// }
+
+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;
+ }
+}
+
+// private void AddHandler (Block b, Expression evt_id, Expression handles_exp)
+// {
+// Expression evt_target;
+// Location loc = lexer.Location;
+
+// Statement addhnd = (Statement) new AddHandler (evt_id,
+// handles_exp,
+// loc);
+
+// b.AddStatement (addhnd);
+// }
+
+// private void RaiseEvent (string evt_name, ArrayList args)
+// {
+// Location loc = lexer.Location;
+
+// Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
+// Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
+// current_block.AddStatement (s);
+// }
+
+// private void RemoveHandler (Block b, Expression evt_definition, Expression handler_exp)
+// {
+// Expression evt_target;
+// Location loc = lexer.Location;
+
+// Statement rmhnd = (Statement) new RemoveHandler (evt_definition,
+// handler_exp,
+// loc);
+// b.AddStatement (rmhnd);
+// }
+
+// <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>
+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 + ")");
+
+}
+
+// private void RemoveHandler (Expression evt_definition, Expression handler_exp)
+// {
+// RemoveHandler (current_block, evt_definition, handler_exp);
+// }
+
+// FIXME: This needs to be fixed for This and Base access because the way the name of the
+// mbas' constructor is changed from "New" to current_container.Basename
+
+private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
+{
+ ConstructorInitializer ci = null;
+
+ if (s.Count > 0) {
+ if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
+ Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
+
+ if (i.expr is BaseAccess) {
+ BaseAccess ba = (BaseAccess) i.expr;
+ if (ba.member == "New" || ba.member == ".ctor") {
+ ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
+ s.RemoveAt(0);
+ }
+ }
+ if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
+ ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location);
+ s.RemoveAt(0);
+ }
+ }
+ }
+ return ci;
+}
+
+void Error_ExpectingTypeName (Location l, Expression expr)
+{
+ if (expr is Invocation){
+ Report.Error (1002, l, "; expected");
+ } else {
+ Report.Error (-1, l, "Invalid Type definition");
+ }
+}
+
+static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
+ return true;
+}
+
+private void ReportError9998()
+{
+ Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
+}
+
+public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
+{
+ current_namespace = new NamespaceEntry (null, file, null, Location.Null);
+ this.name = file.Name;
+ this.file = file;
+ current_container = RootContext.Tree.Types;
+ current_container.NamespaceEntry = current_namespace;
+ oob_stack = new Stack ();
+ switch_stack = new Stack ();
+
+ lexer = new Tokenizer (reader, file, defines);
+
+ ifElseStateMachine = new IfElseStateMachine();
+ tokenizerController = new TokenizerController(lexer);
+}
+
+public void parse ()
+{
+ try {
+ if (yacc_verbose_flag > 1)
+ yyparse (lexer, new yydebug.yyDebugSimple ());
+ else
+ yyparse (lexer);
+ Tokenizer tokenizer = lexer as Tokenizer;
+ tokenizer.cleanup ();
+ } catch (Exception e){
+ //
+ // Removed for production use, use parser verbose to get the output.
+ //
+ // Console.WriteLine (e);
+ Report.Error (-25, lexer.Location, "Parsing error");
+ if (yacc_verbose_flag > 0)
+ Console.WriteLine (e);
+ }
+}
+
+
+// protected override int parse ()
+// {
+// RootContext.InitializeImports(ImportsList);
+// current_namespace = new Namespace (null, RootContext.RootNamespace);
+// current_container = RootContext.Tree.Types;
+// current_container.Namespace = current_namespace;
+// oob_stack = new Stack ();
+// switch_stack = new Stack ();
+// expr_stack = new Stack ();
+// tmp_blocks = new Stack();
+// with_stack = new Stack();
+// statement_stack = new Stack();
+
+// allow_global_attribs = true;
+// expecting_global_attribs = false;
+// expecting_local_attribs = false;
+// local_attrib_section_added = false;
+
+// UseExtendedSyntax = name.EndsWith(".mbs");
+// OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
+// OptionStrict = InitialOptionStrict || UseExtendedSyntax;
+// OptionCompareBinary = InitialOptionCompareBinary;
+
+// lexer = new Tokenizer (input, name, defines);
+
+// ifElseStateMachine = new IfElseStateMachine();
+// tokenizerController = new TokenizerController(lexer);
+
+// StringBuilder value = new StringBuilder ();
+// try {
+// if (yacc_verbose_flag > 0)
+// yyparse (lexer, new yydebug.yyDebugSimple ());
+// else {
+// yyparse (lexer);
+// cleanup();
+// }
+// }
+// catch(MBASException e) {
+// Report.Error(e.code, e.loc, e.Message);
+// }
+// catch (Exception e) {
+// if (Report.Stacktrace)
+// Console.WriteLine(e);
+// Report.Error (29999, lexer.Location, "Parsing error");
+// }
+
+// RootContext.VerifyImports();
+
+// return Report.Errors;
+// }
+
+// void cleanup()
+// {
+// try {
+// ifElseStateMachine.HandleToken(IfElseStateMachine.Token.EOF);
+// }
+// catch(ApplicationException) {
+// throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+// }
+
+// if(in_external_source)
+// Report.Error (30579, lexer.Location, "'#ExternalSource' directives must end with matching '#End ExternalSource'");
+
+// if(in_marked_region > 0)
+// Report.Error (30205, lexer.Location, "'#Region' directive must be followed by a matching '#End Region'");
+// }
+
+void HandleConditionalDirective(IfElseStateMachine.Token tok, BoolLiteral expr)
+{
+ try {
+ tokenizerController.PositionTokenizerCursor(tok, expr);
+ }
+ catch(ApplicationException) {
+ tok = IfElseStateMachine.Token.EOF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+}
+/* end end end */
+
+// <summary>
+// Given the @class_name name, it creates a fully qualified name
+// based on the containing declaration space
+// </summary>
+MemberName
+MakeName (MemberName class_name)
+{
+ string ns = current_namespace.FullName;
+
+ if (current_container.Name == ""){
+ if (ns != "")
+ return new MemberName (new MemberName (ns), class_name);
+ else
+ return class_name;
+ } else {
+ return new MemberName (current_container.MemberName, class_name);
+ }
+}
+
+}
+#line default
+namespace yydebug {
+ using System;
+ internal interface yyDebug {
+ void push (int state, Object value);
+ void lex (int state, int token, string name, Object value);
+ void shift (int from, int to, int errorFlag);
+ void pop (int state);
+ void discard (int state, int token, string name, Object value);
+ void reduce (int from, int to, int rule, string text, int len);
+ void shift (int from, int to);
+ void accept (Object value);
+ void error (string message);
+ void reject ();
+ }
+
+ class yyDebugSimple : yyDebug {
+ void println (string s){
+ Console.Error.WriteLine (s);
+ }
+
+ public void push (int state, Object value) {
+ println ("push\tstate "+state+"\tvalue "+value);
+ }
+
+ public void lex (int state, int token, string name, Object value) {
+ println("lex\tstate "+state+"\treading "+name+"\tvalue "+value);
+ }
+
+ public void shift (int from, int to, int errorFlag) {
+ switch (errorFlag) {
+ default: // normally
+ println("shift\tfrom state "+from+" to "+to);
+ break;
+ case 0: case 1: case 2: // in error recovery
+ println("shift\tfrom state "+from+" to "+to
+ +"\t"+errorFlag+" left to recover");
+ break;
+ case 3: // normally
+ println("shift\tfrom state "+from+" to "+to+"\ton error");
+ break;
+ }
+ }
+
+ public void pop (int state) {
+ println("pop\tstate "+state+"\ton error");
+ }
+
+ public void discard (int state, int token, string name, Object value) {
+ println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value);
+ }
+
+ public void reduce (int from, int to, int rule, string text, int len) {
+ println("reduce\tstate "+from+"\tuncover "+to
+ +"\trule ("+rule+") "+text);
+ }
+
+ public void shift (int from, int to) {
+ println("goto\tfrom state "+from+" to "+to);
+ }
+
+ public void accept (Object value) {
+ println("accept\tvalue "+value);
+ }
+
+ public void error (string message) {
+ println("error\t"+message);
+ }
+
+ public void reject () {
+ println("reject");
+ }
+
+ }
+}
+// %token constants
+ class Token {
+ public const int EOF = 257;
+ public const int NONE = 258;
+ public const int ERROR = 259;
+ public const int ADDHANDLER = 260;
+ public const int ADDRESSOF = 261;
+ public const int ALIAS = 262;
+ public const int AND = 263;
+ public const int ANDALSO = 264;
+ public const int ANSI = 265;
+ public const int AS = 266;
+ public const int ASSEMBLY = 267;
+ public const int AUTO = 268;
+ public const int BINARY = 269;
+ public const int BOOLEAN = 270;
+ public const int BYREF = 271;
+ public const int BYTE = 272;
+ public const int BYVAL = 273;
+ public const int CALL = 274;
+ public const int CASE = 275;
+ public const int CATCH = 276;
+ public const int CBOOL = 277;
+ public const int CBYTE = 278;
+ public const int CCHAR = 279;
+ public const int CDATE = 280;
+ public const int CDEC = 281;
+ public const int CDBL = 282;
+ public const int CHAR = 283;
+ public const int CINT = 284;
+ public const int CLASS = 285;
+ public const int CLNG = 286;
+ public const int COBJ = 287;
+ public const int COMPARE = 288;
+ public const int CONST = 289;
+ public const int CSHORT = 290;
+ public const int CSNG = 291;
+ public const int CSTR = 292;
+ public const int CTYPE = 293;
+ public const int DATE = 294;
+ public const int DECIMAL = 295;
+ public const int DECLARE = 296;
+ public const int DEFAULT = 297;
+ public const int DELEGATE = 298;
+ public const int DIM = 299;
+ public const int DIRECTCAST = 300;
+ public const int DO = 301;
+ public const int DOUBLE = 302;
+ public const int EACH = 303;
+ public const int ELSE = 304;
+ public const int ELSEIF = 305;
+ public const int END = 306;
+ public const int ENDIF = 307;
+ public const int ENUM = 308;
+ public const int EOL = 309;
+ public const int ERASE = 310;
+ public const int EVENT = 311;
+ public const int EXIT = 312;
+ public const int EXPLICIT = 313;
+ public const int FALSE = 314;
+ public const int FINALLY = 315;
+ public const int FOR = 316;
+ public const int FRIEND = 317;
+ public const int FUNCTION = 318;
+ public const int GET = 319;
+ public const int GETTYPE = 320;
+ public const int GOSUB = 321;
+ public const int GOTO = 322;
+ public const int HANDLES = 323;
+ public const int IF = 324;
+ public const int IMPLEMENTS = 325;
+ public const int IMPORTS = 326;
+ public const int IN = 327;
+ public const int INHERITS = 328;
+ public const int INTEGER = 329;
+ public const int INTERFACE = 330;
+ public const int IS = 331;
+ public const int LET = 332;
+ public const int LIB = 333;
+ public const int LIKE = 334;
+ public const int LONG = 335;
+ public const int LOOP = 336;
+ public const int ME = 337;
+ public const int MOD = 338;
+ public const int MODULE = 339;
+ public const int MUSTINHERIT = 340;
+ public const int MUSTOVERRIDE = 341;
+ public const int MYBASE = 342;
+ public const int MYCLASS = 343;
+ public const int NAMESPACE = 344;
+ public const int NEW = 345;
+ public const int NEXT = 346;
+ public const int NOT = 347;
+ public const int NOTHING = 348;
+ public const int NOTINHERITABLE = 349;
+ public const int NOTOVERRIDABLE = 350;
+ public const int OBJECT = 351;
+ public const int OFF = 352;
+ public const int ON = 353;
+ public const int OPTION = 354;
+ public const int OPTIONAL = 355;
+ public const int OR = 356;
+ public const int ORELSE = 357;
+ public const int OVERLOADS = 358;
+ public const int OVERRIDABLE = 359;
+ public const int OVERRIDES = 360;
+ public const int PARAM_ARRAY = 361;
+ public const int PRESERVE = 362;
+ public const int PRIVATE = 363;
+ public const int PROPERTY = 364;
+ public const int PROTECTED = 365;
+ public const int PUBLIC = 366;
+ public const int RAISEEVENT = 367;
+ public const int READONLY = 368;
+ public const int REDIM = 369;
+ public const int REM = 370;
+ public const int REMOVEHANDLER = 371;
+ public const int RESUME = 372;
+ public const int RETURN = 373;
+ public const int SELECT = 374;
+ public const int SET = 375;
+ public const int SHADOWS = 376;
+ public const int SHARED = 377;
+ public const int SHORT = 378;
+ public const int SINGLE = 379;
+ public const int SIZEOF = 380;
+ public const int STATIC = 381;
+ public const int STEP = 382;
+ public const int STOP = 383;
+ public const int STRICT = 384;
+ public const int STRING = 385;
+ public const int STRUCTURE = 386;
+ public const int SUB = 387;
+ public const int SYNCLOCK = 388;
+ public const int TEXT = 389;
+ public const int THEN = 390;
+ public const int THROW = 391;
+ public const int TO = 392;
+ public const int TRUE = 393;
+ public const int TRY = 394;
+ public const int TYPEOF = 395;
+ public const int UNICODE = 396;
+ public const int UNTIL = 397;
+ public const int VARIANT = 398;
+ public const int WEND = 399;
+ public const int WHEN = 400;
+ public const int WHILE = 401;
+ public const int WITH = 402;
+ public const int WITHEVENTS = 403;
+ public const int WRITEONLY = 404;
+ public const int XOR = 405;
+ public const int YIELD = 406;
+ public const int HASH = 407;
+ public const int OPEN_BRACKET = 408;
+ public const int CLOSE_BRACKET = 409;
+ public const int OPEN_PARENS = 410;
+ public const int OPEN_BRACE = 411;
+ public const int CLOSE_BRACE = 412;
+ public const int CLOSE_PARENS = 413;
+ public const int DOT = 414;
+ public const int COMMA = 415;
+ public const int COLON = 416;
+ public const int PLUS = 417;
+ public const int MINUS = 418;
+ public const int ASSIGN = 419;
+ public const int OP_LT = 420;
+ public const int OP_GT = 421;
+ public const int STAR = 422;
+ public const int DIV = 423;
+ public const int OP_EXP = 424;
+ public const int INTERR = 425;
+ public const int OP_IDIV = 426;
+ public const int OP_CONCAT = 427;
+ public const int EXCLAMATION = 428;
+ public const int PERCENT = 429;
+ public const int LONGTYPECHAR = 430;
+ public const int AT_SIGN = 431;
+ public const int SINGLETYPECHAR = 432;
+ public const int NUMBER_SIGN = 433;
+ public const int DOLAR_SIGN = 434;
+ public const int ATTR_ASSIGN = 435;
+ public const int OP_LE = 437;
+ public const int OP_GE = 439;
+ public const int OP_NE = 441;
+ public const int OP_XOR = 443;
+ public const int xor = 444;
+ public const int OP_SHIFT_LEFT = 445;
+ public const int OP_SHIFT_RIGHT = 447;
+ public const int LITERAL_INTEGER = 449;
+ public const int LITERAL_SINGLE = 451;
+ public const int LITERAL_DOUBLE = 453;
+ public const int LITERAL_DECIMAL = 455;
+ public const int LITERAL_CHARACTER = 457;
+ public const int LITERAL_STRING = 459;
+ public const int LITERAL_DATE = 461;
+ public const int IDENTIFIER = 463;
+ public const int LOWPREC = 464;
+ public const int OP_OR = 465;
+ public const int OP_AND = 466;
+ public const int BITWISE_OR = 467;
+ public const int BITWISE_AND = 468;
+ public const int BITWISE_NOT = 469;
+ public const int CARRET = 470;
+ public const int UMINUS = 471;
+ public const int OP_INC = 472;
+ public const int OP_DEC = 473;
+ public const int HIGHPREC = 474;
+ public const int label_name = 475;
+ public const int yyErrorCode = 256;
+ }
+ namespace yyParser {
+ using System;
+ /** thrown for irrecoverable syntax errors and stack overflow.
+ */
+ internal class yyException : System.Exception {
+ public yyException (string message) : base (message) {
+ }
+ }
+
+ /** must be implemented by a scanner object to supply input to the parser.
+ */
+ internal interface yyInput {
+ /** move on to next token.
+ @return false if positioned beyond tokens.
+ @throws IOException on input error.
+ */
+ bool advance (); // throws java.io.IOException;
+ /** classifies current token.
+ Should not be called if advance() returned false.
+ @return current %token or single character.
+ */
+ int token ();
+ /** associated with current token.
+ Should not be called if advance() returned false.
+ @return value for token().
+ */
+ Object value ();
+ }
+ }
+} // close outermost namespace, that MUST HAVE BEEN opened in the prolog
--- /dev/null
+%{
+//
+// Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
+//
+// Authors: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
+// Anirban Bhattacharjee (banirban@novell.com)
+// Jambunathan K (kjambunathan@novell.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// Copyright (C) 2001, 2002, 2003, 2004 A Rafael D Teixeira
+// Copyright (C) 2003, 2004 Novell
+//
+//
+
+namespace Mono.CSharp
+{
+ using System.Text;
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using Mono.CSharp;
+
+ /// <summary>
+ /// The MonoBASIC Parser
+ /// </summary>
+// [DefaultParser]
+// public class Parser : GenericParser
+// {
+
+
+// /// <summary>
+// /// Current block is used to add statements as we find
+// /// them.
+// /// </summary>
+// Block current_block;
+
+// /// <summary>
+// /// Tmp block is used to store block endings in if/select's
+// /// </summary>
+// Block tmp_block;
+
+// /// <summary>
+// /// Tmp block is used to store tmp copies of expressions
+// /// </summary>
+// Expression tmp_expr;
+
+// /// <summary>
+// /// Tmp catch is used to store catch clauses in try..catch..finally
+// /// </summary>
+// ArrayList tmp_catch_clauses;
+
+// /// <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>
+// /// This are used when parsing parameters in property
+// /// declarations.
+// /// </summary>
+// Parameters set_parameters;
+// Parameters get_parameters;
+
+// /// <summary>
+// /// This is used by the sub_header parser to store modifiers
+// /// to be passed to sub/constructor
+// /// </summary>
+// int current_modifiers;
+
+// /// <summary>
+// /// This is used by the sub_header parser to store attributes
+// /// to be passed to sub/constructor
+// /// </summary>
+// Attributes current_attributes;
+
+// /// <summary>
+// /// Using during property parsing to describe the implicit
+// /// value parameter that is passed to the "set" accessor
+// /// method
+// /// </summary>
+// string get_implicit_value_parameter_name;
+
+// // <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 get_implicit_value_parameter_type;
+
+// /// <summary>
+// /// Using during property parsing to describe the implicit
+// /// value parameter that is passed to the "set" accessor
+// /// method
+// /// </summary>
+// string set_implicit_value_parameter_name;
+
+// // <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 set_implicit_value_parameter_type;
+
+// Location member_location;
+
+// // An out-of-band stack.
+// //
+// Stack oob_stack;
+
+// ArrayList current_rank_specifiers;
+
+// DoOptions do_type;
+// //
+// // Switch stack.
+// //
+// Stack switch_stack;
+
+// // Expression stack for nested ifs
+// Stack expr_stack;
+
+// Stack tmp_blocks;
+// Stack statement_stack;
+
+// // A stack for With expressions.
+// //
+// Stack with_stack;
+
+
+// static public bool InitialOptionExplicit = false;
+// static public bool InitialOptionStrict = false;
+// static public bool InitialOptionCompareBinary = true;
+// static public ArrayList ImportsList = null;
+
+// bool OptionExplicit;
+// bool OptionStrict;
+// bool OptionCompareBinary;
+
+// static public bool UseExtendedSyntax; // for ".mbs" files
+
+// bool implicit_modifiers;
+
+// public override string[] extensions()
+// {
+// string [] list = { ".vb", ".mbs" };
+// return list;
+// }
+
+
+ /// <summary>
+ /// The C# Parser
+ /// </summary>
+ public class CSharpParser {
+ NamespaceEntry current_namespace;
+ TypeContainer current_container;
+ TypeContainer current_class;
+
+ IIteratorContainer iterator_container;
+
+ /// <summary>
+ /// Current block is used to add statements as we find
+ /// them.
+ /// </summary>
+ Block current_block, top_current_block;
+
+ /// <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;
+
+ static public int yacc_verbose_flag;
+
+ // Name of the file we are parsing
+ public string name;
+
+ ///
+ /// The current file.
+ ///
+ SourceFile file;
+
+ /// This is used by the sub_header parser to store modifiers
+ /// to be passed to sub/constructor
+ int current_modifiers;
+
+ /// This is used by the sub_header parser to store attributes
+ /// to be passed to sub/constructor
+ Attributes current_attributes;
+
+ /// This is used by the attributes parser to syntactically
+ /// validate the attribute rules
+ bool allow_global_attribs = true;
+
+ bool expecting_global_attribs = false;
+ bool expecting_local_attribs = false;
+
+ bool local_attrib_section_added = false;
+
+ ///FIXME
+ ArrayList current_rank_specifiers;
+
+ /// <summary>
+ /// Using during property parsing to describe the implicit
+ /// value parameter that is passed to the "set" accessor
+ /// method
+ /// </summary>
+ string get_implicit_value_parameter_name;
+
+ // <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 get_implicit_value_parameter_type;
+
+ /// <summary>
+ /// Using during property parsing to describe the implicit
+ /// value parameter that is passed to the "set" accessor
+ /// method
+ /// </summary>
+ string set_implicit_value_parameter_name;
+
+ // <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 set_implicit_value_parameter_type;
+
+ /// <summary>
+ /// This are used when parsing parameters in property
+ /// declarations.
+ /// </summary>
+ Parameters set_parameters;
+ Parameters get_parameters;
+
+// static public ArrayList ImportsList = null;
+
+ bool implicit_modifiers;
+
+
+ /// <summary>
+ /// This is used as a helper class for handling of
+ /// pre-processor statements.
+ /// </summary>
+
+ // FIXME: This class MBASException is actually a kludge
+ // It can be done away with a more elegant replacement.
+
+ public class MBASException : ApplicationException
+ {
+ public int code;
+ public Location loc;
+
+ public MBASException(int code, Location loc, string text) : base(text)
+ {
+ this.code = code;
+ this.loc = loc;
+ }
+ }
+
+
+
+ public class IfElseStateMachine {
+
+ public enum State {
+ START,
+ IF_SEEN,
+ ELSEIF_SEEN,
+ ELSE_SEEN,
+ ENDIF_SEEN,
+ MAX
+ }
+
+ public enum Token {
+ START,
+ IF,
+ ELSEIF,
+ ELSE,
+ ENDIF,
+ EOF,
+ MAX
+ }
+
+ State state;
+ Stack stateStack;
+
+ public static Hashtable errStrings = new Hashtable();
+
+ int err=0;
+ static int[,] errTable = new int[(int)State.MAX, (int)Token.MAX];
+
+ static IfElseStateMachine()
+ {
+ // FIXME: Fix both the error nos and the error strings.
+ // Currently the error numbers and the error strings are
+ // just placeholders for getting the state-machine going.
+
+ errStrings.Add(0, "");
+ errStrings.Add(30012, "#If must end with a matching #End If");
+ errStrings.Add(30013, "#ElseIf, #Else or #End If must be preceded by a matching #If");
+ errStrings.Add(30014, "#ElseIf must be preceded by a matching #If or #ElseIf");
+ errStrings.Add(30028, "#Else must be preceded by a matching #If or #ElseIf");
+ errStrings.Add(32030, "#ElseIf cannot follow #Else as part of #If block");
+
+ errTable[(int)State.START, (int)Token.IF] = 0;
+ errTable[(int)State.START, (int)Token.ELSEIF] = 30014;
+ errTable[(int)State.START, (int)Token.ELSE] = 30028;
+ errTable[(int)State.START, (int)Token.ENDIF] = 30013;
+ errTable[(int)State.START, (int)Token.EOF] = 0;
+
+ errTable[(int)State.IF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ELSEIF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ELSE] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.IF_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSEIF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSE] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.ELSEIF_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ELSE_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ELSEIF] = 32030;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ELSE] = 32030;
+ errTable[(int)State.ELSE_SEEN, (int)Token.ENDIF] = 0;
+ errTable[(int)State.ELSE_SEEN, (int)Token.EOF] = 30012;
+
+ errTable[(int)State.ENDIF_SEEN, (int)Token.IF] = 0;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ELSEIF] = 30014;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ELSE] = 30028;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.ENDIF] = 30013;
+ errTable[(int)State.ENDIF_SEEN, (int)Token.EOF] = 0;
+ }
+
+ public IfElseStateMachine()
+ {
+ state = State.START;
+
+ stateStack = new Stack();
+ stateStack.Push(state);
+ }
+
+ // The parameter here need not be qualified with IfElseStateMachine
+ // But it hits a bug in mcs. So temporarily scoping it so that builds
+ // are not broken.
+
+ public void HandleToken(IfElseStateMachine.Token tok)
+ {
+ err = (int) errTable[(int)state, (int)tok];
+
+ if(err != 0)
+ throw new ApplicationException("Unexpected pre-processor directive #"+tok);
+
+ if(tok == Token.IF) {
+ stateStack.Push(state);
+ state = (State) tok;
+ }
+ else if(tok == Token.ENDIF) {
+ state = (State)stateStack.Pop();
+ }
+ else
+ state = (State)tok;
+ }
+
+ public int Error {
+ get {
+ return err;
+ }
+ }
+
+ public string ErrString {
+ get {
+ return (string) errStrings[err];
+ }
+ }
+ }
+
+
+ public class TokenizerController {
+
+ struct State
+ {
+ public bool CanAcceptTokens;
+ public bool CanSelectBlock;
+
+ }
+
+ State currentState;
+ Stack stateStack;
+ Tokenizer lexer;
+
+ public TokenizerController(Tokenizer lexer)
+ {
+ this.lexer = lexer;
+ stateStack = new Stack();
+
+ currentState.CanAcceptTokens = true;
+ currentState.CanSelectBlock = true;
+
+ stateStack.Push(currentState);
+ }
+
+ State parentState {
+ get {
+ return (State)stateStack.Peek();
+ }
+ }
+
+ public bool IsAcceptingTokens {
+ get {
+ return currentState.CanAcceptTokens;
+ }
+ }
+
+ public void PositionCursorAtNextPreProcessorDirective()
+ {
+ lexer.PositionCursorAtNextPreProcessorDirective();
+ }
+
+ public void PositionTokenizerCursor(IfElseStateMachine.Token tok, BoolLiteral expr)
+ {
+ if(tok == IfElseStateMachine.Token.ENDIF) {
+ currentState = (State)stateStack.Pop();
+
+ if(currentState.CanAcceptTokens)
+ return;
+ else {
+ PositionCursorAtNextPreProcessorDirective();
+ return;
+ }
+ }
+
+ if(tok == IfElseStateMachine.Token.IF) {
+ stateStack.Push(currentState);
+
+ currentState.CanAcceptTokens = parentState.CanAcceptTokens;
+ currentState.CanSelectBlock = true;
+ }
+
+ if(parentState.CanAcceptTokens &&
+ currentState.CanSelectBlock && (bool)(expr.GetValue()) ) {
+
+ currentState.CanAcceptTokens = true;
+ currentState.CanSelectBlock = false;
+ return;
+ }
+ else {
+ currentState.CanAcceptTokens = false;
+ PositionCursorAtNextPreProcessorDirective();
+ return;
+ }
+ }
+ }
+
+ bool in_external_source = false;
+ int in_marked_region = 0;
+
+ TokenizerController tokenizerController;
+ IfElseStateMachine ifElseStateMachine;
+
+
+
+%}
+
+%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 MonoBASIC keywords
+ */
+%token ADDHANDLER
+%token ADDRESSOF
+%token ALIAS
+%token AND
+%token ANDALSO
+%token ANSI
+%token AS
+%token ASSEMBLY
+%token AUTO
+%token BINARY
+%token BOOLEAN
+%token BYREF
+%token BYTE
+%token BYVAL
+%token CALL
+%token CASE
+%token CATCH
+%token CBOOL
+%token CBYTE
+%token CCHAR
+%token CDATE
+%token CDEC
+%token CDBL
+%token CHAR
+%token CINT
+%token CLASS
+%token CLNG
+%token COBJ
+%token COMPARE
+%token CONST
+%token CSHORT
+%token CSNG
+%token CSTR
+%token CTYPE
+%token DATE
+%token DECIMAL
+%token DECLARE
+%token DEFAULT
+%token DELEGATE
+%token DIM
+%token DIRECTCAST
+%token DO
+%token DOUBLE
+%token EACH
+%token ELSE
+%token ELSEIF
+%token END
+%token ENDIF
+%token ENUM
+%token EOL
+%token ERASE
+%token ERROR
+%token EVENT
+%token EXIT
+%token EXPLICIT
+%token FALSE
+%token FINALLY
+%token FOR
+%token FRIEND
+%token FUNCTION
+%token GET
+%token GETTYPE
+%token GOSUB
+%token GOTO
+%token HANDLES
+%token IF
+%token IMPLEMENTS
+%token IMPORTS
+%token IN
+%token INHERITS
+%token INTEGER
+%token INTERFACE
+%token IS
+%token LET
+%token LIB
+%token LIKE
+%token LONG
+%token LOOP
+%token ME
+%token MOD
+%token MODULE
+%token MUSTINHERIT
+%token MUSTOVERRIDE
+%token MYBASE
+%token MYCLASS
+%token NAMESPACE
+%token NEW
+%token NEXT
+%token NOT
+%token NOTHING
+%token NOTINHERITABLE
+%token NOTOVERRIDABLE
+%token OBJECT
+%token OFF
+%token ON
+%token OPTION
+%token OPTIONAL
+%token OR
+%token ORELSE
+%token OVERLOADS
+%token OVERRIDABLE
+%token OVERRIDES
+%token PARAM_ARRAY
+%token PRESERVE
+%token PRIVATE
+%token PROPERTY
+%token PROTECTED
+%token PUBLIC
+%token RAISEEVENT
+%token READONLY
+%token REDIM
+%token REM
+%token REMOVEHANDLER
+%token RESUME
+%token RETURN
+%token SELECT
+%token SET
+%token SHADOWS
+%token SHARED
+%token SHORT
+%token SINGLE
+%token SIZEOF
+%token STATIC
+%token STEP
+%token STOP
+%token STRICT
+%token STRING
+%token STRUCTURE
+%token SUB
+%token SYNCLOCK
+%token TEXT
+%token THEN
+%token THROW
+%token TO
+%token TRUE
+%token TRY
+%token TYPEOF
+%token UNICODE
+%token UNTIL
+%token VARIANT
+%token WEND
+%token WHEN
+%token WHILE
+%token WITH
+%token WITHEVENTS
+%token WRITEONLY
+%token XOR
+%token YIELD // MonoBASIC extension
+
+%token HASH
+
+/* MonoBASIC single character operators/punctuation. */
+
+%token OPEN_BRACKET "["
+%token CLOSE_BRACKET "]"
+%token OPEN_PARENS "("
+%token OPEN_BRACE "{"
+%token CLOSE_BRACE "}"
+%token CLOSE_PARENS ")"
+%token DOT "."
+%token COMMA ","
+%token COLON ":"
+
+%token PLUS "+"
+%token MINUS "-"
+%token ASSIGN "="
+%token OP_LT "<"
+%token OP_GT ">"
+%token STAR "*"
+%token DIV "/"
+%token OP_EXP "^"
+%token INTERR "?"
+%token OP_IDIV "\\" //FIXME: This should be "\"
+%token OP_CONCAT "&"
+%token EXCLAMATION "!"
+
+%token PERCENT "%"
+%token LONGTYPECHAR "&"
+%token AT_SIGN "@"
+%token SINGLETYPECHAR "!"
+%token NUMBER_SIGN "#"
+%token DOLAR_SIGN "$"
+
+%token ATTR_ASSIGN ":="
+
+/* MonoBASIC multi-character operators. */
+%token OP_LE "<="
+%token OP_GE ">="
+%token OP_NE "<>"
+%token OP_XOR "xor"
+//%token OP_MODULUS //"mod"
+
+/* VB.NET 2003 new bit-shift operators */
+%token OP_SHIFT_LEFT "<<"
+%token OP_SHIFT_RIGHT ">>"
+
+/* Numbers */
+%token LITERAL_INTEGER "int literal"
+%token LITERAL_SINGLE "float literal"
+%token LITERAL_DOUBLE "double literal"
+%token LITERAL_DECIMAL "decimal literal"
+%token LITERAL_CHARACTER "character literal"
+%token LITERAL_STRING "string literal"
+%token LITERAL_DATE "datetime 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 BITWISE_NOT CARRET UMINUS
+%nonassoc OP_INC OP_DEC
+%left OPEN_PARENS
+%left OPEN_BRACKET OPEN_BRACE
+%left DOT
+%right NOT
+%nonassoc HIGHPREC
+
+%start compilation_unit
+%%
+
+end_of_stmt
+ : logical_end_of_line
+ | COLON
+ ;
+
+logical_end_of_line
+ : EOL
+ | logical_end_of_line pp_directive
+ ;
+
+compilation_unit
+ : logical_end_of_line
+ opt_option_directives
+ opt_imports_directives
+ declarations
+ EOF
+ {
+ $$=$4;
+ }
+ |logical_end_of_line
+ opt_option_directives
+ opt_imports_directives
+ opt_attributes
+ EOF
+ {
+ /* ????? */ ;
+ }
+ ;
+
+opt_option_directives
+ : /* empty */
+ | option_directives
+ ;
+
+option_directives
+ : option_directive
+ | option_directives option_directive
+ ;
+
+option_directive
+ : option_explicit_directive
+ | option_strict_directive
+ | option_compare_directive
+ ;
+
+on_off
+ : /* empty */
+ {
+ $$ = (object)true;
+ }
+ | ON
+ {
+ $$ = (object)true;
+ }
+ | OFF
+ {
+ $$ = (object)false;
+ }
+ ;
+
+text_or_binary
+ : BINARY
+ {
+ $$ = (object)true;
+ }
+ | TEXT
+ {
+ $$ = (object)false;
+ }
+ ;
+
+option_explicit_directive
+ : OPTION EXPLICIT on_off logical_end_of_line
+ {
+// if (!UseExtendedSyntax)
+// OptionExplicit = (bool)$3;
+// else
+// Report.Warning (
+// 9999, lexer.Location,
+// "In MonoBASIC extended syntax explicit declaration is always required. So OPTION EXPLICIT is deprecated");
+ }
+ ;
+
+
+option_strict_directive
+ : OPTION STRICT on_off logical_end_of_line
+ {
+// if (!UseExtendedSyntax)
+// OptionStrict = (bool)$3;
+// else
+// Report.Warning (
+// 9999, lexer.Location,
+// "In MonoBASIC extended syntax strict assignability is always required. So OPTION STRICT is deprecated");
+ }
+ ;
+
+option_compare_directive
+ : OPTION COMPARE text_or_binary logical_end_of_line
+ {
+// OptionCompareBinary = (bool)$3;
+ }
+ ;
+
+opt_declarations
+ : /* empty */
+ | declarations
+ ;
+
+declarations
+ : declaration
+ | declarations declaration
+ ;
+
+declaration
+ : declaration_qualifiers
+ {
+// FIXME: Need to check declaration qualifiers for multi-file compilation
+// FIXME: Qualifiers cannot be applied to namespaces
+ allow_global_attribs = false;
+ }
+ namespace_declaration
+ {
+ current_namespace.DeclarationFound = true;
+ }
+ | declaration_qualifiers
+ {
+ // FIXME: Need to check declaration qualifiers for multi-file compilation
+ allow_global_attribs = false;
+ }
+ type_spec_declaration
+ {
+ string name = "";
+ int mod_flags;
+
+ if ($3 is Class){
+ Class c = (Class) $3;
+ mod_flags = c.ModFlags;
+ name = c.Name;
+ } else if ($3 is Struct){
+ Struct s = (Struct) $3;
+ 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;
+ }
+ ;
+
+identifier
+ : IDENTIFIER
+ | BINARY
+ | TEXT
+ | COMPARE
+ | EXPLICIT
+ | OFF
+ ;
+
+type_character
+ : PERCENT { $$ = TypeManager.system_int32_expr; }
+ | LONGTYPECHAR { $$ = TypeManager.system_int64_expr; }
+ | AT_SIGN { $$ = TypeManager.system_decimal_expr; }
+ | SINGLETYPECHAR { $$ = TypeManager.system_single_expr; }
+ | NUMBER_SIGN { $$ = TypeManager.system_double_expr; }
+ | DOLAR_SIGN { $$ = TypeManager.system_string_expr; }
+ ;
+
+opt_type_character
+ : /* empty */ { $$ = null; }
+ | type_character { $$ = $1; }
+ ;
+
+
+qualified_identifier
+ : identifier
+ {
+ $$ = new MemberName ((string) $1);
+ }
+ | qualified_identifier DOT identifier // FIXME: It should be qualified_identifier DOT identifier-or-keyword
+ {
+ $$ = new MemberName ((MemberName) $1, (string) $3, null);
+ }
+ ;
+
+opt_imports_directives
+ : /* empty */
+ | imports_directives
+ ;
+
+imports_directives
+ : imports_directive
+ | imports_directives imports_directive
+ ;
+
+imports_directive
+ : IMPORTS imports_terms logical_end_of_line
+ ;
+
+imports_terms
+ : imports_term
+ | imports_terms COMMA imports_term
+ ;
+
+imports_term
+ : namespace_or_type_name
+ {
+ string name = ((MemberName) $1).GetName ();
+ current_namespace.Using (name, lexer.Location);
+ }
+ | identifier ASSIGN namespace_or_type_name
+ {
+ current_namespace.UsingAlias ((string) $1, (MemberName) $3, lexer.Location);
+ }
+ ;
+
+
+opt_params
+ : /* empty */ { $$ = Parameters.EmptyReadOnlyParameters; }
+ | OPEN_PARENS CLOSE_PARENS { $$ = Parameters.EmptyReadOnlyParameters; }
+ | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS { $$ = $2; }
+ ;
+
+opt_attributes
+ : /* empty */
+ {
+ current_attributes = null;
+ }
+ | attribute_sections
+ {
+ $$ = $1;
+ local_attrib_section_added = false;
+ current_attributes = (Attributes) $1;
+ }
+ ;
+
+attribute_sections
+ : attribute_section
+ {
+ $$ = $1;
+ if ($1 == null) {
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ local_attrib_section_added = true;
+ allow_global_attribs = false;
+
+ $$ = new Attributes ((ArrayList) $1);
+ }
+
+ if (expecting_global_attribs) {
+ $$ = null;
+ CodeGen.AddGlobalAttributes ((ArrayList) $1);
+ }
+
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ }
+ | attribute_sections
+ {
+ $$ = lexer.Location;
+ }
+ attribute_section
+ {
+ $$ = $1;
+ if ($3 != null) {
+ ArrayList attrs = (ArrayList) $3;
+
+ if (expecting_local_attribs) {
+ if (local_attrib_section_added) {
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ Report.Error (30205, (Location) $2, "Multiple attribute sections may not be used; Coalesce multiple attribute sections in to a single attribute section");
+ break;
+ }
+
+ if ($1 == null)
+ $$ = new Attributes (attrs);
+ else
+ ((Attributes) $1).AddAttributes (attrs);
+
+ local_attrib_section_added = true;
+ allow_global_attribs = false;
+ }
+
+ if (expecting_global_attribs) {
+ $$ = null;
+ CodeGen.AddGlobalAttributes ((ArrayList) $3);
+ }
+ }
+
+ expecting_local_attribs = false;
+ expecting_global_attribs = false;
+ }
+ ;
+
+attribute_section
+ : OP_LT attribute_list OP_GT opt_end_of_stmt
+ {
+ $$ = null;
+ if ($2 != null) {
+ if (expecting_global_attribs && !(bool) $4) {
+ Report.Error (30205, lexer.Location, "End of statement expected");
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ if ((bool) $4) {
+ Report.Error (32035, lexer.Location, "Use a line continuation after the attribute specifier to apply it to the following statement.");
+ break;
+ }
+ }
+
+ $$ = $2;
+ }
+ }
+ ;
+
+opt_end_of_stmt
+ : /* empty */ { $$ = false; }
+ | end_of_stmt { $$ = true; }
+ ;
+
+attribute_list
+ : attribute
+ {
+ ArrayList attrs = null;
+ if ($1 != null) {
+ attrs = new ArrayList ();
+ attrs.Add ($1);
+ }
+ $$ = attrs;
+ }
+ | attribute_list COMMA attribute
+ {
+ ArrayList attrs = null;
+
+ if ($3 != null) {
+ attrs = ($1 == null) ? new ArrayList () : (ArrayList) $1;
+ attrs.Add ($3);
+ }
+
+ $$ = attrs;
+ }
+ ;
+
+attribute
+ : namespace_or_type_name
+ {
+ $$ = lexer.Location;
+ }
+ opt_attribute_arguments
+ {
+ $$ = null;
+
+ if (expecting_global_attribs)
+ Report.Error (32015, (Location) $2, "Expecting Assembly or Module attribute specifiers");
+ else {
+ expecting_local_attribs = true;
+ MemberName mname = (MemberName) $1;
+ string name = mname.GetName ();
+
+ $$ = new Attribute (null, name, (ArrayList) $3,
+ (Location) $2);
+ }
+ }
+ | attribute_target_specifier
+ {
+ $$ = lexer.Location;
+ }
+ COLON
+ namespace_or_type_name
+ {
+ $$ = lexer.Location;
+ }
+ opt_attribute_arguments
+ {
+ $$ = null;
+
+ string attribute_target = (string) $1;
+ if (attribute_target != "assembly" && attribute_target != "module") {
+ Report.Error (29999, lexer.Location, "`" + (string)$1 + "' is an invalid attribute modifier");
+ break;
+ }
+ if (!allow_global_attribs) {
+ Report.Error (30637, (Location) $2, "Global attribute statements must precede any declarations in a file");
+ break;
+ }
+
+ if (expecting_local_attribs) {
+ Report.Error (30183, (Location) $2, "Global attributes cannot be combined with local attributes");
+ break;
+ }
+
+ expecting_global_attribs = true;
+
+ MemberName mname = (MemberName) $4;
+ string aname = mname.GetName ();
+
+ $$ = new Attribute (attribute_target, aname, (ArrayList) $6, (Location) $5);
+ }
+ ;
+
+
+attribute_target_specifier
+ : ASSEMBLY { $$ = "assembly"; }
+ | MODULE { $$ = "module"; }
+ | namespace_or_type_name
+ ;
+
+
+opt_attribute_arguments
+ : /* empty */ { $$ = null; }
+ | OPEN_PARENS opt_attribute_arguments_list CLOSE_PARENS
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_attribute_arguments_list
+ : /* empty */
+ | attribute_arguments_list
+ ;
+
+attribute_arguments_list
+ : positional_argument_list
+ {
+ 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;
+ }
+ ;
+
+positional_argument_list
+ : constant_expression
+ {
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
+
+ $$ = args;
+ }
+ | positional_argument_list COMMA constant_expression
+ {
+ ArrayList args = (ArrayList) $1;
+ args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
+
+ $$ = args;
+ }
+ ;
+
+named_argument_list
+ : named_argument
+ {
+ ArrayList args = new ArrayList ();
+ args.Add ($1);
+
+ $$ = args;
+ }
+ | named_argument_list COMMA named_argument
+ {
+ ArrayList args = (ArrayList) $1;
+ args.Add ($3);
+
+ $$ = args;
+ }
+ ;
+
+named_argument
+ : identifier ATTR_ASSIGN constant_expression //FIXME: It should be identifier_or_keyword ATTR_ASSIGN constant_expression
+ {
+ $$ = new DictionaryEntry (
+ (string) $1,
+ new Argument ((Expression) $3, Argument.AType.Expression));
+ }
+ ;
+
+namespace_declaration
+ : NAMESPACE qualified_identifier logical_end_of_line
+ {
+ if (current_attributes != null) {
+ Report.Error(1518, Lexer.Location, "Attributes cannot be applied to namespaces."
+ + " Expected class, delegate, enum, interface, or struct");
+ }
+
+ MemberName name = (MemberName) $2;
+
+ if ((current_namespace.Parent != null) && (name.Left != null)) {
+ Report.Error (134, lexer.Location,
+ "Cannot use qualified namespace names in nested " +
+ "namespace declarations");
+ }
+
+ current_namespace = new NamespaceEntry (
+ current_namespace, file, name.GetName (), lexer.Location);
+ }
+ opt_declarations
+ END NAMESPACE logical_end_of_line
+ {
+ current_namespace = current_namespace.Parent;
+ }
+
+ ;
+
+declaration_qualifiers
+ : opt_attributes opt_modifiers
+ ;
+
+type_spec_declaration
+ : class_declaration
+ | module_declaration
+ | interface_declaration
+ | delegate_declaration
+ | struct_declaration
+ | enum_declaration
+ ;
+
+class_declaration
+ : CLASS identifier logical_end_of_line
+ {
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ MemberName name = MakeName (new MemberName ((string) $2));
+ int mod_flags = current_modifiers;
+
+
+ current_class = new Class (current_namespace, current_container, name,
+ mod_flags, (Attributes) current_attributes, lexer.Location);
+
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+ }
+ opt_inherits opt_implements
+
+ {
+ ArrayList bases = (ArrayList) $5;
+ ArrayList ifaces = (ArrayList) $6;
+
+ if (ifaces != null){
+ if (bases != null)
+ bases.AddRange(ifaces);
+ else
+ bases = ifaces;
+ }
+
+ if (bases != null) {
+ if (current_class.Name == "System.Object") {
+ Report.Error (537, current_class.Location,
+ "The class System.Object cannot have a base " +
+ "class or implement an interface.");
+ }
+ current_class.Bases = (ArrayList) bases;
+ }
+
+ current_class.Register ();
+ }
+ opt_class_member_declarations
+ END CLASS logical_end_of_line
+ {
+ $$ = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ ;
+
+opt_inherits
+ : /* empty */ { $$ = null; }
+ | INHERITS type_list logical_end_of_line { $$ = $2; }
+ ;
+
+opt_implements
+ : /* empty */ { $$ = null; }
+ | IMPLEMENTS type_list logical_end_of_line { $$ = $2; }
+ ;
+
+opt_modifiers
+ : /* empty */
+ {
+ $$ = (int) 0;
+ current_modifiers = 0;
+ }
+ | modifiers
+ {
+ $$ = $1;
+ current_modifiers = (int) $1;
+ }
+ ;
+
+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
+ : PUBLIC { $$ = Modifiers.PUBLIC; }
+ | PROTECTED { $$ = Modifiers.PROTECTED; }
+ | PRIVATE { $$ = Modifiers.PRIVATE; }
+ | SHARED { $$ = Modifiers.STATIC; }
+ | FRIEND { $$ = Modifiers.INTERNAL; }
+ | NOTINHERITABLE { $$ = Modifiers.SEALED; }
+ | OVERRIDABLE { $$ = Modifiers.VIRTUAL; }
+ | NOTOVERRIDABLE { $$ = Modifiers.NONVIRTUAL; }
+ | OVERRIDES { $$ = Modifiers.OVERRIDE; }
+ | OVERLOADS { $$ = Modifiers.NEW; }
+ | SHADOWS { $$ = Modifiers.SHADOWS; }
+ | MUSTINHERIT { $$ = Modifiers.ABSTRACT; }
+ | READONLY { $$ = Modifiers.READONLY; }
+ | DEFAULT { $$ = Modifiers.DEFAULT; }
+ | WRITEONLY { $$ = Modifiers.WRITEONLY; }
+ ;
+
+module_declaration
+ : MODULE identifier logical_end_of_line
+ {
+ MemberName name = MakeName(new MemberName ((string) $2));
+ current_class = new VBModule (current_namespace, current_container, name,
+ current_modifiers, current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl(name.GetName (true), current_class);
+
+ current_class.Register ();
+ }
+ opt_module_member_declarations
+ END MODULE logical_end_of_line
+ {
+ $$ = current_class;
+// FIXME: ?????
+// TypeManager.AddStandardModule (current_class);
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ ;
+
+opt_module_member_declarations
+ : /* empty */
+ | module_member_declarations
+ ;
+
+module_member_declarations
+ : module_member_declaration
+ | module_member_declarations module_member_declaration
+ ;
+
+module_member_declaration
+ : opt_attributes
+ opt_modifiers
+ {
+ current_modifiers = ((int)$2) | Modifiers.STATIC;
+ bool explicit_static = (((int) $2 & Modifiers.STATIC) > 0);
+ implicit_modifiers = (!explicit_static);
+ }
+
+ module_member_declarator
+ {
+ implicit_modifiers = false;
+ $$ = $3;
+ }
+ ;
+
+module_member_declarator
+ : constructor_declaration
+ | method_declaration
+ | field_declaration
+// | withevents_declaration /* This is a field but must be treated specially, see below */
+ | constant_declaration
+ | property_declaration
+ | event_declaration
+ | type_spec_declaration
+ ;
+
+
+constant_declaration
+ : CONST constant_declarators logical_end_of_line
+ {
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ int modflags = (int) current_modifiers;
+
+ // Structure members are Public by default
+ if ((current_container is Struct) && (modflags == 0))
+ modflags = Modifiers.PUBLIC;
+
+ ArrayList consts = (ArrayList) $2;
+ if(consts.Count > 0)
+ {
+ VariableDeclaration.FixupTypes ((ArrayList) $2);
+ VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
+
+ foreach (VariableDeclaration constant in (ArrayList) $2){
+ Location l = constant.Location;
+ Const c = new Const (current_class,
+ (Expression) constant.type,
+ (String) constant.identifier,
+ (Expression) constant.expression_or_array_initializer,
+ modflags, current_attributes, l);
+
+ current_container.AddConstant (c);
+ }
+ }
+ }
+ ;
+
+opt_class_member_declarations
+ : /* empty */
+ | class_member_declarations
+ ;
+
+class_member_declarations
+ : class_member_declaration
+ | class_member_declarations class_member_declaration
+ ;
+
+class_member_declaration
+ : opt_attributes
+ opt_modifiers
+ class_member_declarator
+ {
+ $$ = $3;
+ }
+ ;
+
+class_member_declarator
+ : field_declaration
+ | constant_declaration
+ | method_declaration
+ | constructor_declaration
+ | property_declaration
+ | event_declaration
+// | withevents_declaration /* This is a field but must be treated specially, see below */
+ | type_spec_declaration
+ ;
+
+
+method_declaration
+ : sub_declaration
+ | func_declaration
+// | must_override_declaration
+ ;
+
+// must_override_declaration
+// : must_override_sub_declaration
+// | must_override_func_declaration
+// ;
+
+// must_override_sub_declaration
+// : MUSTOVERRIDE SUB identifier opt_params opt_implement_clause logical_end_of_line
+// {
+// // if (current_container is Module)
+// // Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
+
+// if (current_container is Struct)
+// Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
+
+// current_modifiers |= Modifiers.ABSTRACT;
+
+// Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
+// (Parameters) $4, null, (ArrayList) $5, lexer.Location);
+
+// if (!(current_container is Class))
+// Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
+
+// $$ = method;
+// }
+// ;
+
+
+// must_override_func_declaration
+// : MUSTOVERRIDE FUNCTION identifier opt_type_character opt_params opt_type_with_ranks opt_implement_clause logical_end_of_line
+// {
+// Expression ftype = ($6 == null) ? (($4 == null) ? TypeManager.
+// system_object_expr : (Expression) $4 ) : (Expression) $6;
+
+// if (current_container is Module)
+// Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
+
+// if (current_container is Struct)
+// Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
+
+// current_modifiers |= Modifiers.ABSTRACT;
+
+// Method method = new Method ((Expression) ftype, (int) current_modifiers,
+// (string) $3,(Parameters) $5, null, (ArrayList) $7,
+// lexer.Location);
+
+// if (!(current_container is Class))
+// Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
+
+// $$ = method;
+// }
+// ;
+
+
+sub_declaration
+ : SUB identifier opt_params
+ {
+ MemberName name = new MemberName ((string) $2);
+
+ if ((current_container is Struct) && (current_modifiers == 0))
+ current_modifiers = Modifiers.PUBLIC;
+
+
+ GenericMethod generic = null;
+ Method method = new Method (current_class, generic, TypeManager.system_void_expr,
+ (int) current_modifiers, false, name,
+ (Parameters) $3, (Attributes) current_attributes,
+ lexer.Location);
+
+ current_local_parameters = (Parameters) $3;
+ $$ = method;
+
+ iterator_container = (IIteratorContainer) method;
+ }
+ opt_evt_handler opt_implement_clause logical_end_of_line
+ // FIXME: opt_event_handler and opt_implements_clause are yet to be handled
+ begin_block
+ opt_statement_list
+ end_block
+ END SUB logical_end_of_line
+ {
+ Method method = (Method) $4;
+ Block b = (Block) $10;
+ 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 = (ToplevelBlock) $10;
+ current_container.AddMethod (method);
+
+ current_local_parameters = null;
+ iterator_container = null;
+ }
+ ;
+
+func_declaration
+ : FUNCTION identifier opt_type_character
+ opt_params opt_type_with_ranks
+ {
+ MemberName name = new MemberName ((string) $2);
+ Expression rettype = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+
+ GenericMethod generic = null;
+
+ Method method = new Method (current_class, generic, rettype, current_modifiers,
+ false, name, (Parameters) $4, current_attributes,
+ lexer.Location);
+
+ current_local_parameters = (Parameters) $4;
+
+ $$ = method;
+ iterator_container = method;
+ }
+// FIXME: opt_implement_clauses needs to be taken care of
+ opt_implement_clause logical_end_of_line
+ begin_block
+ {
+ Method method = (Method) $6;
+
+ ArrayList retval = new ArrayList ();
+ retval.Add (new VariableDeclaration ((string) $2, method.Type, lexer.Location));
+ declare_local_variables (method.Type, retval, lexer.Location);
+ }
+ opt_statement_list
+ end_block
+ END FUNCTION logical_end_of_line
+ {
+ Method method = (Method) $6;
+ Block b = (Block) $12;
+ 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 = (ToplevelBlock) b;
+ current_container.AddMethod (method);
+
+ current_local_parameters = null;
+ iterator_container = null;
+ }
+ ;
+
+struct_declaration
+ : STRUCTURE identifier logical_end_of_line
+ opt_implement_clause
+ {
+ MemberName name = MakeName (new MemberName ((string) $2));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ current_class = new Struct (current_namespace, current_container, name, current_modifiers,
+ current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+
+ if ($4 != null)
+ current_class.Bases = (ArrayList) $4;
+
+ current_class.Register ();
+ }
+ opt_struct_member_declarations
+ {
+ $$ = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ END STRUCTURE logical_end_of_line
+ ;
+
+
+
+// FIXME: logical_end_of_line is actually part of the opt_implements_clause
+// This rule is temporary
+
+opt_logical_end_of_line
+ : /* empty */
+ | logical_end_of_line
+ ;
+
+
+opt_struct_member_declarations
+ : /* empty */
+ | struct_member_declarations
+ ;
+
+struct_member_declarations
+ : struct_member_declaration
+ | struct_member_declarations struct_member_declaration
+ ;
+
+struct_member_declaration
+ : opt_modifiers
+ struct_member_declarator
+ ;
+
+struct_member_declarator
+ : field_declaration
+ | constant_declaration
+ | constructor_declaration
+ | method_declaration
+// | property_declaration
+ | event_declaration
+ | type_spec_declaration
+
+
+// * This is only included so we can flag error 575:
+// * destructors only allowed on class types
+// | destructor_declaration
+ ;
+
+// event_declaration
+// : EVENT identifier AS type opt_implement_clause logical_end_of_line
+// {
+// VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
+
+// Event e = new Event ((Expression) $4, var.identifier,
+// null, current_modifiers,
+// current_attributes, (ArrayList) $5,
+// lexer.Location);
+
+// CheckDef (current_container.AddEvent (e), e.Name, e.Location);
+// }
+// | EVENT identifier opt_params opt_implement_clause logical_end_of_line
+// {
+// string delName = null;
+
+// if ($4 == null) {
+// delName = (string) $2;
+// delName = delName + "EventHandler";
+// Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate
+// (current_container, TypeManager.system_void_expr,
+// (int) current_modifiers, MakeName(delName), (Parameters) $3,
+// (Attributes) current_attributes, lexer.Location);
+
+// del.Namespace = current_namespace;
+// CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location);
+// } else {
+// ArrayList impls = (ArrayList) $4;
+// if (impls.Count > 1) {
+// string expstr = "Event '" + ((Expression) impls[1]).ToString () +
+// "' can not be implemented with Event '" +
+// (string) $2 + "', since it's delegate type does not match " +
+// "with the delegate type of '" + ((Expression) impls[0]).ToString () + "'";
+// Report.Error (31407, lexer.Location, expstr);
+// }
+// Expression impl = (Expression) impls[0];
+// delName = impl.ToString();
+// delName = delName.Substring (delName.LastIndexOf(".") + 1);
+// delName = delName + "EventHandler";
+// }
+
+// Event e = new Event (DecomposeQI (delName, lexer.Location),
+// (string) $2,
+// null, current_modifiers,
+// current_attributes, (ArrayList) $4,
+// lexer.Location);
+
+// CheckDef (current_container.AddEvent (e), e.Name, e.Location);
+// }
+// ;
+
+
+
+event_declaration
+ : EVENT identifier AS type opt_implement_clause logical_end_of_line
+ {
+ VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
+
+ MemberName name = new MemberName ((string) $2);
+
+ Event e = new EventField (current_class, (Expression) $4, current_modifiers, false, name,
+ var.expression_or_array_initializer, current_attributes,
+ lexer.Location);
+
+ current_container.AddEvent (e);
+ }
+
+// | EVENT identifier opt_params opt_implement_clause logical_end_of_line
+// {
+// string delName = null;
+
+// if ($4 == null) {
+// delName = (string) $2;
+// delName = delName + "EventHandler";
+// Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate
+// (current_container, TypeManager.system_void_expr,
+// (int) current_modifiers, MakeName(delName), (Parameters) $3,
+// (Attributes) current_attributes, lexer.Location);
+
+// del.Namespace = current_namespace;
+// CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location);
+// } else {
+// ArrayList impls = (ArrayList) $4;
+// if (impls.Count > 1) {
+// string expstr = "Event '" + ((Expression) impls[1]).ToString () +
+// "' can not be implemented with Event '" +
+// (string) $2 + "', since it's delegate type does not match " +
+// "with the delegate type of '" + ((Expression) impls[0]).ToString () + "'";
+// Report.Error (31407, lexer.Location, expstr);
+// }
+// Expression impl = (Expression) impls[0];
+// delName = impl.ToString();
+// delName = delName.Substring (delName.LastIndexOf(".") + 1);
+// delName = delName + "EventHandler";
+// }
+
+// Event e = new Event (DecomposeQI (delName, lexer.Location),
+// (string) $2,
+// null, current_modifiers,
+// current_attributes, (ArrayList) $4,
+// lexer.Location);
+
+// CheckDef (current_container.AddEvent (e), e.Name, e.Location);
+// }
+ ;
+
+enum_declaration
+ : ENUM identifier opt_type_spec logical_end_of_line
+ opt_enum_member_declarations
+ {
+ Location enum_location = lexer.Location;
+
+ Expression base_type = TypeManager.system_int32_expr;
+ if ((Expression) $3 != null)
+ base_type = (Expression) $3;
+
+ ArrayList enum_members = (ArrayList) $5;
+ if (enum_members.Count == 0)
+ Report.Error (30280, enum_location,
+ "Enum can not have empty member list");
+
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ MemberName full_name = MakeName (new MemberName ((string) $2));
+ Enum e = new Enum (current_namespace, current_container, base_type,
+ (int) current_modifiers, full_name,
+ (Attributes) current_attributes, enum_location);
+
+ foreach (VariableDeclaration ev in (ArrayList) $5) {
+ e.AddEnumMember (ev.identifier,
+ (Expression) ev.expression_or_array_initializer,
+ ev.Location, ev.OptAttributes, ev.DocComment);
+ }
+
+ string name = full_name.GetName ();
+ current_container.AddEnum (e);
+ RootContext.Tree.RecordDecl (name, e);
+
+ }
+ END ENUM logical_end_of_line
+ ;
+
+opt_enum_member_declarations
+ : /* empty */ { $$ = new ArrayList (4); }
+ | enum_member_declarations { $$ = $1; }
+ ;
+
+enum_member_declarations
+ : enum_member_declaration
+ {
+ ArrayList l = new ArrayList ();
+
+ l.Add ($1);
+ $$ = l;
+ }
+ | enum_member_declarations enum_member_declaration
+ {
+ ArrayList l = (ArrayList) $1;
+
+ l.Add ($2);
+
+ $$ = l;
+ }
+ ;
+
+enum_member_declaration
+ : opt_attributes identifier logical_end_of_line
+ {
+ $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
+ }
+ | opt_attributes identifier
+ {
+ $$ = lexer.Location;
+ }
+ ASSIGN expression logical_end_of_line
+ {
+ $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
+ }
+ ;
+
+// interface_property_declaration
+// : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line
+// {
+// Expression ftype = ($5 == null) ? (($3 == null) ?
+// TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+
+// current_local_parameters = (Parameters) $4;
+// if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+// get_parameters = current_local_parameters.Copy (lexer.Location);
+// set_parameters = current_local_parameters.Copy (lexer.Location);
+
+// Parameter implicit_value_parameter = new Parameter (
+// ftype, "Value", Parameter.Modifier.NONE, null);
+
+// set_parameters.AppendParameter (implicit_value_parameter);
+// }
+// else
+// {
+// get_parameters = Parameters.EmptyReadOnlyParameters;
+// set_parameters = new Parameters (null, null ,lexer.Location);
+
+// Parameter implicit_value_parameter = new Parameter (
+// ftype, "Value", Parameter.Modifier.NONE, null);
+
+// set_parameters.AppendParameter (implicit_value_parameter);
+// }
+// lexer.PropertyParsing = true;
+
+// Accessor get_block = new Accessor (null, null);
+// Accessor set_block = new Accessor (null, null);
+
+// Property prop = new Property ((Expression) ftype, (string) $2, current_modifiers,
+// get_block, set_block, current_attributes, lexer.Location,
+// null, get_parameters, set_parameters, null);
+
+// CheckDef (current_interface.AddProperty (prop), prop.Name, lexer.Location);
+
+// get_implicit_value_parameter_type = null;
+// set_implicit_value_parameter_type = null;
+// get_parameters = null;
+// set_parameters = null;
+// current_local_parameters = null;
+// }
+// ;
+
+// interface_event_declaration
+// : EVENT identifier AS type logical_end_of_line
+// {
+// VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
+
+// Event e = new Event ((Expression) $4, var.identifier,
+// null, current_modifiers,
+// current_attributes, lexer.Location);
+
+// CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
+
+// }
+// | EVENT identifier opt_params logical_end_of_line
+// {
+// string delName = (string) $2;
+// delName = delName + "EventHandler";
+// int delModifiers = (current_modifiers & ~Modifiers.ABSTRACT);
+// Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate
+// (current_container, TypeManager.system_void_expr,
+// (int) delModifiers, MakeName(delName), (Parameters) $3,
+// (Attributes) current_attributes, lexer.Location);
+
+// del.Namespace = current_namespace;
+// CheckDef (current_interface.AddDelegate (del), del.Name, lexer.Location);
+
+// Event e = new Event (DecomposeQI (delName, lexer.Location),
+// (string) $2,
+// null, current_modifiers,
+// current_attributes, lexer.Location);
+
+// CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
+// }
+// ;
+
+
+
+//FIXME: This apparently doesn't seem to emit the right code with property
+//having opt_property_parameters defined
+
+interface_property_declaration
+ : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line
+ {
+ get_implicit_value_parameter_type =
+ ($5 == null) ? (($3 == null) ?
+ TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+
+ current_local_parameters = (Parameters) $4;
+ if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+ get_parameters = current_local_parameters.Copy (lexer.Location);
+ set_parameters = current_local_parameters.Copy (lexer.Location);
+
+ Parameter implicit_value_parameter = new Parameter (
+ get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ }
+ else
+ {
+ get_parameters = Parameters.EmptyReadOnlyParameters;
+ set_parameters = new Parameters (null, null ,lexer.Location);
+
+ Parameter implicit_value_parameter = new Parameter (
+ get_implicit_value_parameter_type, "Value", Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ }
+ lexer.PropertyParsing = true;
+
+ Location loc = lexer.Location;
+ MemberName name = new MemberName ((string) $2);
+
+ Accessor get_block = new Accessor (null, 0, null, loc);
+ Accessor set_block = new Accessor (null, 0, null, loc);
+
+ Property prop = new Property (current_class, get_implicit_value_parameter_type,
+ (int) current_modifiers, true,
+ name, current_attributes,
+ get_parameters, get_block,
+ set_parameters, set_block, lexer.Location);
+
+ current_container.AddProperty (prop);
+
+ get_implicit_value_parameter_type = null;
+ set_implicit_value_parameter_type = null;
+ get_parameters = null;
+ set_parameters = null;
+ current_local_parameters = null;
+ }
+ ;
+
+
+// interface_event_declaration
+// : EVENT identifier AS type logical_end_of_line
+// {
+// VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
+
+// Event e = new Event ((Expression) $4, var.identifier,
+// null, current_modifiers,
+// current_attributes, lexer.Location);
+
+// CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
+
+// }
+// | EVENT identifier opt_params logical_end_of_line
+// {
+// string delName = (string) $2;
+// delName = delName + "EventHandler";
+// int delModifiers = (current_modifiers & ~Modifiers.ABSTRACT);
+// Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate
+// (current_container, TypeManager.system_void_expr,
+// (int) delModifiers, MakeName(delName), (Parameters) $3,
+// (Attributes) current_attributes, lexer.Location);
+
+// del.Namespace = current_namespace;
+// CheckDef (current_interface.AddDelegate (del), del.Name, lexer.Location);
+
+// Event e = new Event (DecomposeQI (delName, lexer.Location),
+// (string) $2,
+// null, current_modifiers,
+// current_attributes, lexer.Location);
+
+// CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
+// }
+// ;
+
+interface_declaration
+ : INTERFACE identifier logical_end_of_line
+ {
+ MemberName name = new MemberName ((string) $2);
+
+ current_class = new Interface (current_namespace, current_container,
+ name, (int) current_modifiers,
+ (Attributes) current_attributes, lexer.Location);
+
+ current_container = current_class;
+ RootContext.Tree.RecordDecl (name.GetName (true), current_class);
+
+ }
+ opt_interface_base
+ {
+ current_class.Bases = (ArrayList) $5;
+ current_class.Register ();
+ }
+ interface_body
+ {
+ $$ = current_class;
+
+ current_container = current_container.Parent;
+ current_class = current_container;
+ }
+ END INTERFACE logical_end_of_line
+ ;
+
+opt_interface_base
+ : /* empty */ { $$ = null; }
+ | interface_bases { $$ = $1; }
+ ;
+
+interface_bases
+ : interface_base
+ | interface_bases interface_base
+ {
+ ArrayList bases = (ArrayList) $1;
+ bases.AddRange ((ArrayList) $2);
+ $$ = bases;
+ }
+ ;
+
+interface_base
+ : INHERITS type_list logical_end_of_line { $$ = $2; }
+ ;
+
+interface_body
+ : opt_interface_member_declarations
+ ;
+
+opt_interface_member_declarations
+ : /* empty */
+ | interface_member_declarations
+ ;
+
+interface_member_declarations
+ : interface_member_declaration
+ | interface_member_declarations interface_member_declaration
+ ;
+
+interface_member_declaration
+ : opt_attributes opt_modifiers interface_member_declarator
+ ;
+
+interface_member_declarator
+ : interface_method_declaration
+ {
+ Method m = (Method) $1;
+
+ current_container.AddMethod (m);
+ }
+ | interface_property_declaration
+// | interface_event_declaration
+ ;
+
+interface_method_declaration
+ : SUB identifier opt_params logical_end_of_line
+ {
+ MemberName name = (MemberName) new MemberName ((string) $2);
+
+ GenericMethod generic = null;
+
+ $$ = new Method (current_class, generic, TypeManager.system_void_expr,
+ (int) current_modifiers, true, name, (Parameters) $3,
+ (Attributes) current_attributes, lexer.Location);
+ }
+
+ | FUNCTION identifier opt_type_character opt_params opt_type_with_ranks logical_end_of_line
+ {
+ MemberName name = new MemberName ((string) $2);
+ Expression return_type = ($5 == null) ?
+ (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 )
+ : (Expression) $5;
+
+ GenericMethod generic = null;
+ $$ = new Method (current_class, generic, return_type, (int) current_modifiers,
+ true, name, (Parameters) $4, (Attributes) current_attributes,
+ lexer.Location);
+ }
+ ;
+
+property_declaration
+ : non_abstract_propery_declaration
+// | abstract_propery_declaration
+ ;
+
+// abstract_propery_declaration
+// : MUSTOVERRIDE PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks logical_end_of_line
+// {
+// Expression ftype = ($6 == null) ? (($4 == null) ?
+// TypeManager.system_object_expr : (Expression) $4 ) : (Expression) $6;
+
+// if (current_container is Module)
+// Report.Error (30503, "Properties in a Module cannot be declared 'MustOverride'.");
+
+// if (current_container is Struct)
+// Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
+
+// current_modifiers |= Modifiers.ABSTRACT;
+
+// current_local_parameters = (Parameters) $5;
+// if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+// get_parameters = current_local_parameters.Copy (lexer.Location);
+// set_parameters = current_local_parameters.Copy (lexer.Location);
+
+// Parameter implicit_value_parameter = new Parameter (
+// ftype, "Value", Parameter.Modifier.NONE, null);
+
+// set_parameters.AppendParameter (implicit_value_parameter);
+// }
+// else
+// {
+// get_parameters = Parameters.EmptyReadOnlyParameters;
+// set_parameters = new Parameters (null, null ,lexer.Location);
+
+// Parameter implicit_value_parameter = new Parameter (
+// ftype, "Value", Parameter.Modifier.NONE, null);
+
+// set_parameters.AppendParameter (implicit_value_parameter);
+// }
+// lexer.PropertyParsing = true;
+
+// Accessor get_block = new Accessor (null, null);
+// Accessor set_block = new Accessor (null, null);
+
+// Property prop = new Property ((Expression) ftype, (string) $3, current_modifiers,
+// get_block, set_block, current_attributes, lexer.Location,
+// null, get_parameters, set_parameters, null);
+
+// if (!(current_container is Class))
+// Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
+
+// CheckDef (current_container.AddProperty (prop), prop.Name, lexer.Location);
+
+// get_implicit_value_parameter_type = null;
+// set_implicit_value_parameter_type = null;
+// get_parameters = null;
+// set_parameters = null;
+// current_local_parameters = null;
+// }
+// ;
+
+non_abstract_propery_declaration
+ : PROPERTY identifier opt_type_character opt_property_parameters opt_type_with_ranks opt_implement_clause logical_end_of_line
+ {
+ get_implicit_value_parameter_type =
+ ($5 == null) ? (($3 == null) ?
+ TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+ get_implicit_value_parameter_name = (string) $2;
+
+ current_local_parameters = (Parameters) $4;
+ if (current_local_parameters != Parameters.EmptyReadOnlyParameters) {
+ get_parameters = current_local_parameters.Copy (lexer.Location);
+ set_parameters = current_local_parameters.Copy (lexer.Location);
+ }
+ else
+ {
+ get_parameters = Parameters.EmptyReadOnlyParameters;
+ set_parameters = new Parameters (null, null ,lexer.Location);
+ }
+ lexer.PropertyParsing = true;
+
+ $$ = lexer.Location;
+ }
+ accessor_declarations
+ END PROPERTY logical_end_of_line
+ {
+ lexer.PropertyParsing = false;
+
+ Property prop;
+ Pair pair = (Pair) $9;
+
+ Accessor get_block = (Accessor) pair.First;
+ Accessor set_block = (Accessor) pair.Second;
+
+ Location loc = lexer.Location;
+ MemberName name = new MemberName ((string) $2);
+
+ // FIXME: Implements Clause needs to be taken care of.
+
+ if ((current_container is Struct) && (current_modifiers == 0))
+ current_modifiers = Modifiers.PUBLIC;
+
+
+ prop = new Property (current_class, get_implicit_value_parameter_type,
+ (int) current_modifiers, false,
+ name, (Attributes) current_attributes,
+ get_parameters, get_block,
+ set_parameters, set_block, lexer.Location);
+
+ current_container.AddProperty (prop);
+ get_implicit_value_parameter_type = null;
+ set_implicit_value_parameter_type = null;
+ get_parameters = null;
+ set_parameters = null;
+ current_local_parameters = null;
+ }
+ ;
+
+opt_property_parameters
+ : /* empty */
+ {
+ $$ = Parameters.EmptyReadOnlyParameters;
+ }
+ | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_implement_clause
+ : /* empty */
+ {
+ $$ = null;
+ }
+ | IMPLEMENTS implement_clause_list
+ {
+ $$ = $2;
+ }
+ ;
+
+implement_clause_list
+ : qualified_identifier
+ {
+ MemberName mname = (MemberName) $1;
+ ArrayList impl_list = new ArrayList ();
+ impl_list.Add (mname.GetTypeExpression (lexer.Location));
+ $$ = impl_list;
+ }
+ | implement_clause_list COMMA qualified_identifier
+ {
+ MemberName mname = (MemberName) $3;
+ ArrayList impl_list = (ArrayList) $1;
+ impl_list.Add (mname.GetTypeExpression (lexer.Location));
+ $$ = impl_list;
+ }
+ ;
+
+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 logical_end_of_line
+ {
+ if ((current_modifiers & Modifiers.WRITEONLY) != 0)
+ Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor");
+
+ current_local_parameters = get_parameters;
+
+ lexer.PropertyParsing = false;
+
+ }
+ begin_block
+ {
+ ArrayList retval = new ArrayList ();
+ retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
+ declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);
+ }
+ opt_statement_list
+ end_block
+ END GET logical_end_of_line
+ {
+ $$ = new Accessor ((ToplevelBlock) $8, (int) current_modifiers,
+ (Attributes) $1, lexer.Location);
+
+ current_local_parameters = null;
+ lexer.PropertyParsing = true;
+ }
+ ;
+
+
+
+set_accessor_declaration
+ : opt_attributes SET opt_set_parameter logical_end_of_line
+ {
+ if ((current_modifiers & Modifiers.READONLY) != 0)
+ Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor");
+
+ Parameter implicit_value_parameter = new Parameter (
+ set_implicit_value_parameter_type,
+ set_implicit_value_parameter_name,
+ Parameter.Modifier.NONE, null);
+
+ set_parameters.AppendParameter (implicit_value_parameter);
+ current_local_parameters = set_parameters;
+
+ lexer.PropertyParsing = false;
+ }
+ begin_block
+ opt_statement_list
+ end_block
+ END SET logical_end_of_line
+ {
+ $$ = new Accessor ((ToplevelBlock) $8, (int) current_modifiers,
+ (Attributes) $1, lexer.Location);
+ current_local_parameters = null;
+ lexer.PropertyParsing = true;
+ }
+ ;
+
+opt_set_parameter
+ : /* empty */
+ {
+ set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; // TypeManager.system_object_expr;
+ set_implicit_value_parameter_name = "Value";
+ }
+ |OPEN_PARENS CLOSE_PARENS
+ {
+ set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type;
+ set_implicit_value_parameter_name = "Value";
+ }
+ | OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_with_ranks CLOSE_PARENS
+ {
+ Parameter.Modifier pm = (Parameter.Modifier)$2;
+ if ((pm | Parameter.Modifier.VAL) != 0)
+ Report.Error (31065,
+ lexer.Location,
+ "Set cannot have a paremeter modifier other than 'ByVal'");
+
+ set_implicit_value_parameter_type = (Expression) $4;
+
+ if (set_implicit_value_parameter_type.ToString () != get_implicit_value_parameter_type.ToString ())
+ Report.Error (31064,
+ lexer.Location,
+ "Set value parameter type can not be different from property type");
+
+ if ($2 != null)
+ set_implicit_value_parameter_name = (string) $3;
+ else
+ set_implicit_value_parameter_name = "Value";
+ }
+ ;
+
+field_declaration
+ : opt_dim_stmt
+ variable_declarators logical_end_of_line
+ {
+ int mod = (int) current_modifiers;
+
+ VariableDeclaration.FixupTypes ((ArrayList) $2);
+ VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
+
+// if (current_container is Module)
+// mod = mod | Modifiers.STATIC;
+
+ // Structure members are Public by default
+ if ((current_container is Struct) && (mod == 0))
+ mod = Modifiers.PUBLIC;
+
+ if ((mod & Modifiers.Accessibility) == 0)
+ mod |= Modifiers.PRIVATE;
+
+ foreach (VariableDeclaration var in (ArrayList) $2){
+ Location l = var.Location;
+ Field field = new Field (current_class, var.type, mod,
+ var.identifier, var.expression_or_array_initializer,
+ (Attributes) null, l);
+
+ current_container.AddField (field);
+ }
+ }
+ ;
+
+
+// withevents_declaration
+// : opt_dim_stmt WITHEVENTS variable_declarators logical_end_of_line
+// {
+// // Module members are static by default, but delegates *can't* be declared static
+// // so we must fix it, if mbas was the one actually responsible for this
+// // instead of triggering an error.
+// if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+// current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+// /* WithEvents Fields must be resolved into properties
+// with a bit of magic behind the scenes */
+
+// VariableDeclaration.FixupTypes ((ArrayList) $3);
+
+// foreach (VariableDeclaration var in (ArrayList) $3) {
+// // 1 - We create a private field
+// Location l = var.Location;
+// Property prop;
+// if ((current_modifiers & Modifiers.STATIC) > 0)
+// Report.Error (30234, l, "'Static' is not valid on a WithEvents declaration.");
+
+// Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier,
+// var.expression_or_array_initializer,
+// (Attributes) null, l);
+
+// CheckDef (current_container.AddField (field), field.Name, l);
+
+// // 2 - Public property
+
+// prop = BuildSimpleProperty (var.type, (string) var.identifier,
+// field, (int) current_modifiers,
+// (Attributes) current_attributes, l);
+
+// CheckDef (current_container.AddProperty (prop), prop.Name, l);
+// }
+// }
+// ;
+
+opt_dim_stmt
+ : /* empty */
+ | DIM
+ ;
+
+delegate_declaration
+ : DELEGATE SUB
+ identifier OPEN_PARENS
+ opt_formal_parameter_list
+ CLOSE_PARENS
+ logical_end_of_line
+ {
+ Location l = lexer.Location;
+ MemberName name = MakeName (new MemberName ((string) $3));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ Delegate del = new Delegate (current_namespace, current_container, TypeManager.system_void_expr,
+ current_modifiers, name, (Parameters) $5, current_attributes, l);
+
+ current_container.AddDelegate (del);
+ RootContext.Tree.RecordDecl (name.GetName (true), del);
+ }
+
+ | DELEGATE FUNCTION
+ identifier OPEN_PARENS
+ opt_formal_parameter_list
+ CLOSE_PARENS opt_type_with_ranks logical_end_of_line
+ {
+ Location l = lexer.Location;
+ MemberName name = MakeName (new MemberName ((string) $3));
+
+ if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+ current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+
+ Expression rettype = ($7 == null) ? TypeManager.system_object_expr : (Expression) $7;
+ Delegate del = new Delegate (current_namespace, current_container, rettype,
+ current_modifiers, name, (Parameters) $5, current_attributes, l);
+
+ current_container.AddDelegate (del);
+ RootContext.Tree.RecordDecl (name.GetName (true), del);
+ }
+
+ ;
+
+
+opt_evt_handler
+ : /* empty */ { $$ = null; }
+// | HANDLES evt_handler { $$ = $2; }
+ ;
+
+// evt_handler
+// : qualified_identifier
+// {
+// $$ = (Expression) DecomposeQI ((string)$1, lexer.Location);
+// }
+// | base_access
+// {
+// $$ = $1;
+// }
+// | ME DOT qualified_identifier
+// {
+// $$ = (Expression) DecomposeQI ((string)$3, lexer.Location);
+// }
+// /*| MYBASE DOT qualified_identifier
+// {
+// // FIXME: this is blatantly wrong and crash-prone
+// $$ = (Expression) DecomposeQI ("MyBase." + (string)$4, lexer.Location);
+// }*/
+// ;
+
+
+constructor_declaration
+ : SUB NEW opt_params logical_end_of_line
+ {
+ current_local_parameters = (Parameters) $3;
+ $$ = new Constructor (current_class, current_container.Basename, 0, (Parameters) $3,
+ (ConstructorInitializer) null, lexer.Location);
+ }
+ begin_block
+ opt_statement_list
+ end_block
+ {
+ Constructor c = (Constructor) $5;
+ c.Block = (ToplevelBlock) $8;
+ c.ModFlags = (int) current_modifiers;
+ c.OptAttributes = current_attributes;
+
+ // FIXME: Some more error checking from mcs needs to be merged here ???
+
+ c.Initializer = CheckConstructorInitializer (ref c.Block.statements);
+
+ current_container.AddConstructor(c);
+ current_local_parameters = null;
+ }
+ END SUB logical_end_of_line
+ ;
+
+opt_formal_parameter_list
+ : /* empty */
+ {
+ $$ = Parameters.EmptyReadOnlyParameters;
+ }
+ | formal_parameter_list
+ {
+ $$ = $1;
+ }
+ ;
+
+formal_parameter_list
+ : parameters
+ {
+ ArrayList pars_list = (ArrayList) $1;
+ Parameter [] pars = null;
+ Parameter array_parameter = null;
+ int non_array_count = pars_list.Count;
+ if (pars_list.Count > 0 && (((Parameter) pars_list [pars_list.Count - 1]).ModFlags & Parameter.Modifier.PARAMS) != 0) {
+ array_parameter = (Parameter) pars_list [pars_list.Count - 1];
+ non_array_count = pars_list.Count - 1;
+ }
+ foreach (Parameter par in pars_list)
+ if (par != array_parameter && (par.ModFlags & Parameter.Modifier.PARAMS) != 0) {
+ Report.Error (30192, lexer.Location, "ParamArray parameters must be last");
+ non_array_count = 0;
+ array_parameter = null;
+ break;
+ }
+ if (non_array_count > 0) {
+ pars = new Parameter [non_array_count];
+ pars_list.CopyTo (0, pars, 0, non_array_count);
+ }
+ $$ = new Parameters (pars, array_parameter, lexer.Location);
+ }
+ ;
+
+parameters
+ : parameter
+ {
+ ArrayList pars = new ArrayList ();
+
+ pars.Add ($1);
+ $$ = pars;
+ }
+ | parameters COMMA parameter
+ {
+ ArrayList pars = (ArrayList) $1;
+
+ pars.Add ($3);
+ $$ = $1;
+ }
+ ;
+
+parameter
+ : opt_attributes
+ opt_parameter_modifier
+ identifier opt_type_character opt_rank_specifiers opt_type_with_ranks opt_variable_initializer
+ {
+ Parameter.Modifier pm = (Parameter.Modifier)$2;
+ bool opt_parm = ((pm & Parameter.Modifier.OPTIONAL) != 0);
+ Expression ptype;
+
+ if (opt_parm && ($7 == null))
+ Report.Error (30812, lexer.Location, "Optional parameters must have a default value");
+
+ if (!opt_parm && ($7 != null))
+ Report.Error (32024, lexer.Location, "Non-Optional parameters should not have a default value");
+
+ if ((pm & Parameter.Modifier.PARAMS) != 0) {
+ if ((pm & ~Parameter.Modifier.PARAMS) != 0)
+ Report.Error (30667, lexer.Location, "ParamArray parameters must be ByVal");
+ }
+
+ if ((pm & Parameter.Modifier.REF) !=0)
+ pm |= Parameter.Modifier.ISBYREF;
+
+ if ($4 != null && $6 != null && $4 != $6)
+ Report.Error (30302, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
+
+ ptype = (Expression)(($6 == null) ? (($4 == null) ? TypeManager.system_object_expr : $4) : $6);
+ if ($5 != null) {
+ string t = ptype.ToString ();
+ if (t.IndexOf('[') >= 0)
+ Report.Error (31087, lexer.Location, "Array types specified in too many places");
+ else
+ ptype = DecomposeQI (t + VariableDeclaration.BuildRanks ((ArrayList) $5, true, lexer.Location), lexer.Location);
+ }
+ if ((pm & Parameter.Modifier.PARAMS) != 0 && ptype.ToString ().IndexOf('[') < 0)
+ Report.Error (30050, lexer.Location, "ParamArray parameters must be an array type");
+ $$ = new Parameter (ptype, (string) $3, pm,
+ (Attributes) $1, (Expression) $7, opt_parm);
+ }
+ ;
+
+opt_parameter_modifier
+ : /* empty */ { $$ = Parameter.Modifier.VAL; }
+ | parameter_modifiers { $$ = $1; }
+ ;
+
+parameter_modifiers
+ : parameter_modifiers parameter_modifier { $$ = (Parameter.Modifier)$1 | (Parameter.Modifier)$2; }
+ | parameter_modifier { $$ = $1; }
+ ;
+
+parameter_modifier
+ : BYREF { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
+ | BYVAL { $$ = Parameter.Modifier.VAL; }
+ | OPTIONAL { $$ = Parameter.Modifier.OPTIONAL; }
+ | PARAM_ARRAY { $$ = Parameter.Modifier.PARAMS; }
+ ;
+
+opt_statement_list
+ : /* empty */
+ | statement_list end_of_stmt
+ ;
+
+statement_list
+ : statement
+ | statement_list end_of_stmt statement
+ ;
+
+block
+ : begin_block
+ opt_statement_list
+ end_block { $$ = $3; }
+ ;
+
+begin_block
+ : /* empty */
+ {
+ if (current_block == null){
+ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location);
+ top_current_block = current_block;
+ } else {
+ current_block = new Block (current_block, current_local_parameters,
+ lexer.Location, Location.Null);
+ }
+ }
+ ;
+
+
+end_block
+ : /* empty */
+ {
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ $$ = current_block;
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+ if (current_block == null)
+ top_current_block = null;
+ }
+ ;
+
+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
+ | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF expression
+ {
+ Location loc = lexer.Location;
+
+ ExpressionStatement expr = new CompoundAssign (Binary.Operator.Addition,
+ (Expression) $2, (Expression) $5, loc);
+
+ Statement stmt = new StatementExpression (expr, loc);
+
+ current_block.AddStatement (stmt);
+
+ }
+
+ | REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF expression
+ {
+ Location loc = lexer.Location;
+
+ ExpressionStatement expr = new CompoundAssign (Binary.Operator.Subtraction,
+ (Expression) $2, (Expression) $5, loc);
+
+ Statement stmt = new StatementExpression (expr, loc);
+
+ current_block.AddStatement (stmt);
+
+ }
+ | RAISEEVENT identifier opt_raise_event_args //OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ Location loc = lexer.Location;
+ MemberName mname = new MemberName ((string) $2);
+ Expression expr = mname.GetTypeExpression (loc);
+
+ Invocation inv_expr = new Invocation (expr, (ArrayList) $3, loc);
+ Statement stmt = new StatementExpression (inv_expr, loc);
+ current_block.AddStatement (stmt);
+ }
+// /* | array_handling_statement */
+// /* | empty_statement */
+// | with_statement
+// {
+// Statement s = (Statement) $1;
+
+// current_block.AddStatement ((Statement) $1);
+// }
+ ;
+
+
+opt_raise_event_args
+ : /* empty */ { $$ = null; }
+ | OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ $$ = $2;
+ }
+ ;
+
+// label_name
+// : identifier
+// | LITERAL_INTEGER
+// {
+// $$ = $1.ToString();
+// }
+// ;
+
+// labeled_statement
+// : label_name 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);
+// }
+// | label_name 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
+// ;
+
+embedded_statement
+ : expression_statement
+ | selection_statement
+// | iteration_statement
+ | try_statement
+ | synclock_statement
+ | jump_statement
+// | array_handling_statement
+ ;
+
+// /*
+// empty_statement
+// : end_of_stmt
+// {
+// $$ = new EmptyStatement ();
+// }
+// ;
+// */
+
+// with_statement
+// : WITH expression end_of_stmt /* was : WITH qualified_identifier end_of_stmt */
+// {
+// // was : Expression e = DecomposeQI ((string) $2, lexer.Location);
+// Expression e = (Expression) $2;
+// with_stack.Push(e);
+// start_block();
+// }
+// opt_statement_list
+// END WITH
+// {
+// Block b = end_block();
+// with_stack.Pop();
+// $$ = b;
+// }
+// ;
+
+
+// array_handling_statement
+// : redim_statement
+// | erase_statement
+// ;
+
+// redim_statement
+// : REDIM opt_preserve redim_clauses
+// {
+// ArrayList list = (ArrayList) $3;
+// ReDim r = new ReDim (list, (bool) $2, lexer.Location);
+// $$ = r;
+
+// }
+// ;
+
+// opt_preserve
+// : /* empty */ { $$ = false; }
+// | PRESERVE { $$ = true; }
+// ;
+
+// redim_clauses
+// : redim_clause
+// {
+// ArrayList clauses = new ArrayList ();
+
+// clauses.Add ($1);
+// $$ = clauses;
+// }
+// | redim_clauses COMMA redim_clause
+// {
+// ArrayList clauses = (ArrayList) ($1);
+// clauses.Add ($2);
+
+// $$ = clauses;
+// }
+// ;
+
+// redim_clause
+// : invocation_expression
+// {
+// Invocation i = (Invocation) $1;
+// RedimClause rc = new RedimClause (i.expr, i.Arguments);
+// $$ = rc;
+// }
+// ;
+
+// erase_statement
+// : ERASE erase_clauses
+// {
+// ArrayList list = (ArrayList) $2;
+// foreach(Expression e in list)
+// {
+// Erase r = new Erase (e, lexer.Location);
+// $$ = r;
+// }
+// }
+// ;
+
+// erase_clauses
+// : erase_clause
+// {
+// ArrayList clauses = new ArrayList ();
+
+// clauses.Add ($1);
+// $$ = clauses;
+// }
+// | erase_clauses COMMA erase_clause
+// {
+// ArrayList clauses = (ArrayList) ($1);
+// clauses.Add ($2);
+
+// $$ = clauses;
+// }
+// ;
+
+// erase_clause
+// : primary_expression
+// ;
+
+jump_statement
+ : /*break_statement
+ | continue_statement
+ | */return_statement
+ | goto_statement
+ | throw_statement
+// | exit_statement
+// | yield_statement
+ ;
+
+goto_statement
+ : GOTO label_name
+ {
+ $$ = new Goto (current_block, (string) $2, lexer.Location);
+ }
+ ;
+
+throw_statement
+ : THROW opt_expression
+ {
+ $$ = new Throw ((Expression) $2, lexer.Location);
+ }
+ ;
+
+// exit_statement
+// : EXIT exit_type
+// {
+// $$ = new Exit ((ExitType)$2, lexer.Location);
+// }
+// ;
+
+// exit_type
+// : DO { $$ = ExitType.DO; }
+// | FOR { $$ = ExitType.FOR; }
+// | WHILE { $$ = ExitType.WHILE; }
+// | SELECT { $$ = ExitType.SELECT; }
+// | SUB { $$ = ExitType.SUB; }
+// | FUNCTION { $$ = ExitType.FUNCTION; }
+// | PROPERTY { $$ = ExitType.PROPERTY; }
+// | TRY { $$ = ExitType.TRY; }
+// ;
+
+return_statement
+ : RETURN opt_expression
+ {
+ $$ = new Return ((Expression) $2, lexer.Location);
+ }
+ ;
+
+// iteration_statement
+// : while_statement
+// | do_statement
+// | for_statement
+// | foreach_statement
+// ;
+
+// foreach_statement
+// : FOR EACH identifier opt_type_spec IN
+// {
+// oob_stack.Push (lexer.Location);
+// }
+// expression end_of_stmt
+// {
+// Location l = lexer.Location;
+// LocalVariableReference v = null;
+// VariableInfo vi;
+
+// if ($4 != null)
+// {
+// start_block();
+// VariableDeclaration decl = new VariableDeclaration ((string) $3,
+// (Expression) $4, null, lexer.Location, null);
+
+// vi = current_block.AddVariable (
+// (Expression) $4, decl.identifier, current_local_parameters, decl.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 ((Expression) $4, "", init, decl.Location);
+// }
+
+// v = new LocalVariableReference (current_block, decl.identifier, l);
+
+// if (expr != null)
+// {
+// Assign a = new Assign (v, expr, decl.Location);
+// current_block.AddStatement (new StatementExpression (a, lexer.Location));
+// }
+// }
+// else
+// {
+// vi = current_block.GetVariableInfo ((string) $3);
+
+// if (vi != null) {
+// // Get a reference to this variable.
+// v = new LocalVariableReference (current_block, (string) $3, l, vi, false);
+// }
+// else
+// Report.Error (451, "Name '" + (string) $3 + "' is not declared.");
+// }
+
+// oob_stack.Push (v);
+// start_block();
+// }
+// opt_statement_list
+// NEXT opt_identifier
+// {
+// LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
+// Block foreach_block = end_block();
+// Location l = (Location) oob_stack.Pop ();
+
+// Foreach f = null;
+// if (v != null)
+// f = new Foreach (null, v, (Expression) $7, foreach_block, l);
+
+// if ($4 != null)
+// {
+// current_block.AddStatement (f);
+// $$ = end_block ();
+// }
+// else
+// $$ = f;
+// }
+// ;
+
+// yield_statement
+// : YIELD expression
+// {
+// if (!UseExtendedSyntax)
+// {
+// ReportError9998();
+// $$ = null;
+// }
+// /* else
+// 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 STOP
+// {
+// if (!UseExtendedSyntax)
+// {
+// ReportError9998();
+// $$ = null;
+// }
+// /* else
+// 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);
+// } */
+// }
+// ;
+
+synclock_statement
+ : SYNCLOCK expression end_of_stmt
+ block
+ END SYNCLOCK
+ {
+ $$ = new Lock ((Expression) $2, (Statement) $4, lexer.Location);
+ }
+ ;
+
+try_statement
+ : try_catch
+ | try_catch_finally
+ ;
+
+
+try_catch
+ : TRY end_of_stmt block opt_catch_clauses END TRY
+ {
+ Catch g = null;
+
+ ArrayList c = (ArrayList)$4;
+ for (int i = 0; i < c.Count; ++i) {
+ Catch cc = (Catch) c [i];
+ if (cc.IsGeneral) {
+ if (i != c.Count - 1)
+ Report.Error (1017, cc.loc, "Empty catch block must be the last in a series of catch blocks");
+ g = cc;
+ c.RemoveAt (i);
+ i--;
+ }
+ }
+
+ // Now s contains the list of specific catch clauses
+ // and g contains the general one.
+
+ $$ = new Try ((Block) $3, c, g, null, ((Block) $3).loc);
+ }
+ ;
+
+try_catch_finally
+ : TRY end_of_stmt
+ block
+ opt_catch_clauses
+ FINALLY end_of_stmt
+ block
+ END TRY
+ {
+ Catch g = null;
+ ArrayList s = new ArrayList (4);
+ ArrayList catch_list = (ArrayList) $4;
+
+ if (catch_list != null){
+ foreach (Catch cc in catch_list) {
+ if (cc.IsGeneral)
+ g = cc;
+ else
+ s.Add (cc);
+ }
+ }
+
+ $$ = new Try ((Block) $3, s, g, (Block) $7, ((Block) $3).loc);
+ }
+ ;
+
+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
+ ;
+
+// opt_when
+// : /* empty */ { $$ = null; }
+// | WHEN boolean_expression { $$ = $2; }
+// ;
+
+
+catch_clause
+// : CATCH opt_catch_args opt_when end_of_stmt
+ : CATCH opt_catch_args end_of_stmt
+ {
+ // FIXME: opt_when needs to be hnadled
+ 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, type, 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) $5, ((Block) $5).loc);
+ }
+ ;
+
+opt_catch_args
+ : /* empty */ { $$ = null; }
+ | catch_args
+ ;
+
+catch_args
+ : identifier AS type
+ {
+ $$ = new DictionaryEntry ($3, $1);
+ }
+ ;
+
+
+// do_statement
+// : DO opt_do_construct end_of_stmt
+// {
+// start_block();
+// oob_stack.Push (lexer.Location);
+// }
+// opt_statement_list
+// LOOP opt_do_construct
+// {
+// Expression t_before = (Expression) $2;
+// Expression t_after = (Expression) $7;
+// Expression t;
+
+// if ((t_before != null) && (t_after != null))
+// Report.Error (30238, "'Loop' cannot have a condition if matching 'Do' has one.");
+
+// if ((t_before == null) && (t_after == null))
+// t = new BoolLiteral (true);
+// else
+// t = (t_before != null) ? t_before : t_after;
+
+// DoOptions test_type = (t_before != null) ? DoOptions.TEST_BEFORE : DoOptions.TEST_AFTER;
+
+// if (((do_type == DoOptions.WHILE) && (test_type == DoOptions.TEST_BEFORE)) ||
+// ((do_type == DoOptions.UNTIL) && (test_type == DoOptions.TEST_AFTER)))
+// t = new Unary (Unary.Operator.LogicalNot, (Expression) t, lexer.Location);
+
+// $$ = new Do ((Statement) end_block(), (Expression) t, test_type, lexer.Location);
+// }
+// ;
+
+// opt_do_construct
+// : /* empty */ { $$ = null; }
+// | while_or_until boolean_expression
+// {
+// do_type = (DoOptions)$1;
+// $$ = (Expression) $2;
+// }
+// ;
+
+// while_or_until
+// : WHILE { $$ = DoOptions.WHILE; }
+// | UNTIL { $$ = DoOptions.UNTIL; }
+// ;
+
+while_statement
+ : WHILE
+ {
+ oob_stack.Push (lexer.Location);
+ }
+ boolean_expression end_of_stmt
+ begin_block
+ opt_statement_list
+ end_block
+ END WHILE
+ {
+ Location l = (Location) oob_stack.Pop ();
+ $$ = new While ((Expression) $3, (Statement) $7, l);
+ }
+ ;
+
+// for_statement
+// : FOR identifier opt_type_spec ASSIGN expression TO expression opt_step end_of_stmt
+// {
+// if ($3 != null)
+// {
+// start_block();
+// ArrayList VarDeclaration = new ArrayList ();
+// VarDeclaration.Add (new VariableDeclaration ((string) $2,
+// (Expression) $3, null, lexer.Location, null));
+
+// DictionaryEntry de = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), VarDeclaration);
+// Block b = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+// current_block = b;
+// }
+// oob_stack.Push (lexer.Location);
+// start_block();
+// }
+// opt_statement_list
+// NEXT opt_identifier
+// {
+// Block inner_statement = end_block();
+// Location l = (Location) oob_stack.Pop ();
+// Expression for_var = (Expression) DecomposeQI ((string)$2, l);
+
+// Expression assign_expr = new Assign (for_var, (Expression) $5, l);
+// Expression test_expr = new Binary (Binary.Operator.LessThanOrEqual,
+// for_var, (Expression) $7, l);
+// Expression step_expr = new Assign (for_var, (Expression) new Binary (Binary.Operator.Addition,
+// for_var, (Expression) $8, l), l);
+
+// Statement assign_stmt = new StatementExpression ((ExpressionStatement) assign_expr, l);
+// Statement step_stmt = new StatementExpression ((ExpressionStatement) step_expr, l);
+
+// For f = new For (assign_stmt, test_expr, step_stmt, inner_statement, l);
+// if ($3 != null)
+// {
+// current_block.AddStatement (f);
+// $$ = end_block();
+// }
+// else
+// $$ = f;
+// }
+// ;
+
+// opt_step
+// : /* empty */ { $$ = new IntLiteral ((Int32) 1); }
+// | STEP expression { $$ = $2; }
+// ;
+
+selection_statement
+ : if_statement
+// | select_statement
+ ;
+
+// if_statement
+// : IF boolean_expression opt_then end_of_stmt
+// if_statement_rest
+// // | IF boolean_expression THEN block opt_else_pre_embedded_statement
+// // | IF boolean_expression else_pre_embedded_statement
+// ;
+
+
+// FXIME: The rule for LineIfThenStatement needs to be still enabled
+// FIXME: The lexer.Location that is calculated may have to replaced with the most correct one
+
+if_statement
+ : IF boolean_expression opt_then end_of_stmt
+ block
+ END IF
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, l);
+
+ if (RootContext.WarningLevel >= 3){
+ if ($5 == EmptyStatement.Value)
+ Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
+ }
+
+ }
+
+ | IF boolean_expression opt_then end_of_stmt
+ block
+ ELSE end_of_stmt
+ block
+ END IF
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, (Statement) $8, l);
+ }
+
+ | IF boolean_expression opt_then end_of_stmt
+ block
+ else_if_statement_rest
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, (Statement) $6, l);
+ }
+ ;
+
+else_if_statement_rest
+ : ELSEIF boolean_expression opt_then end_of_stmt
+ block
+ END IF
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, l);
+
+ if (RootContext.WarningLevel >= 3){
+ if ($5 == EmptyStatement.Value)
+ Report.Warning (642, lexer.Location, "Possible mistaken empty statement");
+ }
+
+ }
+
+ | ELSEIF boolean_expression opt_then end_of_stmt
+ block
+ ELSE end_of_stmt
+ block
+ END IF
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, (Statement) $8, l);
+ }
+
+ | ELSEIF boolean_expression opt_then end_of_stmt
+ block
+ else_if_statement_rest
+ {
+ oob_stack.Push (lexer.Location);
+ Location l = (Location) oob_stack.Pop ();
+
+ $$ = new If ((Expression) $2, (Statement) $5, (Statement) $6, l);
+ }
+ ;
+
+
+// opt_else_pre_embedded_statement
+// : /* empty */
+// | else_pre_embedded_statement
+// ;
+
+// else_pre_embedded_statement
+// : ELSE
+// {
+// Block bl = end_block();
+// tmp_blocks.Push(bl);
+
+// start_block();
+// }
+// | ELSE embedded_statement
+// {
+// Block bl = end_block();
+// tmp_blocks.Push(bl);
+
+// start_block();
+// Statement s = (Statement) $2;
+// current_block.AddStatement ((Statement) $2);
+// }
+// ;
+
+
+opt_then
+ : /* empty */
+ | THEN
+ ;
+
+
+// select_statement
+// : SELECT opt_case expression end_of_stmt
+// {
+// oob_stack.Push (lexer.Location);
+// switch_stack.Push (current_block);
+// }
+// opt_case_sections
+// END SELECT
+// {
+// $$ = new Switch ((Expression) $3, (ArrayList) $6, (Location) oob_stack.Pop ());
+// current_block = (Block) switch_stack.Pop ();
+// }
+// ;
+
+// opt_case_sections
+// : /* empty */ { $$ = null; }
+// | case_sections { $$ = $1; }
+// ;
+
+// case_sections
+// : case_sections case_section
+// {
+// ArrayList sections = (ArrayList) $1;
+
+// sections.Add ($2);
+// $$ = sections;
+// }
+// | case_section
+// {
+// ArrayList sections = new ArrayList (4);
+
+// sections.Add ($1);
+// $$ = sections;
+// }
+// ;
+
+// ends
+// : end_of_stmt
+// | ends end_of_stmt
+// ;
+
+
+// case_section
+// : CASE case_clauses ends
+// {
+// start_block();
+// }
+// opt_statement_list
+// {
+// //Block topmost = current_block;
+// Block topmost = end_block();
+
+// while (topmost.Implicit)
+// topmost = topmost.Parent;
+
+// // FIXME: This is a horrible hack which MUST go
+// topmost.statements.Add (new Break (lexer.Location));
+// $$ = new SwitchSection ((ArrayList) $2, topmost);
+// }
+// | CASE ELSE ends
+// /* FIXME: we should somehow flag an error
+// (BC30321 'Case' cannot follow a 'Case Else'
+// in the same 'Select' statement.)
+// if Case Else is not the last of the Case clauses
+// */
+// {
+// start_block();
+// }
+// opt_statement_list
+// {
+// //Block topmost = current_block;
+// Block topmost = end_block();
+
+// while (topmost.Implicit)
+// topmost = topmost.Parent;
+
+// // FIXME: This is a horrible hack which MUST go
+// topmost.statements.Add (new Break (lexer.Location));
+
+// ArrayList a = new ArrayList();
+// a.Add (new SwitchLabel (null, lexer.Location));
+// $$ = new SwitchSection ((ArrayList) a, topmost);
+// }
+// ;
+
+
+case_clauses
+ : case_clause
+ {
+ ArrayList labels = new ArrayList ();
+
+ labels.Add ($1);
+ $$ = labels;
+ }
+ | case_clauses COMMA case_clause
+ {
+ ArrayList labels = (ArrayList) ($1);
+ labels.Add ($2);
+
+ $$ = labels;
+ }
+ ;
+
+case_clause
+ : opt_is comparison_operator expression
+ | expression
+ {
+ $$ = new SwitchLabel ((Expression) $1, lexer.Location);
+ }
+ ;
+
+opt_is
+ : /* empty */
+ | IS
+ ;
+
+comparison_operator
+ : OP_LT
+ | OP_GT
+ | OP_LE
+ | OP_NE
+ /*| OP_EQ */
+ ;
+
+opt_case
+ : /* empty */
+ | CASE
+ ;
+
+expression_statement
+ : statement_expression
+ {
+ $$ = $1;
+ }
+ ;
+
+
+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); }
+ ;
+
+object_creation_expression
+ : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
+ }
+ | NEW type
+ {
+ $$ = new New ((Expression) $2, new ArrayList(), lexer.Location);
+ }
+ ;
+
+
+// array_creation_expression
+// : object_creation_expression opt_rank_specifiers array_initializer
+// {
+// New n = (New) $1;
+// ArrayList dims = new ArrayList();
+
+// if (n.Arguments != null) {
+// foreach (Argument a in n.Arguments) {
+// dims.Add (a.Expr);
+// }
+// }
+
+// Expression atype = n.RequestedType;
+
+// if ($2 != null)
+// atype = DecomposeQI (atype.ToString () + VariableDeclaration.BuildRanks ((ArrayList)$2, true, lexer.Location), lexer.Location);
+
+// ArrayList init = (ArrayList) $3;
+// if (init.Count == 0)
+// init = null;
+
+// if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
+// VariableDeclaration.VBFixIndexList (ref dims);
+// $$ = new ArrayCreation (atype, dims, "", init, lexer.Location);
+// }
+// else
+// {
+// string rank = VariableDeclaration.BuildRank (dims);
+// $$ = new ArrayCreation (atype, rank, (ArrayList) $3, lexer.Location);
+// }
+// //Console.WriteLine ("Creating a new array of type " + (atype.ToString()) + " with rank '" + dims + "'");
+// }
+// ;
+
+new_expression
+ : object_creation_expression
+// | array_creation_expression
+ ;
+
+declaration_statement
+ : local_variable_declaration
+ {
+ if ($1 != null){
+ DictionaryEntry de = (DictionaryEntry) $1;
+
+ $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+ }
+ }
+ | local_constant_declaration
+ {
+ if ($1 != null){
+ DictionaryEntry de = (DictionaryEntry) $1;
+
+ $$ = declare_local_constant ((Expression) de.Key, (ArrayList) de.Value);
+ }
+ }
+ ;
+
+local_variable_declaration
+ : DIM variable_declarators
+ {
+ $$ = new DictionaryEntry (DecomposeQI("_local_vars_", lexer.Location), $2);
+ }
+ ;
+
+
+local_constant_declaration
+ : CONST constant_declarators
+ {
+ if ($2 != null)
+ $$ = new DictionaryEntry (DecomposeQI("_local_consts_", lexer.Location), $2);
+ else
+ $$ = null;
+ }
+ ;
+
+constant_declarators
+ : constant_declarator
+ {
+ ArrayList decl = new ArrayList ();
+ if ($1 != null)
+ decl.Add ($1);
+
+ $$ = decl;
+ }
+ | constant_declarators COMMA constant_declarator
+ {
+ ArrayList decls = (ArrayList) $1;
+ if ($3 != null)
+ decls.Add ($3);
+
+ $$ = $1;
+ }
+ ;
+
+constant_declarator
+ : variable_name opt_type_decl opt_variable_initializer
+ {
+ VarName vname = (VarName) $1;
+ string varname = (string) vname.Name;
+ current_rank_specifiers = (ArrayList) vname.Rank;
+ object varinit = $3;
+ ArrayList a_dims = null;
+
+ if (varinit == null)
+ Report.Error (
+ 30438, lexer.Location, "Constant should have a value"
+ );
+
+ if (vname.Type != null && $2 != null)
+ Report.Error (
+ 30302, lexer.Location,
+ "Type character cannot be used with explicit type declaration" );
+
+ Expression vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
+
+ if (current_rank_specifiers != null)
+ {
+ Report.Error (30424, lexer.Location, "Constant doesn't support array");
+ $$ = null;
+ }
+ else
+ $$ = new VariableDeclaration (varname, vartype, varinit, lexer.Location, null);
+ }
+ ;
+
+variable_declarators
+ : variable_declarator
+ {
+ ArrayList decl = new ArrayList ();
+ decl.AddRange ((ArrayList) $1);
+ $$ = decl;
+ }
+ | variable_declarators COMMA variable_declarator
+ {
+ ArrayList decls = (ArrayList) $1;
+ decls.AddRange ((ArrayList) $3);
+ $$ = $1;
+ }
+ ;
+
+variable_declarator
+ : variable_names opt_type_decl opt_variable_initializer
+ {
+ ArrayList names = (ArrayList) $1;
+ object varinit = $3;
+ ArrayList VarDeclarations = new ArrayList();
+ Expression vartype;
+ ArrayList a_dims = null;
+
+ if ((names.Count > 1) && (varinit != null))
+ Report.Error (
+ 30671, lexer.Location,
+ "Multiple variables with single type can not have " +
+ "a explicit initialization" );
+
+
+ foreach (VarName vname in names)
+ {
+ string varname = (string) vname.Name;
+ current_rank_specifiers = (ArrayList) vname.Rank;
+ a_dims = null;
+ varinit = $3;
+
+ if(vname.Type != null && $2 != null)
+ Report.Error (
+ 30302, lexer.Location,
+ "Type character cannot be used with explicit type declaration" );
+
+ // Some checking is required for particularly weird declarations
+ // like Dim a As Integer(,)
+ if ($2 is Pair) {
+ vartype = (Expression) ((Pair) $2).First;
+
+ /*if ($3 != null && $3 is ArrayList)
+ Report.Error (205, "End of statement expected.");*/
+
+ ArrayList args = (ArrayList) ((Pair) $2).Second;
+ if (current_rank_specifiers != null)
+ Report.Error (31087, lexer.Location,
+ "Array types specified in too many places");
+
+ if (VariableDeclaration.IndexesSpecifiedInRank (args))
+ Report.Error (30638, "Array bounds cannot appear in type specifiers.");
+
+ current_rank_specifiers = new ArrayList ();
+ current_rank_specifiers.Add (args);
+ }
+ else
+ vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
+
+ // if the variable is an array with explicit bound
+ // and having explicit initialization throw exception
+ if (current_rank_specifiers != null && varinit != null)
+ {
+ bool broken = false;
+ foreach (ArrayList exprs in current_rank_specifiers)
+ {
+ foreach (Expression expr in exprs)
+ {
+ if (!((Expression)expr is EmptyExpression ))
+ {
+ Report.Error (
+ 30672, lexer.Location,
+ "Array declared with explicit bound " +
+ " can not have explicit initialization");
+ broken = true;
+ break;
+ }
+ }
+ if (broken)
+ break;
+ }
+ }
+
+ /*
+ Check for a declaration like Dim a(2) or Dim a(2,3)
+ If this is the case, we must generate an ArrayCreationExpression
+ and, in case, add the initializer after the array has been created.
+ */
+// if (VariableDeclaration.IsArrayDecl (this)) {
+// if (VariableDeclaration.IndexesSpecified(current_rank_specifiers)) {
+// a_dims = (ArrayList) current_rank_specifiers;
+// VariableDeclaration.VBFixIndexLists (ref a_dims);
+// varinit = VariableDeclaration.BuildArrayCreator(vartype, a_dims, (ArrayList) varinit, lexer.Location);
+// }
+// vartype = DecomposeQI (vartype.ToString() + VariableDeclaration.BuildRanks (current_rank_specifiers, false, lexer.Location), lexer.Location);
+// }
+
+ if (vartype is New) {
+ if (varinit != null) {
+ Report.Error (30205, lexer.Location, "End of statement expected");
+ $$ = null;
+ }
+ else
+ {
+ varinit = vartype;
+ vartype = ((New)vartype).RequestedType;
+ }
+ }
+ VarDeclarations.Add (new VariableDeclaration (varname, vartype, varinit, lexer.Location, null));
+ }// end of for
+ $$ = VarDeclarations;
+ }
+ ;
+
+variable_names
+ : variable_name
+ {
+ ArrayList list = new ArrayList ();
+ list.Add ($1);
+ $$ = list;
+ }
+ | variable_names COMMA variable_name
+ {
+ ArrayList list = (ArrayList) $1;
+ list.Add ($3);
+ $$ = list;
+ }
+ ;
+
+variable_name
+ : identifier opt_type_character opt_array_name_modifier
+ {
+ $$ = new VarName ($1, $2, $3);
+ }
+ ;
+
+opt_type_spec
+ : /* empty */
+ {
+ $$ = null;
+ }
+ | AS type
+ {
+ $$ = (Expression) $2;
+ }
+ ;
+
+opt_type_with_ranks
+ : opt_type_spec
+// | AS type rank_specifiers
+// {
+// // $$ = DecomposeQI ($2.ToString() + VariableDeclaration.BuildRanks ((ArrayList)$3, true, lexer.Location), lexer.Location);
+// }
+ ;
+
+opt_type_decl
+ : opt_type_with_ranks
+ {
+ $$ = $1;
+ }
+ | AS NEW type
+ {
+ New n = new New ((Expression)$3, null, lexer.Location);
+ $$ = (Expression) n;
+ }
+ | AS NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
+ $$ = (Expression) n;
+ }
+ /*| AS NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS
+ {
+ ArrayList args = new ArrayList();
+ Argument arg = new Argument ((Expression) $6, Argument.AType.Expression);
+ args.Add (arg);
+
+ New n = new New ((Expression)$3, (ArrayList) args, lexer.Location);
+ $$ = (Expression) n;
+ }*/
+ ;
+
+opt_array_name_modifier
+ : /* empty */ { $$ = null; }
+// | array_type_modifier { $$ = $1; }
+ ;
+
+// array_type_modifier
+// : rank_specifiers { $$ = $1; }
+// ;
+
+opt_variable_initializer
+ : /* empty */ { $$ = null; }
+ | ASSIGN variable_initializer { $$ = $2; }
+ ;
+
+variable_initializer
+ : expression
+ {
+ $$ = $1;
+ }
+ | array_initializer
+ {
+ $$ = $1;
+ }
+
+ ;
+
+array_initializer
+ : OPEN_BRACE CLOSE_BRACE
+ {
+ ArrayList list = new ArrayList ();
+ $$ = list;
+ }
+ | OPEN_BRACE variable_initializer_list CLOSE_BRACE
+ {
+ $$ = (ArrayList) $2;
+ }
+ ;
+
+variable_initializer_list
+ : variable_initializer
+ {
+ ArrayList list = new ArrayList ();
+ list.Add ($1);
+ $$ = list;
+ }
+ | variable_initializer_list COMMA variable_initializer
+ {
+ ArrayList list = (ArrayList) $1;
+ list.Add ($3);
+ $$ = list;
+ }
+ ;
+
+opt_rank_specifiers
+ : /* empty */
+ {
+ // $$ = "";
+ $$ = null;
+ }
+ | rank_specifiers
+ {
+ $$ = $1;
+ }
+ ;
+
+rank_specifiers
+ : rank_specifier
+ {
+ ArrayList rs = new ArrayList();
+ rs.Add ($1);
+ $$ = rs;
+ }
+ | rank_specifiers rank_specifier
+ {
+ ArrayList rs = (ArrayList) $1;
+ rs.Add ($2);
+ $$ = rs;
+ }
+ ;
+
+rank_specifier
+ : OPEN_PARENS opt_dim_specifiers CLOSE_PARENS
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_dim_specifiers
+ : /* empty */
+ {
+ ArrayList ds = new ArrayList();
+ ds.Add (new EmptyExpression());
+ $$ = ds;
+ }
+ | expression
+ {
+ ArrayList ds = new ArrayList();
+ ds.Add ((Expression) $1);
+ $$ = ds;
+ }
+ | opt_dim_specifiers COMMA expression
+ {
+ ArrayList ds = (ArrayList) $1;
+ ds.Add ((Expression) $3);
+ $$ = ds;
+ }
+ | opt_dim_specifiers COMMA
+ {
+ ArrayList ds = (ArrayList) $1;
+ ds.Add (new EmptyExpression());
+ $$ = ds;
+ }
+ ;
+
+// primary_expression
+// : literal
+// {
+// //TODO
+// }
+// | parenthesized_expression
+// | this_access
+// | base_access
+// | qualified_identifier
+// {
+// string name = (string) $1;
+// $$ = DecomposeQI (name, lexer.Location);
+// }
+// | get_type_expression
+// | member_access
+// | invocation_expression
+// //| element_access
+// | new_expression
+// | cast_expression
+// ;
+
+primary_expression
+ : literal
+ {
+ //TODO
+ }
+ | parenthesized_expression
+ | this_access
+ | base_access
+ | qualified_identifier
+ {
+ $$ = ((MemberName) $1).GetTypeExpression (lexer.Location);
+ }
+ | get_type_expression
+ | member_access
+ | invocation_expression
+ //| element_access
+ | new_expression
+ | cast_expression
+ ;
+
+
+
+literal
+ : boolean_literal
+ | integer_literal
+ | real_literal
+// | LITERAL_DATE { $$ = new DateLiteral ((DateTime)lexer.Value); }
+ | LITERAL_CHARACTER { $$ = new CharLiteral ((char) lexer.Value); }
+ | LITERAL_STRING { $$ = new StringLiteral ((string) lexer.Value); }
+ | NOTHING { $$ = NullLiteral.Null; }
+ ;
+
+real_literal
+ : LITERAL_SINGLE { $$ = 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 short)
+// $$ = new ShortLiteral ((Int16)v);
+ else if (v is long)
+ $$ = new LongLiteral ((Int64)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
+ {
+ if ($1 != null) {
+ string id_name = (string)$3;
+ if (id_name.ToUpper() == "NEW")
+ id_name = ".ctor";
+ $$ = new MemberAccess ((Expression) $1, id_name, lexer.Location);
+ }
+ else
+ {
+// if (with_stack.Count > 0) {
+// Expression e = (Expression) with_stack.Peek();
+// $$ = new MemberAccess (e, (string) $3, lexer.Location);
+// }
+// else
+// {
+// // OOps
+// }
+ }
+ }
+/* | primary_expression DOT NEW
+ {
+ $$ = new MemberAccess ((Expression) $1, (string) ".ctor", lexer.Location);
+ } */
+ | predefined_type DOT identifier
+ {
+ if ($1 != null)
+ $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
+ else
+ {
+// if (with_stack.Count > 0) {
+// Expression e = (Expression) with_stack.Peek();
+// $$ = new MemberAccess (e, (string) $3, lexer.Location);
+// }
+// else
+// {
+// // OOps
+// }
+ }
+ }
+ ;
+
+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);
+ }
+ | CALL primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
+ {
+ if ($2 == null) {
+ Location l = lexer.Location;
+ Report.Error (1, l, "THIS IS CRAZY");
+ }
+ $$ = new Invocation ((Expression) $2, (ArrayList) $3, lexer.Location);
+// Console.WriteLine ("Invocation: {0} with {1} arguments", $2, ($3 != null) ? ((ArrayList) $3).Count : 0);
+ }
+ ;
+
+base_access
+ : MYBASE DOT IDENTIFIER
+ {
+ string id_name = (string) $3;
+ if (id_name.ToUpper() == "NEW")
+ id_name = "New";
+ $$ = new BaseAccess (id_name, lexer.Location);
+ }
+/* | MYBASE DOT NEW
+ {
+ $$ = new BaseAccess ("New", lexer.Location);
+ }*/
+ ;
+
+opt_argument_list
+ : argument_list
+ {
+ /*
+ The 'argument' rule returns an 'empty' argument
+ of type NoArg (used for default arguments in invocations)
+ if no arguments are actually passed.
+
+ If there is only one argument and it is o type NoArg,
+ we return a null (empty) list
+ */
+ ArrayList args = (ArrayList) $1;
+ if (args.Count == 1 &&
+ ((Argument)args[0]).ArgType == Argument.AType.NoArg)
+ $$ = null;
+ else
+ $$ = $1;
+ }
+ ;
+
+argument_list
+ : argument
+ {
+ ArrayList list = new ArrayList ();
+ 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);
+ }
+ | BYREF variable_reference
+ {
+ $$ = new Argument ((Expression) $2, Argument.AType.Ref);
+ }
+ | /* empty */
+ {
+ $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
+ }
+ | ADDRESSOF expression
+ {
+ $$ = new Argument ((Expression) $2, Argument.AType.AddressOf);
+ }
+ ;
+
+variable_reference
+ : expression {/* note ("section 5.4"); */ $$ = $1; }
+ ;
+
+
+expression
+ : conditional_xor_expression { $$ = $1; }
+ /*| assignment_expression*/
+ ;
+
+opt_expression
+ : /* empty */
+ | expression
+ ;
+
+this_access
+ : ME
+ {
+ $$ = new This (current_block, lexer.Location);
+ }
+ | MYCLASS
+ {
+ // FIXME: This is actually somewhat different from Me
+ // because it is for accessing static (classifier) methods/properties/fields
+ $$ = new This (current_block, lexer.Location);
+ }
+ ;
+
+cast_expression
+ : DIRECTCAST OPEN_PARENS expression COMMA type CLOSE_PARENS
+ {
+ // TODO
+ }
+ | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
+ {
+ $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
+ }
+ | cast_operator OPEN_PARENS expression CLOSE_PARENS
+ {
+ $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+cast_operator
+ : CBOOL { $$ = TypeManager.system_boolean_expr; }
+ | CBYTE { $$ = TypeManager.system_byte_expr; }
+ | CCHAR { $$ = TypeManager.system_char_expr; }
+// | CDATE { $$ = TypeManager.system_date_expr; }
+ | CDBL { $$ = TypeManager.system_double_expr; }
+ | CDEC { $$ = TypeManager.system_decimal_expr; }
+ | CINT { $$ = TypeManager.system_int32_expr; }
+ | CLNG { $$ = TypeManager.system_int64_expr; }
+ | COBJ { $$ = TypeManager.system_object_expr; }
+ | CSHORT { $$ = TypeManager.system_int16_expr; }
+ | CSNG { $$ = TypeManager.system_single_expr; }
+ | CSTR { $$ = TypeManager.system_string_expr; }
+ ;
+
+get_type_expression
+ : GETTYPE OPEN_PARENS type CLOSE_PARENS
+ {
+ $$ = new TypeOf ((Expression) $3, lexer.Location);
+ }
+ ;
+
+exponentiation_expression
+ : primary_expression
+ | exponentiation_expression OP_EXP primary_expression
+ {
+ //TODO
+ }
+ ;
+
+prefixed_unary_expression
+ : exponentiation_expression
+ | PLUS prefixed_unary_expression
+ {
+ //FIXME: Is this rule correctly defined ?
+ $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
+ }
+ | MINUS prefixed_unary_expression
+ {
+ //FIXME: Is this rule correctly defined ?
+ $$ = new Unary (Unary.Operator.UnaryNegation, (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);
+ }
+ ;
+
+integer_division_expression
+ : multiplicative_expression
+ | integer_division_expression OP_IDIV multiplicative_expression
+ {
+ //FIXME: Is this right ?
+ $$ = new Binary (Binary.Operator.Division,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+mod_expression
+ : integer_division_expression
+ | mod_expression MOD integer_division_expression
+ {
+ $$ = new Binary (Binary.Operator.Modulus,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+additive_expression
+ : mod_expression
+ | additive_expression PLUS mod_expression
+ {
+ $$ = new Binary (Binary.Operator.Addition,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | additive_expression MINUS mod_expression
+ {
+ $$ = new Binary (Binary.Operator.Subtraction,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+concat_expression
+ : additive_expression
+ | concat_expression OP_CONCAT additive_expression
+ {
+ // FIXME: This should only work for String expressions
+ // We probably need to use something from the runtime
+ $$ = new Binary (Binary.Operator.Addition,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+shift_expression
+ : concat_expression
+ | shift_expression OP_SHIFT_LEFT concat_expression
+ {
+ // TODO
+ }
+ | shift_expression OP_SHIFT_RIGHT concat_expression
+ {
+ //TODO
+ }
+ ;
+
+relational_expression
+ : shift_expression
+ | relational_expression ASSIGN shift_expression
+ {
+ $$ = new Binary (Binary.Operator.Equality,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | relational_expression OP_NE shift_expression
+ {
+ $$ = new Binary (Binary.Operator.Inequality,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | 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 shift_expression
+ {
+ //FIXME: Should be a different op for reference equality but allows tests to use Is
+ $$ = new Binary (Binary.Operator.Equality,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | TYPEOF shift_expression IS type
+ {
+ //FIXME: Is this rule correctly defined ?
+ $$ = new Is ((Expression) $2, (Expression) $4, lexer.Location);
+ }
+ ;
+
+negation_expression
+ : relational_expression
+ | NOT negation_expression
+ {
+ //FIXME: Is this rule correctly defined ?
+ $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
+ }
+ ;
+
+conditional_and_expression
+ : negation_expression
+ | conditional_and_expression AND negation_expression
+ {
+ $$ = new Binary (Binary.Operator.LogicalAnd,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | conditional_and_expression ANDALSO negation_expression
+ { // FIXME: this is likely to be broken
+ $$ = new Binary (Binary.Operator.LogicalAnd,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+conditional_or_expression
+ : conditional_and_expression
+ | conditional_or_expression OR conditional_and_expression
+ {
+ $$ = new Binary (Binary.Operator.LogicalOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | conditional_or_expression ORELSE conditional_and_expression
+ { // FIXME: this is likely to be broken
+ $$ = new Binary (Binary.Operator.LogicalOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+conditional_xor_expression
+ : conditional_or_expression
+ | conditional_xor_expression XOR conditional_or_expression
+ {
+ $$ = new Binary (Binary.Operator.ExclusiveOr,
+ (Expression) $1, (Expression) $3, lexer.Location);
+ }
+ ;
+
+assignment_expression
+ : prefixed_unary_expression ASSIGN expression
+ {
+ $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
+ }
+ | prefixed_unary_expression STAR ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.Multiply, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression DIV ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.Division, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression PLUS ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.Addition, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression MINUS ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.Subtraction, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression OP_SHIFT_LEFT ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.LeftShift, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression OP_SHIFT_RIGHT ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ $$ = new CompoundAssign (
+ Binary.Operator.RightShift, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression OP_CONCAT ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ // FIXME should be strings only
+ $$ = new CompoundAssign (
+ Binary.Operator.Addition, (Expression) $1, (Expression) $4, l);
+ }
+ | prefixed_unary_expression OP_EXP ASSIGN expression
+ {
+ Location l = lexer.Location;
+
+ /* TODO: $$ = new CompoundAssign (
+ Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $4, l); */
+ }
+ | prefixed_unary_expression ASSIGN ADDRESSOF expression
+ {
+// ArrayList args = new ArrayList();
+// Argument arg = new Argument ((Expression) $4, Argument.AType.Expression);
+// args.Add (arg);
+
+// New n = new New ((Expression) $1, (ArrayList) args, lexer.Location);
+// n.isDelegate = true;
+ $$ = new Assign ((Expression) $1, (Expression) $4, lexer.Location);
+ }
+ ;
+
+constant_expression
+ : expression
+ ;
+
+boolean_expression
+ : expression
+ ;
+
+type
+ : namespace_or_type_name
+ {
+ $$ = ((MemberName) $1).GetTypeExpression (lexer.Location);
+ }
+ | builtin_types
+ //| array_type
+ ;
+
+type_list
+ : type
+ {
+ ArrayList types = new ArrayList ();
+
+ types.Add ($1);
+ $$ = types;
+ }
+ | type_list COMMA type
+ {
+ ArrayList types = (ArrayList) $1;
+
+ types.Add ($3);
+ $$ = types;
+ }
+ ;
+
+namespace_or_type_name
+ : qualified_identifier
+ ;
+
+builtin_types
+ : OBJECT { $$ = TypeManager.system_object_expr; }
+ | primitive_type
+ ;
+
+primitive_type
+ : numeric_type
+ | BOOLEAN { $$ = TypeManager.system_boolean_expr; }
+// | DATE { $$ = TypeManager.system_date_expr; }
+ | CHAR { $$ = TypeManager.system_char_expr; }
+ | STRING { $$ = TypeManager.system_string_expr; }
+ ;
+
+
+numeric_type
+ : integral_type
+ | floating_point_type
+ | DECIMAL { $$ = TypeManager.system_decimal_expr; }
+ ;
+
+integral_type
+ :
+ | BYTE { $$ = TypeManager.system_byte_expr; }
+ | SHORT { $$ = TypeManager.system_int16_expr; }
+ | INTEGER { $$ = TypeManager.system_int32_expr; }
+ | LONG { $$ = TypeManager.system_int64_expr; }
+ ;
+
+floating_point_type
+ : SINGLE { $$ = TypeManager.system_single_expr; }
+ | DOUBLE { $$ = TypeManager.system_double_expr; }
+ ;
+
+pp_directive
+ : HASH IDENTIFIER OPEN_PARENS LITERAL_STRING COMMA LITERAL_INTEGER CLOSE_PARENS EOL
+ {
+// if(tokenizerController.IsAcceptingTokens)
+// {
+// if(in_external_source)
+// Report.Error (30580, lexer.Location, "#ExternalSource directives may not be nested");
+// else {
+// in_external_source = true;
+
+// lexer.EffectiveSource = (string) $4;
+// lexer.EffectiveLine = (int) $6;
+// }
+// }
+ }
+ | HASH IDENTIFIER LITERAL_STRING EOL
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+ string id = ($2 as string);
+
+ if(!($2 as string).ToLower().Equals("region"))
+ Report.Error (30205, lexer.Location, "Invalid Pre-processor directive");
+ else
+ {
+ ++in_marked_region;
+ }
+ }
+ }
+ | HASH END IDENTIFIER EOL
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+// if( ($3 as string).ToLower().Equals("externalsource")) {
+// if(!in_external_source)
+// Report.Error (30578, lexer.Location, "'#End ExternalSource' must be preceded by a matching '#ExternalSource'");
+// else {
+// in_external_source = false;
+// lexer.EffectiveSource = lexer.Source;
+// lexer.EffectiveLine = lexer.Line;
+// }
+// }
+ /* else */if(($3 as string).ToLower().Equals("region")) {
+ if(in_marked_region > 0)
+ --in_marked_region;
+ else
+ Report.Error (30205, lexer.Location, "'#End Region' must be preceded by a matching '#Region'");
+ }
+ else {
+ Report.Error (29999, lexer.Location, "Unrecognized Pre-Processor statement");
+ }
+ }
+ }
+ | HASH CONST IDENTIFIER ASSIGN boolean_literal EOL
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ {
+ //TODO;
+ }
+ }
+ | HASH IF
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.IF;
+
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ boolean_literal opt_then EOL
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.IF, (BoolLiteral)$4);
+ }
+ | HASH ELSEIF
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSEIF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ boolean_literal opt_then EOL
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ELSEIF, (BoolLiteral)$4);
+ }
+ | HASH ELSE
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSE;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ EOL
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ELSE, new BoolLiteral(true));
+ }
+ | HASH END IF
+ {
+ IfElseStateMachine.Token tok = IfElseStateMachine.Token.ENDIF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+ EOL
+ {
+ HandleConditionalDirective(IfElseStateMachine.Token.ENDIF, new BoolLiteral(false));
+ }
+ | HASH error EOL
+ {
+ if(tokenizerController.IsAcceptingTokens)
+ Report.Error(2999, lexer.Location, "Unrecognized Pre-Processor statement");
+ else
+ Report.Warning (9999, lexer.Location, "Unrecognized Pre-Processor statement");
+ }
+
+ ;
+
+%%
+
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+ get {
+ return lexer;
+ }
+}
+
+public static 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);
+ }
+}
+
+Block declare_local_variables (Expression dummy_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;
+ //
+
+ VariableDeclaration.FixupTypes (variable_declarators);
+ // FIXME: Should VariableDeclaration.FixupArrayTypes be called here
+
+ if (current_block.Used)
+ implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
+ else
+ implicit_block = current_block;
+
+
+ foreach (VariableDeclaration decl in variable_declarators){
+ Expression type = decl.type;
+ 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 ();
+ inits.Add (decl);
+ }
+ }
+ }
+
+ if (inits == null)
+ return implicit_block;
+
+ foreach (VariableDeclaration decl in inits){
+ Assign assign;
+ Expression expr;
+ Expression type = decl.type;
+
+ if ((decl.expression_or_array_initializer is Expression) ||
+ (decl.expression_or_array_initializer is New)) {
+ 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 dummy_type, ArrayList variable_declarators)
+{
+ Block implicit_block;
+ VariableDeclaration.FixupTypes (variable_declarators);
+
+ if (current_block.Used)
+ implicit_block = new Block (current_block, Block.Flags.Implicit);
+ else
+ implicit_block = current_block;
+
+ foreach (VariableDeclaration decl in variable_declarators){
+ Expression type = decl.type;
+ implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
+ current_local_parameters, decl.Location);
+ }
+
+ return implicit_block;
+}
+
+
+
+struct VarName {
+ public object Name;
+ public object Type;
+ public object Rank;
+
+ public VarName (object n, object t, object r)
+ {
+ Name = n;
+ Type = t;
+ Rank = r;
+ }
+ }
+
+
+// <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 string DocComment;
+ public Expression type;
+ public ArrayList dims;
+
+ public VariableDeclaration (string id, Expression t, object eoai, Location l, Attributes opt_attrs)
+ {
+ this.identifier = id;
+ this.expression_or_array_initializer = eoai;
+ this.Location = l;
+ this.OptAttributes = opt_attrs;
+ this.type = t;
+ this.dims = null;
+ }
+
+ public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
+ {
+ }
+
+ public VariableDeclaration (string id, Expression t, Location l) : this (id, t, null, l, null)
+ {
+ }
+
+ public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs) : this
+ (id, TypeManager.system_object_expr, eoai, l, opt_attrs)
+ {
+ }
+
+ public static ArrayCreation BuildArrayCreator (Expression vartype, ArrayList a_dims, ArrayList varinit, Location l)
+ {
+ // FIXME : This is broken: only the first rank is parsed
+ return new ArrayCreation (vartype, (ArrayList) a_dims[0], "", varinit, l);
+ }
+
+ public static void FixupTypes (ArrayList vars)
+ {
+ int varcount = vars.Count;
+ VariableDeclaration last_var = (VariableDeclaration) vars[varcount - 1];
+
+ if (last_var.type == null)
+ last_var.type = TypeManager.system_object_expr;
+
+ Expression cur_type = last_var.type;
+ int n = varcount - 1;
+
+ while (n >= 0) {
+ VariableDeclaration var = (VariableDeclaration) vars[n--];
+ if (var.type == null)
+ var.type = cur_type;
+ else
+ cur_type = var.type;
+ }
+ }
+
+ public static bool IndexesSpecifiedInRank (ArrayList IndexList)
+ {
+ bool res = false;
+
+ if (IndexList != null) {
+ foreach (Expression e in IndexList)
+ if (!(e is EmptyExpression)) {
+ res = true;
+ break;
+ }
+ }
+ return (res);
+ }
+
+
+ public static bool IndexesSpecified (ArrayList ranks)
+ {
+ bool res = false;
+
+ if (ranks != null) {
+ foreach (ArrayList IndexList in ranks) {
+ if (IndexesSpecifiedInRank (IndexList)) {
+ res = true;
+ break;
+ }
+ }
+ }
+ return (res);
+ }
+
+ public static string StripDims (string varname, ref string d)
+ {
+ string res = varname;
+ string dres = "";
+
+ if (varname.IndexOf("[") >= 0) {
+ dres = varname.Substring(varname.IndexOf("["), (varname.LastIndexOf("]") - varname.IndexOf("["))+1);
+ res = varname.Substring(0, varname.IndexOf("["));
+ }
+ d = dres;
+ return (res);
+ }
+
+ public static string StripDims (string varname)
+ {
+ string dres = "";
+
+ return (StripDims(varname, ref dres));
+ }
+
+ public static string StripIndexesFromDims (string dims)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (char c in dims)
+ if (c == ',' || c == ']' || c == '[')
+ sb.Append (c);
+
+ return sb.ToString();
+ }
+
+ public static string BuildRank (ArrayList rank)
+ {
+ bool allEmpty;
+ return BuildRank(rank, out allEmpty);
+ }
+
+ public static string BuildRank (ArrayList rank, out bool allEmpty)
+ {
+ string res = "";
+
+ res += "[";
+ allEmpty = true;
+ bool first = true;
+ foreach (object e in rank) {
+ if (!(e is EmptyExpression))
+ allEmpty = false;
+ if (!first)
+ res += ",";
+ first = false;
+ }
+
+ res += "]";
+ return res;
+ }
+
+ public static string BuildRanks (ArrayList rank_specifiers, bool mustBeEmpty, Location loc)
+ {
+ string res = "";
+
+ bool allEmpty = true;
+ foreach (ArrayList rank in rank_specifiers) {
+ bool tmp;
+ res = BuildRank (rank, out tmp) + res;
+ if (!tmp)
+ allEmpty = false;
+ }
+ if (!allEmpty && mustBeEmpty)
+ Report.Error (30638, loc, "Array bounds cannot appear in type specifiers.");
+
+ return res;
+ }
+
+ public static void VBFixIndexList (ref ArrayList IndexList)
+ {
+ if (IndexList != null) {
+ for (int x = 0; x < IndexList.Count; x++) {
+ Expression e = (Expression) IndexList[x];
+ if (!(e is EmptyExpression)) {
+ IndexList[x] = new Binary (Binary.Operator.Addition, e, new IntLiteral(1), Location.Null);
+ }
+ }
+ }
+ }
+
+// public static bool IsArrayDecl (Parser t)
+// {
+// // return (varname.IndexOf("[") >= 0);
+// return (t.current_rank_specifiers != null);
+// }
+
+ public static void VBFixIndexLists (ref ArrayList ranks)
+ {
+ if (ranks != null) {
+ for (int x = 0; x < ranks.Count; x++) {
+ ArrayList IndexList = (ArrayList) ranks[x];
+ VBFixIndexList (ref IndexList);
+ }
+ }
+ }
+
+ public static void FixupArrayTypes (ArrayList vars)
+ {
+ int varcount = vars.Count;
+ string dims;
+
+ foreach (VariableDeclaration var in vars) {
+ if (var.identifier.EndsWith(",")) {
+ dims = "[" + var.identifier.Substring(var.identifier.IndexOf (","),
+ var.identifier.LastIndexOf(",")) + "]";
+ var.identifier = var.identifier.Substring (0, var.identifier.IndexOf (","));
+ var.type = new ComposedCast (var.type, (string) dims, var.Location);
+ }
+ }
+ }
+}
+
+
+// public Property BuildSimpleProperty (Expression p_type, string name,
+// Field p_fld, int mod_flags,
+// Attributes attrs, Location loc)
+// {
+// Property p;
+// Block get_block, set_block;
+// Accessor acc_set, acc_get;
+// StatementExpression a_set;
+// Statement a_get;
+// Parameter [] args;
+
+// // Build SET Block
+// Parameter implicit_value_parameter = new Parameter (p_type, "value", Parameter.Modifier.NONE, null);
+// args = new Parameter [1];
+// args [0] = implicit_value_parameter;
+
+// Parameters set_params = new Parameters (args, null, loc);
+// a_set = new StatementExpression ((ExpressionStatement) new Assign ((Expression) DecomposeQI(p_fld.Name, loc),
+// (Expression) new SimpleName("value", loc), loc), loc);
+
+// set_block = new Block (current_block, set_params, loc, Location.Null);
+// set_block.AddStatement ((Statement) a_set);
+// acc_set = new Accessor (set_block, attrs);
+
+// // Build GET Block
+// a_get = (Statement) new Return ((Expression) DecomposeQI(p_fld.Name, loc), loc);
+// get_block = new Block (current_block, null, loc, Location.Null);
+// get_block.AddStatement ((Statement) a_get);
+// acc_get = new Accessor (get_block, attrs);
+
+// p = new Property (p_type, name, mod_flags, (Accessor) acc_get, (Accessor) acc_set, attrs, loc);
+
+// return (p);
+// }
+
+void start_block ()
+{
+ if (current_block == null){
+ current_block = new ToplevelBlock ((ToplevelBlock) top_current_block,
+ current_local_parameters, lexer.Location);
+ top_current_block = current_block;
+ } else {
+ current_block = new Block (current_block, current_local_parameters,
+ lexer.Location, Location.Null);
+ }
+}
+
+
+Block end_block ()
+{
+ Block res;
+
+ while (current_block.Implicit)
+ current_block = current_block.Parent;
+ res = current_block;
+ current_block.SetEndLocation (lexer.Location);
+ current_block = current_block.Parent;
+ if (current_block == null)
+ top_current_block = null;
+
+ return res;
+}
+
+// private void AddHandler (Expression evt_definition, Expression handler_exp)
+// {
+// AddHandler (current_block, evt_definition, handler_exp);
+// }
+
+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;
+ }
+}
+
+// private void AddHandler (Block b, Expression evt_id, Expression handles_exp)
+// {
+// Expression evt_target;
+// Location loc = lexer.Location;
+
+// Statement addhnd = (Statement) new AddHandler (evt_id,
+// handles_exp,
+// loc);
+
+// b.AddStatement (addhnd);
+// }
+
+// private void RaiseEvent (string evt_name, ArrayList args)
+// {
+// Location loc = lexer.Location;
+
+// Invocation evt_call = new Invocation (DecomposeQI(evt_name, loc), args, lexer.Location);
+// Statement s = (Statement)(new StatementExpression ((ExpressionStatement) evt_call, loc));
+// current_block.AddStatement (s);
+// }
+
+// private void RemoveHandler (Block b, Expression evt_definition, Expression handler_exp)
+// {
+// Expression evt_target;
+// Location loc = lexer.Location;
+
+// Statement rmhnd = (Statement) new RemoveHandler (evt_definition,
+// handler_exp,
+// loc);
+// b.AddStatement (rmhnd);
+// }
+
+// <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>
+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 + ")");
+
+}
+
+// private void RemoveHandler (Expression evt_definition, Expression handler_exp)
+// {
+// RemoveHandler (current_block, evt_definition, handler_exp);
+// }
+
+// FIXME: This needs to be fixed for This and Base access because the way the name of the
+// mbas' constructor is changed from "New" to current_container.Basename
+
+private ConstructorInitializer CheckConstructorInitializer (ref ArrayList s)
+{
+ ConstructorInitializer ci = null;
+
+ if (s.Count > 0) {
+ if (s[0] is StatementExpression && ((StatementExpression) s[0]).expr is Invocation) {
+ Invocation i = (Invocation) ((StatementExpression) s[0]).expr;
+
+ if (i.expr is BaseAccess) {
+ BaseAccess ba = (BaseAccess) i.expr;
+ if (ba.member == "New" || ba.member == ".ctor") {
+ ci = new ConstructorBaseInitializer (i.Arguments, current_local_parameters, lexer.Location);
+ s.RemoveAt(0);
+ }
+ }
+ if (i.expr.ToString() == "Mono.MonoBASIC.This..ctor") {
+ ci = new ConstructorThisInitializer (i.Arguments, current_local_parameters, lexer.Location);
+ s.RemoveAt(0);
+ }
+ }
+ }
+ return ci;
+}
+
+void Error_ExpectingTypeName (Location l, Expression expr)
+{
+ if (expr is Invocation){
+ Report.Error (1002, l, "; expected");
+ } else {
+ Report.Error (-1, l, "Invalid Type definition");
+ }
+}
+
+static bool AlwaysAccept (MemberInfo m, object filterCriteria) {
+ return true;
+}
+
+private void ReportError9998()
+{
+ Report.Error (29998, lexer.Location, "This construct is only available in MonoBASIC extended syntax.");
+}
+
+public CSharpParser (SeekableStreamReader reader, SourceFile file, ArrayList defines)
+{
+ current_namespace = new NamespaceEntry (null, file, null, Location.Null);
+ this.name = file.Name;
+ this.file = file;
+ current_container = RootContext.Tree.Types;
+ current_container.NamespaceEntry = current_namespace;
+ oob_stack = new Stack ();
+ switch_stack = new Stack ();
+
+ lexer = new Tokenizer (reader, file, defines);
+
+ ifElseStateMachine = new IfElseStateMachine();
+ tokenizerController = new TokenizerController(lexer);
+}
+
+public void parse ()
+{
+ try {
+ if (yacc_verbose_flag > 1)
+ yyparse (lexer, new yydebug.yyDebugSimple ());
+ else
+ yyparse (lexer);
+ Tokenizer tokenizer = lexer as Tokenizer;
+ tokenizer.cleanup ();
+ } catch (Exception e){
+ //
+ // Removed for production use, use parser verbose to get the output.
+ //
+ // Console.WriteLine (e);
+ Report.Error (-25, lexer.Location, "Parsing error");
+ if (yacc_verbose_flag > 0)
+ Console.WriteLine (e);
+ }
+}
+
+
+// protected override int parse ()
+// {
+// RootContext.InitializeImports(ImportsList);
+// current_namespace = new Namespace (null, RootContext.RootNamespace);
+// current_container = RootContext.Tree.Types;
+// current_container.Namespace = current_namespace;
+// oob_stack = new Stack ();
+// switch_stack = new Stack ();
+// expr_stack = new Stack ();
+// tmp_blocks = new Stack();
+// with_stack = new Stack();
+// statement_stack = new Stack();
+
+// allow_global_attribs = true;
+// expecting_global_attribs = false;
+// expecting_local_attribs = false;
+// local_attrib_section_added = false;
+
+// UseExtendedSyntax = name.EndsWith(".mbs");
+// OptionExplicit = InitialOptionExplicit || UseExtendedSyntax;
+// OptionStrict = InitialOptionStrict || UseExtendedSyntax;
+// OptionCompareBinary = InitialOptionCompareBinary;
+
+// lexer = new Tokenizer (input, name, defines);
+
+// ifElseStateMachine = new IfElseStateMachine();
+// tokenizerController = new TokenizerController(lexer);
+
+// StringBuilder value = new StringBuilder ();
+// try {
+// if (yacc_verbose_flag > 0)
+// yyparse (lexer, new yydebug.yyDebugSimple ());
+// else {
+// yyparse (lexer);
+// cleanup();
+// }
+// }
+// catch(MBASException e) {
+// Report.Error(e.code, e.loc, e.Message);
+// }
+// catch (Exception e) {
+// if (Report.Stacktrace)
+// Console.WriteLine(e);
+// Report.Error (29999, lexer.Location, "Parsing error");
+// }
+
+// RootContext.VerifyImports();
+
+// return Report.Errors;
+// }
+
+// void cleanup()
+// {
+// try {
+// ifElseStateMachine.HandleToken(IfElseStateMachine.Token.EOF);
+// }
+// catch(ApplicationException) {
+// throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+// }
+
+// if(in_external_source)
+// Report.Error (30579, lexer.Location, "'#ExternalSource' directives must end with matching '#End ExternalSource'");
+
+// if(in_marked_region > 0)
+// Report.Error (30205, lexer.Location, "'#Region' directive must be followed by a matching '#End Region'");
+// }
+
+void HandleConditionalDirective(IfElseStateMachine.Token tok, BoolLiteral expr)
+{
+ try {
+ tokenizerController.PositionTokenizerCursor(tok, expr);
+ }
+ catch(ApplicationException) {
+ tok = IfElseStateMachine.Token.EOF;
+ try {
+ ifElseStateMachine.HandleToken(tok);
+ }
+ catch(ApplicationException) {
+ throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+ }
+ }
+}
+/* end end end */
+
+// <summary>
+// Given the @class_name name, it creates a fully qualified name
+// based on the containing declaration space
+// </summary>
+MemberName
+MakeName (MemberName class_name)
+{
+ string ns = current_namespace.FullName;
+
+ if (current_container.Name == ""){
+ if (ns != "")
+ return new MemberName (new MemberName (ns), class_name);
+ else
+ return class_name;
+ } else {
+ return new MemberName (current_container.MemberName, class_name);
+ }
+}
+
+}
--- /dev/null
+//
+// Mono.MonoBASIC.Tokenizer.cs: The Tokenizer for the MonoBASIC compiler
+//
+// Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
+//
+// Based on cs-tokenizer.cs by Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// Copyright (C) 2001 A Rafael D Teixeira
+//
+
+namespace Mono.CSharp
+{
+ using System;
+ using System.Text;
+ using System.Collections;
+ using System.IO;
+ using System.Globalization;
+ // using Mono.Languages;
+ using Mono.CSharp;
+
+ /// <summary>
+ /// Tokenizer for MonoBASIC source code.
+ /// </summary>
+
+ public class Tokenizer : yyParser.yyInput
+ {
+ SeekableStreamReader reader;
+ SourceFile file_name;
+ SourceFile ref_name;
+ int ref_line = 0;
+ int line = 0;
+ int col = 1;
+ public int current_token = Token.ERROR;
+ bool handle_get_set = false;
+ bool cant_have_a_type_character = false;
+
+ public int ExpandedTabsSize = 4;
+
+ public string location {
+ get {
+ string det;
+
+ if (current_token == Token.ERROR)
+ det = "detail: " + error_details;
+ else
+ det = "";
+
+ return "Line: "+line+" Col: "+col + "\n" +
+ "VirtLine: "+ref_line +
+ " Token: "+current_token + " " + det;
+ }
+ }
+
+ public bool properties {
+ get {
+ return handle_get_set;
+ }
+
+ set {
+ handle_get_set = value;
+ }
+ }
+
+ //
+ // Class variables
+ //
+ static Hashtable keywords;
+ static NumberStyles styles;
+ static NumberFormatInfo csharp_format_info;
+
+ //
+ // Values for the associated token returned
+ //
+ StringBuilder number;
+ int putback_char = -1;
+ Object val;
+
+ //
+ // Details about the error encoutered by the tokenizer
+ //
+ string error_details;
+
+ public string error {
+ get {
+ return error_details;
+ }
+ }
+
+// public string Source {
+// get {
+// return file_name;
+// }
+
+// set {
+// file_name = value;
+// ref_name = value;
+// //Location.SetCurrentSource(file_name);
+// }
+// }
+
+// public string EffectiveSource {
+// get {
+// return ref_name;
+// }
+// set {
+// ref_name = value;
+// //Location.SetCurrentSource(ref_name);
+// }
+// }
+
+ public int Line {
+ get {
+ return line;
+ }
+ }
+
+ public int EffectiveLine {
+ get {
+ return ref_line;
+ }
+ set {
+ ref_line = value;
+ }
+ }
+
+ public int Col {
+ get {
+ return col;
+ }
+ }
+
+ static void initTokens ()
+ {
+ keywords = new Hashtable ();
+
+ keywords.Add ("addhandler", Token.ADDHANDLER);
+ keywords.Add ("addressof", Token.ADDRESSOF);
+ keywords.Add ("alias", Token.ALIAS);
+ keywords.Add ("and", Token.AND);
+ keywords.Add ("andalso", Token.ANDALSO);
+ keywords.Add ("ansi", Token.ANSI);
+ keywords.Add ("as", Token.AS);
+ keywords.Add ("assembly", Token.ASSEMBLY);
+ keywords.Add ("auto", Token.AUTO);
+ keywords.Add ("binary", Token.BINARY); // Not a VB.NET Keyword
+ keywords.Add ("boolean", Token.BOOLEAN);
+ keywords.Add ("byref", Token.BYREF);
+ keywords.Add ("byte", Token.BYTE);
+ keywords.Add ("byval", Token.BYVAL);
+ keywords.Add ("call", Token.CALL);
+ keywords.Add ("case", Token.CASE);
+ keywords.Add ("catch", Token.CATCH);
+ keywords.Add ("cbool", Token.CBOOL);
+ keywords.Add ("cbyte", Token.CBYTE);
+ keywords.Add ("cchar", Token.CCHAR);
+ keywords.Add ("cdate", Token.CDATE);
+ keywords.Add ("cdec", Token.CDEC);
+ keywords.Add ("cdbl", Token.CDBL);
+ keywords.Add ("char", Token.CHAR);
+ keywords.Add ("cint", Token.CINT);
+ keywords.Add ("class", Token.CLASS);
+ keywords.Add ("clng", Token.CLNG);
+ keywords.Add ("cobj", Token.COBJ);
+ keywords.Add ("compare", Token.COMPARE); // Not a VB.NET Keyword
+ keywords.Add ("const", Token.CONST);
+ keywords.Add ("cshort", Token.CSHORT);
+ keywords.Add ("csng", Token.CSNG);
+ keywords.Add ("cstr", Token.CSTR);
+ keywords.Add ("ctype", Token.CTYPE);
+ keywords.Add ("date", Token.DATE);
+ keywords.Add ("decimal", Token.DECIMAL);
+ keywords.Add ("declare", Token.DECLARE);
+ keywords.Add ("default", Token.DEFAULT);
+ keywords.Add ("delegate", Token.DELEGATE);
+ keywords.Add ("dim", Token.DIM);
+ keywords.Add ("directcast", Token.DIRECTCAST);
+ keywords.Add ("do", Token.DO);
+ keywords.Add ("double", Token.DOUBLE);
+ keywords.Add ("each", Token.EACH);
+ keywords.Add ("else", Token.ELSE);
+ keywords.Add ("elseif", Token.ELSEIF);
+ keywords.Add ("end", Token.END);
+ keywords.Add ("endif", Token.ENDIF); // An unused VB.NET keyword
+ keywords.Add ("enum", Token.ENUM);
+ keywords.Add ("erase", Token.ERASE);
+ keywords.Add ("error", Token.ERROR);
+ keywords.Add ("event", Token.EVENT);
+ keywords.Add ("exit", Token.EXIT);
+ keywords.Add ("explicit", Token.EXPLICIT); // Not a VB.NET keyword
+ keywords.Add ("false", Token.FALSE);
+ keywords.Add ("finally", Token.FINALLY);
+ keywords.Add ("for", Token.FOR);
+ keywords.Add ("friend", Token.FRIEND);
+ keywords.Add ("function", Token.FUNCTION);
+ keywords.Add ("get", Token.GET);
+ keywords.Add ("gettype", Token.GETTYPE);
+ keywords.Add ("gosub", Token.GOSUB); // An unused VB.NET keyword
+ keywords.Add ("goto", Token.GOTO);
+ keywords.Add ("handles", Token.HANDLES);
+ keywords.Add ("if", Token.IF);
+ keywords.Add ("implements", Token.IMPLEMENTS);
+ keywords.Add ("imports", Token.IMPORTS);
+ keywords.Add ("in", Token.IN);
+ keywords.Add ("inherits", Token.INHERITS);
+ keywords.Add ("integer", Token.INTEGER);
+ keywords.Add ("interface", Token.INTERFACE);
+ keywords.Add ("is", Token.IS);
+ keywords.Add ("let ", Token.LET ); // An unused VB.NET keyword
+ keywords.Add ("lib ", Token.LIB );
+ keywords.Add ("like ", Token.LIKE );
+ keywords.Add ("long", Token.LONG);
+ keywords.Add ("loop", Token.LOOP);
+ keywords.Add ("me", Token.ME);
+ keywords.Add ("mod", Token.MOD);
+ keywords.Add ("module", Token.MODULE);
+ keywords.Add ("mustinherit", Token.MUSTINHERIT);
+ keywords.Add ("mustoverride", Token.MUSTOVERRIDE);
+ keywords.Add ("mybase", Token.MYBASE);
+ keywords.Add ("myclass", Token.MYCLASS);
+ keywords.Add ("namespace", Token.NAMESPACE);
+ keywords.Add ("new", Token.NEW);
+ keywords.Add ("next", Token.NEXT);
+ keywords.Add ("not", Token.NOT);
+ keywords.Add ("nothing", Token.NOTHING);
+ keywords.Add ("notinheritable", Token.NOTINHERITABLE);
+ keywords.Add ("notoverridable", Token.NOTOVERRIDABLE);
+ keywords.Add ("object", Token.OBJECT);
+ keywords.Add ("off", Token.OFF); // Not a VB.NET Keyword
+ keywords.Add ("on", Token.ON);
+ keywords.Add ("option", Token.OPTION);
+ keywords.Add ("optional", Token.OPTIONAL);
+ keywords.Add ("or", Token.OR);
+ keywords.Add ("orelse", Token.ORELSE);
+ keywords.Add ("overloads", Token.OVERLOADS);
+ keywords.Add ("overridable", Token.OVERRIDABLE);
+ keywords.Add ("overrides", Token.OVERRIDES);
+ keywords.Add ("paramarray", Token.PARAM_ARRAY);
+ keywords.Add ("preserve", Token.PRESERVE);
+ keywords.Add ("private", Token.PRIVATE);
+ keywords.Add ("property", Token.PROPERTY);
+ keywords.Add ("protected", Token.PROTECTED);
+ keywords.Add ("public", Token.PUBLIC);
+ keywords.Add ("raiseevent", Token.RAISEEVENT);
+ keywords.Add ("readonly", Token.READONLY);
+ keywords.Add ("redim", Token.REDIM);
+ keywords.Add ("rem", Token.REM);
+ keywords.Add ("removehandler", Token.REMOVEHANDLER);
+ keywords.Add ("resume", Token.RESUME);
+ keywords.Add ("return", Token.RETURN);
+ keywords.Add ("select", Token.SELECT);
+ keywords.Add ("set", Token.SET);
+ keywords.Add ("shadows", Token.SHADOWS);
+ keywords.Add ("shared", Token.SHARED);
+ keywords.Add ("short", Token.SHORT);
+ keywords.Add ("single", Token.SINGLE);
+ keywords.Add ("sizeof", Token.SIZEOF); // Not a VB.NET Keyword
+ keywords.Add ("static", Token.STATIC);
+ keywords.Add ("step", Token.STEP);
+ keywords.Add ("stop", Token.STOP);
+ keywords.Add ("strict", Token.STRICT); // Not a VB.NET Keyword
+ keywords.Add ("string", Token.STRING);
+ keywords.Add ("structure", Token.STRUCTURE);
+ keywords.Add ("sub", Token.SUB);
+ keywords.Add ("synclock", Token.SYNCLOCK);
+ keywords.Add ("text", Token.TEXT); // Not a VB.NET Keyword
+ keywords.Add ("then", Token.THEN);
+ keywords.Add ("throw", Token.THROW);
+ keywords.Add ("to", Token.TO);
+ keywords.Add ("true", Token.TRUE);
+ keywords.Add ("try", Token.TRY);
+ keywords.Add ("typeof", Token.TYPEOF);
+ keywords.Add ("unicode", Token.UNICODE);
+ keywords.Add ("until", Token.UNTIL);
+ keywords.Add ("variant", Token.VARIANT); // An unused VB.NET keyword
+ keywords.Add ("wend", Token.WEND); // An unused VB.NET keyword
+ keywords.Add ("when", Token.WHEN);
+ keywords.Add ("while", Token.WHILE);
+ keywords.Add ("with", Token.WITH);
+ keywords.Add ("withevents", Token.WITHEVENTS);
+ keywords.Add ("writeonly", Token.WRITEONLY);
+ keywords.Add ("xor", Token.XOR);
+
+ /*
+
+ if (Parser.UseExtendedSyntax){
+ keywords.Add ("yield", Token.YIELD);
+ }
+ */
+
+
+ }
+
+ static Tokenizer ()
+ {
+ initTokens ();
+ csharp_format_info = new NumberFormatInfo ();
+ csharp_format_info.CurrencyDecimalSeparator = ".";
+ styles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint;
+ }
+
+ public Tokenizer (SeekableStreamReader input, SourceFile fname, ArrayList defines)
+ {
+ this.ref_name = fname;
+ this.file_name = fname;
+
+ reader = input;
+
+ // putback an EOL at the beginning of a stream. This is a convenience that
+ // allows pre-processor directives to be added to the beginning of a vb file.
+ putback('\n');
+ }
+
+ bool is_keyword (string name)
+ {
+ bool res;
+ name = name.ToLower();
+
+ res = keywords.Contains(name);
+ if ((name == "GET" || name == "SET") && handle_get_set == false)
+ return false;
+ return res;
+ }
+
+ int getKeyword (string name)
+ {
+ return (int) (keywords [name.ToLower()]);
+ }
+
+ public Location Location {
+ get {
+ return new Location (ref_line);
+ }
+ }
+
+ public bool PropertyParsing {
+ get {
+ return handle_get_set;
+ }
+
+ set {
+ handle_get_set = value;
+ }
+ }
+
+ static bool is_identifier_start_character (char c)
+ {
+ return Char.IsLetter (c) || c == '_' ;
+ }
+
+ static bool is_identifier_part_character (char c)
+ {
+ return (Char.IsLetter (c) || Char.IsDigit (c) || c == '_');
+ }
+
+ public static bool IsValidIdentifier (string s)
+ {
+ if (s == null || s.Length == 0)
+ return false;
+
+ if (!is_identifier_start_character (s [0]))
+ return false;
+
+ for (int i = 1; i < s.Length; i ++)
+ if (! is_identifier_part_character (s [i]))
+ return false;
+
+ return true;
+ }
+
+ int is_punct (char c, ref bool doread)
+ {
+ int d;
+ int t;
+
+ doread = false;
+
+ error_details = c.ToString();
+
+ d = peekChar ();
+
+ switch (c){
+ case '[':
+ return Token.OPEN_BRACKET;
+ case ']':
+ return Token.CLOSE_BRACKET;
+ case '{':
+ return Token.OPEN_BRACE;
+ case '}':
+ return Token.CLOSE_BRACE;
+ case '(':
+ return Token.OPEN_PARENS;
+ case ')':
+ return Token.CLOSE_PARENS;
+ case ',':
+ return Token.COMMA;
+ case '?':
+ return Token.INTERR;
+ case '!':
+ if (is_identifier_start_character((char)d) || cant_have_a_type_character)
+ return Token.EXCLAMATION;
+ return Token.SINGLETYPECHAR;
+ case '$':
+ if (cant_have_a_type_character)
+ return Token.ERROR;
+ return Token.DOLAR_SIGN;
+ case '@':
+ if (cant_have_a_type_character)
+ return Token.ERROR;
+ return Token.AT_SIGN;
+ case '%':
+ if (cant_have_a_type_character)
+ return Token.ERROR;
+ return Token.PERCENT;
+ case '#':
+ if(tokens_seen)
+ {
+ if (cant_have_a_type_character)
+ return ExtractDateTimeLiteral();
+ else
+ return Token.NUMBER_SIGN;
+ }
+ else
+ {
+ tokens_seen = true;
+ return Token.HASH;
+ }
+ case '&':
+ if (!cant_have_a_type_character)
+ return Token.LONGTYPECHAR;
+ t = handle_integer_literal_in_other_bases(d);
+ if (t == Token.NONE) {
+ t = Token.OP_CONCAT;
+ }
+ return t;
+ }
+
+ if (c == '+'){
+ if (d == '+')
+ t = Token.OP_INC;
+ else
+ return Token.PLUS;
+ doread = true;
+ return t;
+ }
+ if (c == '-'){
+ return Token.MINUS;
+ }
+
+ if (c == '='){
+ return Token.ASSIGN;
+ }
+
+ if (c == '*'){
+ return Token.STAR;
+ }
+
+ if (c == '/'){
+ return Token.DIV;
+ }
+
+ if (c == '\\'){
+ return Token.OP_IDIV;
+ }
+
+ if (c == '^'){
+ return Token.OP_EXP;
+ }
+
+ if (c == '<'){
+ if (d == '>')
+ {
+ doread = true;
+ return Token.OP_NE;
+ }
+ if (d == '='){
+ doread = true;
+ return Token.OP_LE;
+ }
+ if (d == '<')
+ {
+ doread = true;
+ return Token.OP_SHIFT_LEFT;
+ }
+ return Token.OP_LT;
+ }
+
+ if (c == '>'){
+ if (d == '='){
+ doread = true;
+ return Token.OP_GE;
+ }
+ if (d == '>')
+ {
+ doread = true;
+ return Token.OP_SHIFT_RIGHT;
+ }
+ return Token.OP_GT;
+ }
+
+ if (c == ':'){
+ if (d == '='){
+ doread = true;
+ return Token.ATTR_ASSIGN;
+ }
+ return Token.COLON;
+ }
+
+ return Token.ERROR;
+ }
+
+ bool decimal_digits (int c)
+ {
+ int d;
+ bool seen_digits = false;
+
+ if (c != -1)
+ number.Append ((char) c);
+
+ while ((d = peekChar ()) != -1){
+ if (Char.IsDigit ((char)d)){
+ number.Append ((char) d);
+ getChar ();
+ seen_digits = true;
+ } else
+ break;
+ }
+ return seen_digits;
+ }
+
+
+ int real_type_suffix (int c)
+ {
+ int t;
+
+ switch (c){
+ case 'F': case 'f':
+ t = Token.LITERAL_SINGLE;
+ break;
+ case 'R': case 'r':
+ t = Token.LITERAL_DOUBLE;
+ break;
+ case 'D': case 'd':
+ t= Token.LITERAL_DECIMAL;
+ break;
+ default:
+ return Token.NONE;
+ }
+ getChar ();
+ return t;
+ }
+
+ int integer_type_suffix (int c)
+ {
+ int t;
+
+ try {
+
+ switch (c){
+ case 'S': case 's':
+ t = Token.LITERAL_INTEGER; // SHORT ?
+ val = ((IConvertible)val).ToInt16(null);
+ break;
+ case 'I': case 'i':
+ t = Token.LITERAL_INTEGER;
+ val = ((IConvertible)val).ToInt32(null);
+ break;
+ case 'L': case 'l':
+ t= Token.LITERAL_INTEGER; // LONG ?
+ val = ((IConvertible)val).ToInt64(null);
+ break;
+ default:
+ if ((long)val <= System.Int32.MaxValue &&
+ (long)val >= System.Int32.MinValue) {
+ val = ((IConvertible)val).ToInt32(null);
+ return Token.LITERAL_INTEGER;
+ } else {
+ val = ((IConvertible)val).ToInt64(null);
+ return Token.LITERAL_INTEGER; // LONG ?
+ }
+ }
+ getChar ();
+ return t;
+ } catch (Exception e) {
+ val = e.ToString();
+ return Token.ERROR;
+ }
+ }
+
+ int adjust_real (int t)
+ {
+ string s = number.ToString ();
+
+ switch (t){
+ case Token.LITERAL_DECIMAL:
+ val = new System.Decimal ();
+ val = System.Decimal.Parse (
+ s, styles, csharp_format_info);
+ break;
+ case Token.LITERAL_DOUBLE:
+ val = new System.Double ();
+ val = System.Double.Parse (
+ s, styles, csharp_format_info);
+ break;
+ case Token.LITERAL_SINGLE:
+ val = new System.Double ();
+ val = (float) System.Double.Parse (
+ s, styles, csharp_format_info);
+ break;
+
+ case Token.NONE:
+ val = new System.Double ();
+ val = System.Double.Parse (
+ s, styles, csharp_format_info);
+ t = Token.LITERAL_DOUBLE;
+ break;
+ }
+ return t;
+ }
+
+ long hex_digits ()
+ {
+ StringBuilder hexNumber = new StringBuilder ();
+
+ int d;
+
+ while ((d = peekChar ()) != -1){
+ char e = Char.ToUpper ((char) d);
+
+ if (Char.IsDigit (e) || (e >= 'A' && e <= 'F')){
+ hexNumber.Append (e);
+ getChar ();
+ } else
+ break;
+ }
+ return System.Int64.Parse (hexNumber.ToString(), NumberStyles.HexNumber);
+ }
+
+ long octal_digits ()
+ {
+ long valueToReturn = 0;
+
+ int d;
+
+ while ((d = peekChar ()) != -1){
+ char e = (char)d;
+ if (Char.IsDigit (e) && (e < '8')){
+ valueToReturn *= 8;
+ valueToReturn += (d - (int)'0');
+ getChar ();
+ } else
+ break;
+ }
+
+ return valueToReturn;
+ }
+
+ int handle_integer_literal_in_other_bases(int peek)
+ {
+ if (peek == 'h' || peek == 'H'){
+ getChar ();
+ val = hex_digits ();
+ return integer_type_suffix (peekChar ());
+ }
+
+ if (peek == 'o' || peek == 'O'){
+ getChar ();
+ val = octal_digits ();
+ return integer_type_suffix (peekChar ());
+ }
+
+ return Token.NONE;
+ }
+
+ //
+ // Invoked if we know we have .digits or digits
+ //
+ int is_number (int c)
+ {
+ bool is_real = false;
+ number = new StringBuilder ();
+ int type;
+
+ number.Length = 0;
+
+ if (Char.IsDigit ((char)c)){
+ decimal_digits (c);
+ c = peekChar ();
+ }
+
+ //
+ // We need to handle the case of
+ // "1.1" vs "1.ToString()" (LITERAL_SINGLE vs NUMBER DOT IDENTIFIER)
+ //
+ if (c == '.'){
+ if (decimal_digits (getChar())){
+ is_real = true;
+ c = peekChar ();
+ } else {
+ putback ('.');
+ number.Length -= 1;
+ val = System.Int64.Parse(number.ToString());
+ return integer_type_suffix('.');
+ }
+ }
+
+ if (c == 'e' || c == 'E'){
+ is_real = true;
+ number.Append ("e");
+ getChar ();
+
+ c = peekChar ();
+ if (c == '+'){
+ number.Append ((char) c);
+ getChar ();
+ c = peekChar ();
+ } else if (c == '-'){
+ number.Append ((char) c);
+ getChar ();
+ c = peekChar ();
+ }
+ decimal_digits (-1);
+ c = peekChar ();
+ }
+
+ type = real_type_suffix (c);
+ if (type == Token.NONE && !is_real){
+ val = System.Int64.Parse(number.ToString());
+ return integer_type_suffix(c);
+ }
+
+ return adjust_real (type);
+ }
+
+ int getChar ()
+ {
+ if (putback_char != -1){
+ int x = putback_char;
+ putback_char = -1;
+
+ return x;
+ }
+ return reader.Read ();
+ }
+
+ int peekChar ()
+ {
+ if (putback_char != -1)
+ return putback_char;
+ return reader.Peek ();
+ }
+
+ void putback (int c)
+ {
+ if (putback_char != -1)
+ throw new Exception ("This should not happen putback on putback");
+ putback_char = c;
+ }
+
+ public bool advance ()
+ {
+ return current_token != Token.EOF ;
+ }
+
+ public Object Value {
+ get {
+ return val;
+ }
+ }
+
+ public Object value ()
+ {
+ return val;
+ }
+
+ private bool IsEOL(int currentChar)
+ {
+ bool retVal;
+
+ if (currentChar == 0x0D) {
+ if (peekChar() == 0x0A) // if it is a CR-LF pair consume LF also
+ getChar();
+
+ retVal = true;
+ }
+ else {
+ retVal = (currentChar == -1 || currentChar == 0x0A || currentChar == 0x2028 || currentChar == 0x2029);
+ }
+
+ if(retVal) {
+ nextLine();
+ }
+
+ return retVal;
+ }
+
+ private int DropComments()
+ {
+ int d;
+ while (!IsEOL(d = getChar ()))
+ col++;
+
+ return Token.EOL;
+ }
+
+ public int token ()
+ {
+ int lastToken = current_token;
+ do
+ {
+ current_token = xtoken ();
+ if (current_token == 0)
+ return Token.EOF;
+ if (current_token == Token.REM)
+ current_token = DropComments();
+ } while (lastToken == Token.EOL && current_token == Token.EOL);
+
+ // Console.WriteLine ("Token = " + val);
+
+ return current_token;
+ }
+
+ private string GetIdentifier()
+ {
+ int c = getChar();
+ if (is_identifier_start_character ((char) c))
+ return GetIdentifier(c);
+ else
+ return null;
+ }
+
+ private string GetIdentifier(int c)
+ {
+ StringBuilder id = new StringBuilder ();
+
+ id.Append ((char) c);
+
+ while ((c = peekChar ()) != -1)
+ {
+ if (is_identifier_part_character ((char) c))
+ {
+ id.Append ((char)getChar ());
+ col++;
+ }
+ else
+ break;
+ }
+
+ cant_have_a_type_character = false;
+
+ return id.ToString();
+ }
+
+ private bool is_doublequote(int currentChar)
+ {
+ return (currentChar == '"' ||
+ currentChar == 0x201C || // unicode left double-quote character
+ currentChar == 0x201D); // unicode right double-quote character
+ }
+
+ private bool is_whitespace(int c)
+ {
+ return (c == ' ' || c == '\t' || c == '\v' || c == '\r' || c == 0xa0);
+ }
+
+ private bool tokens_seen = false;
+
+ private void nextLine()
+ {
+ cant_have_a_type_character = true;
+ line++;
+ ref_line++;
+ col = 0;
+ tokens_seen = false;
+ }
+
+ public int xtoken ()
+ {
+ int t;
+ bool doread = false;
+ int c;
+
+ val = null;
+ for (;(c = getChar ()) != -1; col++) {
+
+ // Handle line continuation character
+ if (c == '_')
+ {
+ int d = peekChar();
+ if (!is_identifier_part_character((char)d)) {
+ while ((c = getChar ()) != -1 && !IsEOL(c)) {}
+ c = getChar ();
+ }
+ }
+
+ // white space
+ if (is_whitespace(c)) {
+ // expand tabs for location
+ if (c == '\t')
+ col = (((col + ExpandedTabsSize) / ExpandedTabsSize) * ExpandedTabsSize) - 1;
+ cant_have_a_type_character = true;
+ continue;
+ }
+
+ // Handle line comments.
+ if (c == '\'')
+ return Token.REM;
+
+ // Handle EOL.
+ if (IsEOL(c))
+ {
+ if (current_token == Token.EOL) // if last token was also EOL keep skipping
+ continue;
+ return Token.EOL;
+ }
+
+ // Handle escaped identifiers
+ if (c == '[')
+ {
+ if ((val = GetIdentifier()) == null)
+ break;
+ if ((c = getChar()) != ']')
+ break;
+ tokens_seen = true;
+ return Token.IDENTIFIER;
+ }
+
+ // Handle unescaped identifiers
+ if (is_identifier_start_character ((char) c))
+ {
+ string id;
+ if ((id = GetIdentifier(c)) == null)
+ break;
+ val = id;
+ tokens_seen = true;
+ if (is_keyword(id) && (current_token != Token.DOT))
+ return getKeyword(id);
+ return Token.IDENTIFIER;
+ }
+
+ // Treat string literals
+ if (is_doublequote(c)) {
+ cant_have_a_type_character = true;
+ return ExtractStringOrCharLiteral(c);
+ }
+
+ // handle numeric literals
+ if (c == '.')
+ {
+ cant_have_a_type_character = true;
+ tokens_seen = true;
+ if (Char.IsDigit ((char) peekChar ()))
+ return is_number (c);
+ return Token.DOT;
+ }
+
+ if (Char.IsDigit ((char) c))
+ {
+ cant_have_a_type_character = true;
+ tokens_seen = true;
+ return is_number (c);
+ }
+
+ if ((t = is_punct ((char)c, ref doread)) != Token.ERROR) {
+ cant_have_a_type_character = true;
+
+ if (t == Token.NONE)
+ continue;
+
+ if (doread){
+ getChar ();
+ col++;
+ }
+ tokens_seen = true;
+ return t;
+ }
+
+ error_details = ((char)c).ToString ();
+ return Token.ERROR;
+ }
+
+ if (current_token != Token.EOL) // if last token wasn't EOL send it before EOF
+ return Token.EOL;
+
+ return Token.EOF;
+ }
+
+ private int ExtractDateTimeLiteral()
+ {
+ int c;
+
+ StringBuilder sb = new StringBuilder();
+ for (;(c = getChar ()) != -1; col++)
+ {
+ if (c == '#') {
+ val = ParseDateLiteral(sb);
+ return Token.LITERAL_DATE;
+ }
+ if (IsEOL(c)) {
+ break;
+ }
+ if (c == '-')
+ c = '/';
+ sb.Append((char)c);
+ }
+ return Token.ERROR;
+ }
+
+ private int ExtractStringOrCharLiteral(int c)
+ {
+ StringBuilder s = new StringBuilder ();
+
+ tokens_seen = true;
+
+ while ((c = getChar ()) != -1){
+ if (is_doublequote(c)){
+ if (is_doublequote(peekChar()))
+ getChar();
+ else {
+ //handle Char Literals
+ if (peekChar() == 'C' || peekChar() == 'c') {
+ getChar();
+ if (s.Length == 1) {
+ val = s[0];
+ return Token.LITERAL_CHARACTER;
+ } else {
+ val = "Incorrect length for a character literal";
+ return Token.ERROR;
+ }
+ } else {
+ val = s.ToString ();
+ return Token.LITERAL_STRING;
+ }
+ }
+ }
+
+ if (IsEOL(c)) {
+ return Token.ERROR;
+ }
+
+ s.Append ((char) c);
+ }
+
+ return Token.ERROR;
+ }
+
+ static IFormatProvider enUSculture = new CultureInfo("en-US", true);
+
+ private DateTime ParseDateLiteral(StringBuilder value)
+ {
+ try
+ {
+ return DateTime.Parse(value.ToString(),
+ enUSculture,
+ DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AllowWhiteSpaces);
+ }
+ catch (FormatException ex)
+ {
+ //TODO: What is the correct error number and message?
+ Report.Error (1, Location, string.Format("Invalid date literal '{0}'", value.ToString())
+ + Environment.NewLine + ex.ToString());
+ }
+ catch (Exception)
+ {
+ Report.Error (1, Location, "Error parsing date literal"); //TODO: What is the correct error number and message?
+ }
+ return new DateTime();
+ }
+
+ public void PositionCursorAtNextPreProcessorDirective()
+ {
+ int t;
+
+ for(t = token(); t != Token.HASH && t != Token.EOF; t = token());
+
+ if(t == Token.EOF)
+ throw new ApplicationException("Unexpected EOF while looking for a pre-processor directive");
+
+ if(t == Token.HASH) {
+ tokens_seen = false;
+ putback('#');
+ }
+ }
+
+ public void cleanup ()
+ {
+ // FIXME;
+ }
+
+ public static void Cleanup ()
+ {
+ }
+
+ }
+}
--- /dev/null
+//
+// 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 WRITEONLY = 0x04000;
+ public const int SHADOWS = 0x08000;
+ public const int DEFAULT = 0x10000;
+ public const int NONVIRTUAL= 0x20000;
+ private const int TOP = 0x20000;
+
+ //
+ // We use this internally to flag that the method contains an iterator
+ //
+ public const int METHOD_YIELDS = 0x8000;
+ public const int METHOD_GENERIC = 0x10000;
+
+ public const int Accessibility =
+ PUBLIC | PROTECTED | INTERNAL | PRIVATE;
+ public const int AllowedExplicitImplFlags =
+ UNSAFE | EXTERN;
+
+ 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;
+ case Modifiers.UNSAFE:
+ s = "unsafe"; 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.UserDefinedStaticConstructor &&
+ (caller.Kind != Kind.Interface))
+ 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 = MethodAttributes.HideBySig;
+
+ 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;
+ }
+ if ((mod_flags & SEALED) != 0)
+ ma |= MethodAttributes.Final;
+
+ if ((mod_flags & VIRTUAL) != 0)
+ ma |= MethodAttributes.Virtual;
+
+ if ((mod_flags & OVERRIDE) != 0)
+ ma |= MethodAttributes.Virtual;
+ else {
+ if ((ma & MethodAttributes.Virtual) != 0)
+ ma |= MethodAttributes.NewSlot;
+ }
+
+ 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");
+ }
+ }
+}
--- /dev/null
+//
+// module.cs: Module handler
+//
+// Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2002 Rafael Teixeira
+//
+using System;
+using System.Collections;
+using System.Diagnostics.SymbolStore;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using Mono.CSharp ;
+
+namespace Mono.CSharp
+{
+ public class Utils
+ {
+ public static void AddSpecializedAttribute(ref Attributes attrs, string attributeName, ArrayList args, Location loc)
+ {
+ Mono.CSharp.Attribute specialAttr = new Mono.CSharp.Attribute(null, attributeName, args, loc); // Sudha : passed null for target
+ ArrayList al = new ArrayList();
+ al.Add(specialAttr);
+ if (attrs == null) {
+ attrs = new Attributes(al);
+ } else {
+ attrs.AddAttributes(al);
+ }
+ }
+ }
+
+ public class VBModule : Class
+ {
+ public new const int AllowedModifiers = Modifiers.PUBLIC |Modifiers.INTERNAL;
+
+ public VBModule (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
+ Attributes attrs, Location l)
+ : base (ns, parent, name, 0, attrs, l)
+
+ {
+ if (parent.Parent != null)
+ Report.Error (30617, l,
+ "'Module' statements can occur only at file or namespace level");
+
+ // overwrite ModFlags
+ this.ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.INTERNAL, l);
+
+ // add specialized attribute
+ Utils.AddSpecializedAttribute(ref attributes, "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute", null, l);
+ }
+
+
+ public override TypeAttributes TypeAttr
+ {
+ get {
+ return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.Sealed;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// namespace.cs: Tracks namespaces
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+using System;
+using System.Collections;
+
+namespace Mono.CSharp {
+
+ /// <summary>
+ /// Keeps track of the namespaces defined in the C# code.
+ /// </summary>
+ public class Namespace : IAlias {
+ static ArrayList all_namespaces = new ArrayList ();
+ static Hashtable namespaces_map = new Hashtable ();
+
+ Namespace parent;
+ string fullname;
+ ArrayList entries;
+ Hashtable namespaces;
+ Hashtable defined_names;
+
+ /// <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.parent = parent;
+
+ string pname = parent != null ? parent.Name : "";
+
+ if (pname == "")
+ fullname = name;
+ else
+ fullname = parent.Name + "." + name;
+
+ entries = new ArrayList ();
+ namespaces = new Hashtable ();
+ defined_names = new Hashtable ();
+
+ all_namespaces.Add (this);
+ if (namespaces_map.Contains (fullname))
+ return;
+ namespaces_map [fullname] = true;
+ }
+
+ public static bool IsNamespace (string name)
+ {
+ return namespaces_map [name] != null;
+ }
+
+ 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 IAlias Lookup (DeclSpace ds, string name, Location loc)
+ {
+ IAlias o = Lookup (name);
+
+ Type t;
+ DeclSpace tdecl = o as DeclSpace;
+ if (tdecl != null) {
+ t = tdecl.DefineType ();
+ if (t == null)
+ return null;
+
+ if ((ds == null) || ds.CheckAccessLevel (t))
+ return new TypeExpression (t, loc);
+ }
+
+ Namespace ns = GetNamespace (name, false);
+ if (ns != null)
+ return ns;
+
+ t = TypeManager.LookupType (DeclSpace.MakeFQN (fullname, name));
+ if ((t == null) || ((ds != null) && !ds.CheckAccessLevel (t)))
+ return null;
+
+ return new TypeExpression (t, loc);
+ }
+
+ public void AddNamespaceEntry (NamespaceEntry entry)
+ {
+ entries.Add (entry);
+ }
+
+ public void DefineName (string name, IAlias o)
+ {
+ defined_names.Add (name, o);
+ }
+
+ public IAlias Lookup (string name)
+ {
+ return (IAlias) defined_names [name];
+ }
+
+ 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);
+ }
+
+ bool IAlias.IsType {
+ get { return false; }
+ }
+
+ TypeExpr IAlias.ResolveAsType (EmitContext ec)
+ {
+ throw new InvalidOperationException ();
+ }
+ }
+
+ 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;
+
+ object resolved = NamespaceEntry.LookupForUsing (Name, Location);
+ resolved_ns = resolved as Namespace;
+ return resolved_ns;
+ }
+ }
+
+ public class AliasEntry {
+ public readonly string Name;
+ public readonly MemberName Alias;
+ public readonly NamespaceEntry NamespaceEntry;
+ public readonly Location Location;
+
+ public AliasEntry (NamespaceEntry entry, string name, MemberName alias, Location loc)
+ {
+ Name = name;
+ Alias = alias;
+ NamespaceEntry = entry;
+ Location = loc;
+ }
+
+ IAlias resolved;
+
+ public IAlias Resolve ()
+ {
+ if (resolved != null)
+ return resolved;
+
+ //
+ // GENERICS: Cope with the expression and not with the string
+ // this will fail with `using A = Stack<int>'
+ //
+
+ string alias = Alias.GetTypeName ();
+
+ resolved = NamespaceEntry.LookupForUsing (alias, Location);
+ if (resolved == null)
+ return null;
+
+ if (resolved.IsType)
+ resolved = new TypeAliasExpression (
+ resolved, Alias.TypeArguments, Location);
+
+ return resolved;
+ }
+ }
+
+ public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, Location loc)
+ : this (parent, file, name, false, loc)
+ { }
+
+ protected NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, bool is_implicit, Location loc)
+ {
+ 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, loc);
+ else
+ implicit_parent = parent;
+
+ this.FullName = ns.Name;
+ }
+
+ static int next_id = 0;
+ public readonly string FullName;
+ public readonly int ID;
+ public readonly bool IsImplicit;
+
+ public Namespace NS {
+ get {
+ return ns;
+ }
+ }
+
+ public NamespaceEntry Parent {
+ get {
+ return parent;
+ }
+ }
+
+ public NamespaceEntry ImplicitParent {
+ get {
+ return implicit_parent;
+ }
+ }
+
+ public void DefineName (string name, IAlias o)
+ {
+ ns.DefineName (name, o);
+ }
+
+ /// <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 == FullName)
+ return;
+
+ if (using_clauses == null)
+ using_clauses = new ArrayList ();
+
+ foreach (UsingEntry old_entry in using_clauses) {
+ if (old_entry.Name == ns) {
+ if (RootContext.WarningLevel >= 3)
+ Report.Warning (105, loc, "The using directive for '{0}' appeared previously in this namespace", ns);
+ return;
+ }
+ }
+
+ UsingEntry ue = new UsingEntry (this, ns, loc);
+ using_clauses.Add (ue);
+ }
+
+ public void UsingAlias (string name, MemberName alias, Location loc)
+ {
+ if (DeclarationFound){
+ Report.Error (1529, loc, "A using clause must precede all other namespace elements");
+ return;
+ }
+
+ if (aliases == null)
+ aliases = new Hashtable ();
+
+ if (aliases.Contains (name)){
+ Report.Error (1537, loc, "The using alias `" + name +
+ "' appeared previously in this namespace");
+ return;
+ }
+
+ aliases [name] = new AliasEntry (this, name, alias, 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 IAlias LookupAlias (string alias)
+ {
+ AliasEntry entry = GetAliasEntry (alias);
+
+ if (entry == null)
+ return null;
+
+ return entry.Resolve ();
+ }
+
+ //
+ // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ public IAlias LookupForUsing (string dotted_name, Location loc)
+ {
+ int pos = dotted_name.IndexOf ('.');
+ string simple_name = dotted_name;
+ string rest = null;
+ if (pos >= 0) {
+ simple_name = dotted_name.Substring (0, pos);
+ rest = dotted_name.Substring (pos + 1);
+ }
+
+ IAlias o = NS.Lookup (null, simple_name, loc);
+ if (o == null && ImplicitParent != null)
+ o = ImplicitParent.LookupNamespaceOrType (null, simple_name, loc);
+
+ if (o == null || rest == null)
+ return o;
+
+ Namespace ns = o as Namespace;
+ if (ns != null)
+ return ns.Lookup (null, rest, loc);
+
+ Type nested = TypeManager.LookupType (o.Name + "." + rest);
+ if (nested == null)
+ return null;
+
+ return new TypeExpression (nested, loc);
+ }
+
+ public IAlias LookupNamespaceOrType (DeclSpace ds, string name, Location loc)
+ {
+ IAlias resolved = null;
+ for (NamespaceEntry curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc)) != null)
+ break;
+ }
+ return resolved;
+ }
+
+ private IAlias Lookup (DeclSpace ds, string name, Location loc)
+ {
+ IAlias o;
+ Namespace ns;
+
+ //
+ // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
+ //
+ // FIXME: Remove this block. Only simple names should come here.
+ // The bug: The loop in LookupNamespaceOrType continues if
+ // the lookup for N succeeds but the nested lookup for I fails.
+ // This is one part of #52697.
+ //
+ int pos = name.IndexOf ('.');
+ if (pos >= 0) {
+ string first = name.Substring (0, pos);
+ string last = name.Substring (pos + 1);
+
+ o = Lookup (ds, first, loc);
+ if (o == null)
+ return null;
+
+ ns = o as Namespace;
+ if (ns != null) {
+ o = ns.Lookup (ds, last, loc);
+ return o;
+ }
+
+ Type nested = TypeManager.LookupType (o.Name + "." + last);
+ if ((nested == null) || ((ds != null) && !ds.CheckAccessLevel (nested)))
+ return null;
+
+ return new TypeExpression (nested, loc);
+ }
+
+ //
+ // Check whether it's in the namespace.
+ //
+ o = NS.Lookup (ds, name, loc);
+ if (o != null)
+ return o;
+
+ //
+ // Check aliases.
+ //
+ AliasEntry entry = GetAliasEntry (name);
+ if (entry != null) {
+ IAlias alias = entry.Resolve ();
+ if (alias != null)
+ return alias;
+ }
+
+ if (name.IndexOf ('.') > 0)
+ return null;
+
+ //
+ // Check using entries.
+ //
+ IAlias t = null, match = null;
+ foreach (Namespace using_ns in GetUsingTable ()) {
+ match = using_ns.Lookup (ds, name, loc);
+ if ((match != null) && match.IsType){
+ if (t != null) {
+ DeclSpace.Error_AmbiguousTypeReference (loc, name, t.Name, match.Name);
+ return null;
+ } else {
+ t = match;
+ }
+ }
+ }
+
+ return t;
+ }
+
+ // Our cached computation.
+ Namespace [] namespace_using_table;
+ public Namespace[] GetUsingTable ()
+ {
+ if (namespace_using_table != null)
+ return namespace_using_table;
+
+ if (using_clauses == null)
+ return new Namespace [0];
+
+ ArrayList list = new ArrayList (using_clauses.Count);
+
+ foreach (UsingEntry ue in using_clauses) {
+ Namespace using_ns = ue.Resolve ();
+ if (using_ns == null)
+ continue;
+
+ list.Add (using_ns);
+ }
+
+ namespace_using_table = new Namespace [list.Count];
+ list.CopyTo (namespace_using_table, 0);
+ return namespace_using_table;
+ }
+
+ 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;
+ if (file.SourceFileEntry == null)
+ return;
+
+ symfile_id = symwriter.DefineNamespace (
+ ns.Name, file.SourceFileEntry, using_list, parent_id);
+ }
+
+ public int SymbolFileID {
+ get {
+ return symfile_id;
+ }
+ }
+
+ static void MsgtryRef (string s)
+ {
+ Console.WriteLine (" Try using -r:" + s);
+ }
+
+ static void MsgtryPkg (string s)
+ {
+ Console.WriteLine (" Try using -pkg:" + s);
+ }
+
+ protected void error246 (Location loc, string name)
+ {
+ Report.Error (246, loc, "The namespace `" + name +
+ "' can not be found (missing assembly reference?)");
+
+ switch (name) {
+ case "Gtk": case "GtkSharp":
+ MsgtryPkg ("gtk-sharp");
+ break;
+
+ case "Gdk": case "GdkSharp":
+ MsgtryPkg ("gdk-sharp");
+ break;
+
+ case "Glade": case "GladeSharp":
+ MsgtryPkg ("glade-sharp");
+ break;
+
+ case "System.Drawing":
+ case "System.Web.Services":
+ case "System.Web":
+ case "System.Data":
+ case "System.Windows.Forms":
+ MsgtryRef (name);
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Used to validate that all the using clauses are correct
+ /// after we are finished parsing all the files.
+ /// </summary>
+ public void VerifyUsing ()
+ {
+ TypeContainer dummy = new RootTypes ();
+ EmitContext ec = new EmitContext (
+ dummy, Location.Null, null, null, 0, false);
+
+ if (using_clauses != null){
+ foreach (UsingEntry ue in using_clauses){
+ if (ue.Resolve () != null)
+ continue;
+
+ if (LookupForUsing (ue.Name, ue.Location) == null)
+ error246 (ue.Location, ue.Name);
+ else
+ Report.Error (138, ue.Location, "The using keyword only lets you specify a namespace, " +
+ "`" + ue.Name + "' is a class not a namespace.");
+
+ }
+ }
+
+ if (aliases != null){
+ foreach (DictionaryEntry de in aliases){
+ AliasEntry entry = (AliasEntry) de.Value;
+
+ IAlias alias = entry.Resolve ();
+ if (alias != null) {
+ if (alias.IsType)
+ alias.ResolveAsType (ec);
+
+ continue;
+ }
+
+ error246 (entry.Location, entry.Alias.GetTypeName ());
+ }
+ }
+ }
+
+ public override string ToString ()
+ {
+ if (NS == Namespace.Root)
+ return "NamespaceEntry (<root>)";
+ else
+ return String.Format ("NamespaceEntry ({0},{1},{2})", FullName, IsImplicit, ID);
+ }
+ }
+}
--- /dev/null
+//
+// 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>
+ /// Abstract Base class for parameters of a method.
+ /// </summary>
+ public abstract class ParameterBase : Attributable {
+
+ protected ParameterBuilder builder;
+
+ public ParameterBase (Attributes attrs)
+ : base (attrs)
+ {
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.marshal_as_attr_type) {
+ UnmanagedMarshal marshal = a.GetMarshal (this);
+ if (marshal != null) {
+ builder.SetMarshal (marshal);
+ }
+ return;
+ }
+
+ if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
+ a.Error_InvalidSecurityParent ();
+ return;
+ }
+
+ builder.SetCustomAttribute (cb);
+ }
+
+ public override bool IsClsCompliaceRequired(DeclSpace ds)
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Class for applying custom attributes on the return type
+ /// </summary>
+ public class ReturnParameter: ParameterBase {
+ public ReturnParameter (MethodBuilder mb, Location location):
+ base (null)
+ {
+ try {
+ builder = mb.DefineParameter (0, ParameterAttributes.None, "");
+ }
+ catch (ArgumentOutOfRangeException) {
+ Report.Warning (-28, location, "The Microsoft .NET Runtime 1.x does not permit setting custom attributes on the return type");
+ }
+ }
+
+ public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+ {
+ // This occurs after Warning -28
+ if (builder == null)
+ return;
+
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.ReturnValue;
+ }
+ }
+
+ /// <summary>
+ /// Is never called
+ /// </summary>
+ public override string[] ValidAttributeTargets {
+ get {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class for applying custom attributes on the implicit parameter type
+ /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
+ /// </summary>
+ public class ImplicitParameter: ParameterBase {
+ public ImplicitParameter (MethodBuilder mb):
+ base (null)
+ {
+ builder = mb.DefineParameter (1, ParameterAttributes.None, "");
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Parameter;
+ }
+ }
+
+ /// <summary>
+ /// Is never called
+ /// </summary>
+ public override string[] ValidAttributeTargets {
+ get {
+ return null;
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Represents a single method parameter
+ /// </summary>
+
+ //TODO: Add location member to this or base class for better error location and all methods simplification.
+ public class Parameter : ParameterBase {
+ [Flags]
+ public enum Modifier : byte {
+ NONE = 0,
+ VAL = 0,
+ REF = 1,
+ OUT = 2,
+ PARAMS = 4,
+ // This is a flag which says that it's either REF or OUT.
+ ISBYREF = 8,
+ ARGLIST = 16,
+ // This value is changed from the one in mbas source code
+ OPTIONAL = 32
+ }
+
+ static string[] attribute_targets = new string [] { "param" };
+
+ public Expression TypeName;
+ public readonly Modifier ModFlags;
+ public readonly string Name;
+ GenericConstraints constraints;
+ Type parameter_type;
+
+ /* These two fields are mbas specific. The corresponding
+ changes need to be merged from mbas */
+
+ public readonly Expression ParameterInitializer;
+ public readonly bool IsOptional;
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
+ : base (attrs)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ ParameterInitializer = null;
+ IsOptional = false;
+ }
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi)
+ : base (attrs)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ ParameterInitializer = pi;
+ IsOptional = false;
+ }
+
+ public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Expression pi, bool opt)
+ : base (attrs)
+ {
+ Name = name;
+ ModFlags = mod;
+ TypeName = type;
+ ParameterInitializer = pi;
+ IsOptional = opt;
+ }
+
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
+ {
+ if (a.Type == TypeManager.param_array_type) {
+ Report.Error (674, a.Location, "Do not use 'System.ParamArrayAttribute'. Use the 'params' keyword instead");
+ return;
+ }
+ base.ApplyAttributeBuilder (a, cb);
+ }
+
+ // <summary>
+ // Resolve is used in method definitions
+ // </summary>
+ public bool Resolve (EmitContext ec, Location l)
+ {
+ TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return false;
+
+ TypeParameterExpr tparam = texpr as TypeParameterExpr;
+ if (tparam != null)
+ constraints = tparam.TypeParameter.Constraints;
+
+ parameter_type = texpr.Type;
+
+ if (parameter_type.IsAbstract && parameter_type.IsSealed) {
+ Report.Error (721, l, "'{0}': static types cannot be used as parameters", GetSignatureForError ());
+ return false;
+ }
+
+ if (parameter_type == TypeManager.void_type){
+ Report.Error (1536, l, "`void' parameter is not permitted");
+ return false;
+ }
+
+ if ((ModFlags & Parameter.Modifier.ISBYREF) != 0){
+ if (parameter_type == TypeManager.typed_reference_type ||
+ parameter_type == TypeManager.arg_iterator_type){
+ Report.Error (1601, l,
+ "out or ref parameter can not be of type TypedReference or ArgIterator");
+ 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 GenericConstraints GenericConstraints {
+ get {
+ return constraints;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ public static ParameterAttributes GetParameterAttributes (Modifier mod)
+ {
+ int flags = ((int) mod) & ~((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;
+ }
+
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Parameter;
+ }
+ }
+
+ /// <summary>
+ /// Returns the signature for this parameter evaluating it on the
+ /// @tc context
+ /// </summary>
+ public string GetSignature (EmitContext ec, Location loc)
+ {
+ if (parameter_type == null){
+ if (!Resolve (ec, loc))
+ return null;
+ }
+
+ return ExternalType ().FullName;
+ }
+
+ public string GetSignatureForError ()
+ {
+ string typeName;
+ if (parameter_type != null)
+ typeName = TypeManager.CSharpName (parameter_type);
+ else if (TypeName.Type != null)
+ typeName = TypeManager.CSharpName (TypeName.Type);
+ else
+ typeName = TypeName.ToString ();
+
+ switch (ModFlags & unchecked (~Modifier.ISBYREF)) {
+ case Modifier.OUT:
+ return "out " + typeName;
+ case Modifier.PARAMS:
+ return "params " + typeName;
+ case Modifier.REF:
+ return "ref " + typeName;
+ }
+ return typeName;
+ }
+
+ public void DefineParameter (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index, Location loc)
+ {
+ ParameterAttributes par_attr = Attributes;
+
+ if (mb == null)
+ builder = cb.DefineParameter (index, par_attr, Name);
+ else
+ builder = mb.DefineParameter (index, par_attr, Name);
+
+ if (OptAttributes != null) {
+ OptAttributes.Emit (ec, this);
+
+ if (par_attr == ParameterAttributes.Out){
+ if (OptAttributes.Contains (TypeManager.in_attribute_type, ec))
+ Report.Error (36, loc, "Can not use [In] attribute on out parameter");
+ }
+ }
+ }
+
+ public override string[] ValidAttributeTargets {
+ get {
+ return attribute_targets;
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Represents the methods parameters
+ /// </summary>
+ public class Parameters {
+ public Parameter [] FixedParameters;
+ public readonly Parameter ArrayParameter;
+ public readonly bool HasArglist;
+ 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;
+ }
+
+ public Parameters (Parameter [] fixed_parameters, bool has_arglist, Location l)
+ {
+ FixedParameters = fixed_parameters;
+ HasArglist = has_arglist;
+ 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 (EmitContext ec)
+ {
+ signature = "";
+ if (FixedParameters != null){
+ for (int i = 0; i < FixedParameters.Length; i++){
+ Parameter par = FixedParameters [i];
+
+ signature += par.GetSignature (ec, loc);
+ }
+ }
+ //
+ // Note: as per the spec, the `params' arguments (ArrayParameter)
+ // are not used in the signature computation for a method
+ //
+
+ }
+
+ void Error_DuplicateParameterName (string name)
+ {
+ Report.Error (
+ 100, loc, "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 @ec EmitContext
+ /// </summary>
+ public string GetSignature (EmitContext ec)
+ {
+ if (signature == null){
+ VerifyArgs ();
+ ComputeSignature (ec);
+ }
+
+ 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;
+ }
+
+ public Parameter GetParameterByName (string name)
+ {
+ int idx;
+
+ return GetParameterByName (name, out idx);
+ }
+
+ bool ComputeParameterTypes (EmitContext ec)
+ {
+ 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 (ec, loc))
+ t = p.ExternalType ();
+ else
+ failed = true;
+
+ types [i] = t;
+ i++;
+
+ }
+ }
+
+ if (extra > 0){
+ if (ArrayParameter.Resolve (ec, 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 (EmitContext ec)
+ {
+ bool old_type_resolving = ec.ResolvingTypeTree;
+ ec.ResolvingTypeTree = true;
+ bool retval = ComputeParameterTypes (ec);
+ ec.ResolvingTypeTree = old_type_resolving;
+ return retval;
+ }
+
+ /// <summary>
+ /// Returns the argument types as an array
+ /// </summary>
+ static Type [] no_types = new Type [0];
+
+ public Type [] GetParameterInfo (EmitContext ec)
+ {
+ if (types != null)
+ return types;
+
+ if (FixedParameters == null && ArrayParameter == null)
+ return no_types;
+
+ if (ComputeParameterTypes (ec) == 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 (EmitContext ec, 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 (ec) == 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 ()
+ {
+ if (HasArglist)
+ return CallingConventions.VarArgs;
+ else
+ return CallingConventions.Standard;
+ }
+
+ //
+ // 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,
+ Location loc) {
+ //
+ // Define each type attribute (in/out/ref) and
+ // the argument names.
+ //
+ int i = 0;
+
+ MethodBuilder mb = builder as MethodBuilder;
+ ConstructorBuilder cb = builder as ConstructorBuilder;
+
+ if (FixedParameters != null) {
+ for (i = 0; i < FixedParameters.Length; i++) {
+ FixedParameters [i].DefineParameter (ec, mb, cb, i + 1, loc);
+ }
+ }
+
+ if (ArrayParameter != null){
+ ParameterBuilder pb;
+ Parameter array_param = 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);
+ }
+ }
+
+ public Parameters Copy (Location l)
+ {
+ Parameters p = new Parameters (null, null, l);
+ p.FixedParameters = new Parameter[this.FixedParameters.Length];
+ this.FixedParameters.CopyTo (p.FixedParameters, 0);
+
+ return (p);
+ }
+
+ public void AppendParameter (Parameter p)
+ {
+ if (FixedParameters != null)
+ {
+ Parameter [] pa = new Parameter [FixedParameters.Length+1];
+ FixedParameters.CopyTo (pa, 0);
+ pa[FixedParameters.Length] = p;
+ FixedParameters = pa;
+ }
+ else
+ {
+ FixedParameters = new Parameter [1];
+ FixedParameters[0] = p;
+ }
+
+ }
+ }
+}
--- /dev/null
+
+namespace Compiler {
+
+ using System;
+
+ abstract public class Parser {
+ public string name;
+ public System.IO.Stream input;
+
+ public Parser (Mono.CSharp.Tree tree, string name, System.IO.Stream stream)
+ {
+ this.tree = tree;
+ this.name = name;
+ this.input = stream;
+ }
+
+ public string getName (){
+ return name;
+ }
+
+ abstract public int parse ();
+ }
+}
--- /dev/null
+//
+// 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;
+
+ //
+ // The name of the indexer (if it exists), precompute set/get, because
+ // they would be recomputed many times inside a loop later on.
+ //
+ public string set_indexer_name;
+ public string get_indexer_name;
+ }
+
+ 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)
+ {
+ MethodInfo mi = m as MethodInfo;
+ return (mi == null) ? false : mi.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.IsInterface)
+ continue;
+
+ if (t is TypeBuilder){
+ TypeContainer iface;
+
+ iface = TypeManager.LookupInterface (t);
+
+ mi = iface.GetMethods ();
+ } else
+ mi = t.GetMethods ();
+
+ int count = mi.Length;
+ pending_implementations [i].type = t;
+ 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];
+ string indexer_name = TypeManager.IndexerPropertyName (t);
+
+ pending_implementations [i].set_indexer_name = "set_" + indexer_name;
+ pending_implementations [i].get_indexer_name = "get_" + indexer_name;
+
+ 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;
+
+ string indexer_name = TypeManager.IndexerPropertyName (type_builder);
+ pending_implementations [i].set_indexer_name = "set_" + indexer_name;
+ pending_implementations [i].get_indexer_name = "get_" + indexer_name;
+
+ 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.
+ //
+ // Even better -- on MS it returns an empty array, no matter what.
+ //
+ // Completely broken. So we do it ourselves!
+ //
+ Type [] impl = TypeManager.GetExplicitInterfaces (type_builder);
+
+ if (impl == null || impl.Length == 0)
+ return EmptyMissingInterfacesInfo;
+
+ MissingInterfacesInfo [] ret = new MissingInterfacesInfo [impl.Length];
+
+ for (int i = 0; i < impl.Length; i++)
+ ret [i] = new MissingInterfacesInfo (impl [i]);
+
+ // we really should not get here because Object doesnt implement any
+ // interfaces. But it could implement something internal, so we have
+ // to handle that case.
+ if (type_builder.BaseType == null)
+ return ret;
+
+ Type [] parent_impls = TypeManager.GetInterfaces (type_builder.BaseType);
+
+ foreach (Type t in parent_impls) {
+ for (int i = 0; i < ret.Length; i ++) {
+ if (t == ret [i].Type) {
+ ret [i].Optional = true;
+ break;
+ }
+ }
+ }
+ return ret;
+ }
+
+ //
+ // 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, null, 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;
+
+ string mname = TypeManager.GetMethodName (m);
+
+ //
+ // `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){
+ if (mname != tm.get_indexer_name && mname != tm.set_indexer_name)
+ continue;
+ } else if ((need_proxy == null) && (name != mname))
+ continue;
+
+ if (!TypeManager.IsEqual (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 (!TypeManager.IsEqual (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.
+ bool name_matches = false;
+ if (name == mname || mname == tm.get_indexer_name || mname == tm.set_indexer_name)
+ name_matches = true;
+
+ if ((t == null) && (need_proxy != null) && !name_matches)
+ 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);
+
+ ParameterData pd = Invocation.GetParameterData (iface_method);
+ proxy.DefineParameter (0, ParameterAttributes.None, "");
+ for (int i = 0; i < pd.Count; i++) {
+ string name = pd.ParameterName (i);
+ ParameterAttributes attr = Parameter.GetParameterAttributes (pd.ParameterModifier (i));
+ ParameterBuilder pb = proxy.DefineParameter (i + 1, attr, name);
+ }
+
+ 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;
+
+ if (pending_implementations [i].found [j]) {
+ string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
+ Report.Error (536, container.Location,
+ "'{0}' does not implement interface member '{1}'. '{2}.{3}' " +
+ "is either static, not public, or has the wrong return type",
+ container.Name, TypeManager.CSharpSignature (mi),
+ container.Name, methodLabel[methodLabel.Length - 1]);
+ }
+ else {
+ Report.Error (535, container.Location, "'{0}' does not implement interface member '{1}'",
+ container.Name, TypeManager.CSharpSignature (mi));
+ }
+ } else {
+ Report.Error (534, container.Location, "'{0}' does not implement inherited abstract member '{1}'",
+ container.Name, TypeManager.CSharpSignature (mi));
+ }
+ errors = true;
+ j++;
+ }
+ }
+ return errors;
+ }
+ } /* end of class */
+}
--- /dev/null
+//
+// 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.Collections.Specialized;
+using System.Diagnostics;
+using System.Reflection;
+
+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 Hashtable warning_regions_table;
+
+ /// <summary>
+ /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported.
+ /// </summary>
+ static StringCollection extra_information = new StringCollection ();
+
+ abstract class AbstractMessage {
+
+ static void Check (int code)
+ {
+ if (code == expected_error) {
+ Environment.Exit (0);
+ }
+ }
+
+ public abstract bool IsWarning { get; }
+
+ public abstract string MessageType { get; }
+
+ public virtual void Print (int code, string location, string text)
+ {
+ if (code < 0)
+ code = 8000-code;
+
+ StringBuilder msg = new StringBuilder ();
+ if (location.Length != 0) {
+ msg.Append (location);
+ msg.Append (' ');
+ }
+ msg.AppendFormat ("{0} CS{1:0000}: {2}", MessageType, code, text);
+ Console.Error.WriteLine (msg.ToString ());
+
+ foreach (string s in extra_information)
+ Console.Error.WriteLine (s + MessageType);
+
+ extra_information.Clear ();
+
+ if (Stacktrace)
+ Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
+
+ if (Fatal) {
+ if (!IsWarning || WarningsAreErrors)
+ throw new Exception (text);
+ }
+
+ Check (code);
+ }
+
+ public virtual void Print (int code, Location location, string text)
+ {
+ if (location.Equals (Location.Null)) {
+ Print (code, "", text);
+ return;
+ }
+ Print (code, String.Format ("{0}({1})", location.Name, location.Row), text);
+ }
+ }
+
+ sealed class WarningMessage: AbstractMessage {
+ Location loc = Location.Null;
+ readonly int Level;
+
+ public WarningMessage ():
+ this (-1) {}
+
+ public WarningMessage (int level)
+ {
+ Level = level;
+ }
+
+ public override bool IsWarning {
+ get { return true; }
+ }
+
+ bool IsEnabled (int code)
+ {
+ if (RootContext.WarningLevel < Level)
+ return false;
+
+ if (warning_ignore_table != null) {
+ if (warning_ignore_table.Contains (code)) {
+ return false;
+ }
+ }
+
+ if (warning_regions_table == null || loc.Equals (Location.Null))
+ return true;
+
+ WarningRegions regions = (WarningRegions)warning_regions_table [loc.Name];
+ return regions.IsWarningEnabled (code, loc.Row);
+ }
+
+ public override void Print(int code, string location, string text)
+ {
+ if (!IsEnabled (code)) {
+ extra_information.Clear ();
+ return;
+ }
+
+ if (WarningsAreErrors) {
+ new ErrorMessage ().Print (code, location, text);
+ return;
+ }
+
+ Warnings++;
+ base.Print (code, location, text);
+ }
+
+ public override void Print(int code, Location location, string text)
+ {
+ loc = location;
+ base.Print (code, location, text);
+ }
+
+ public override string MessageType {
+ get {
+ return "warning";
+ }
+ }
+ }
+
+ sealed class ErrorMessage: AbstractMessage {
+
+ public override void Print(int code, string location, string text)
+ {
+ Errors++;
+ base.Print (code, location, text);
+ }
+
+ public override bool IsWarning {
+ get { return false; }
+ }
+
+ public override string MessageType {
+ get {
+ return "error";
+ }
+ }
+
+ }
+
+ public static void FeatureIsNotStandardized (Location loc, string feature)
+ {
+ Report.Error (1644, loc, "Feature '{0}' cannot be used because it is not part of the standardized ISO C# language specification", feature);
+ }
+
+ public static string FriendlyStackTrace (Exception e)
+ {
+ return FriendlyStackTrace (new StackTrace (e, true));
+ }
+
+ static string FriendlyStackTrace (StackTrace t)
+ {
+ StringBuilder sb = new StringBuilder ();
+
+ bool foundUserCode = false;
+
+ for (int i = 0; i < t.FrameCount; i++) {
+ StackFrame f = t.GetFrame (i);
+ MethodBase mb = f.GetMethod ();
+
+ if (!foundUserCode && mb.ReflectedType == typeof (Report))
+ continue;
+
+ foundUserCode = true;
+
+ sb.Append ("\tin ");
+
+ if (f.GetFileLineNumber () > 0)
+ sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ());
+
+ sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name);
+
+ bool first = true;
+ foreach (ParameterInfo pi in mb.GetParameters ()) {
+ if (!first)
+ sb.Append (", ");
+ first = false;
+
+ sb.Append (TypeManager.CSharpName (pi.ParameterType));
+ }
+ sb.Append (")\n");
+ }
+
+ return sb.ToString ();
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // IF YOU ADD A NEW WARNING YOU HAVE TO DUPLICATE ITS ID HERE
+ //
+ public static bool IsValidWarning (int code)
+ {
+ int[] all_warnings = new int[] {
+ 28, 67, 78, 105, 108, 109, 114, 192, 168, 169, 183, 184, 219, 251, 612, 618, 626, 628, 642, 649,
+ 659, 660, 661, 672, 1030, 1522, 1616, 1691, 1692, 1901, 2002, 2023, 3012, 3019, 8024, 8028
+ };
+
+ foreach (int i in all_warnings) {
+ if (i == code)
+ return true;
+ }
+ return false;
+ }
+
+ static public void LocationOfPreviousError (Location loc)
+ {
+ Console.Error.WriteLine (String.Format ("{0}({1}) (Location of symbol related to previous error)", loc.Name, loc.Row));
+ }
+
+ static public void RuntimeMissingSupport (Location loc, string feature)
+ {
+ Report.Error (-88, loc, "Your .NET Runtime does not support '{0}'. Please use the latest Mono runtime instead.", feature);
+ }
+
+ /// <summary>
+ /// In most error cases is very useful to have information about symbol that caused the error.
+ /// Call this method before you call Report.Error when it makes sense.
+ /// </summary>
+ static public void SymbolRelatedToPreviousError (Location loc, string symbol)
+ {
+ SymbolRelatedToPreviousError (String.Format ("{0}({1})", loc.Name, loc.Row), symbol);
+ }
+
+ static public void SymbolRelatedToPreviousError (MemberInfo mi)
+ {
+ TypeContainer temp_ds = TypeManager.LookupGenericTypeContainer (mi.DeclaringType);
+ if (temp_ds == null) {
+ SymbolRelatedToPreviousError (mi.DeclaringType.Assembly.Location, TypeManager.GetFullNameSignature (mi));
+ } else {
+ MethodBase mb = mi as MethodBase;
+ if (mb != null) {
+ while (mb.Mono_IsInflatedMethod)
+ mb = mb.GetGenericMethodDefinition ();
+ IMethodData md = TypeManager.GetMethod (mb);
+ SymbolRelatedToPreviousError (md.Location, md.GetSignatureForError (temp_ds));
+ return;
+ }
+
+ string name = String.Concat (temp_ds.Name, ".", mi.Name);
+ MemberCore mc = temp_ds.GetDefinition (name);
+ SymbolRelatedToPreviousError (mc);
+ }
+ }
+
+ static public void SymbolRelatedToPreviousError (MemberCore mc)
+ {
+ SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ());
+ }
+
+ static public void SymbolRelatedToPreviousError (Type type)
+ {
+ DeclSpace temp_ds = TypeManager.LookupDeclSpace (type);
+ if (temp_ds == null)
+ SymbolRelatedToPreviousError (type.Assembly.Location, TypeManager.CSharpName (type));
+ else
+ SymbolRelatedToPreviousError (temp_ds.Location, TypeManager.CSharpName (type));
+ }
+
+ static void SymbolRelatedToPreviousError (string loc, string symbol)
+ {
+ extra_information.Add (String.Format ("{0}: '{1}' (name of symbol related to previous ", loc, symbol));
+ }
+
+ public static void ExtraInformation (Location loc, string msg)
+ {
+ extra_information.Add (String.Format ("{0}({1}) {2}", loc.Name, loc.Row, msg));
+ }
+
+ public static WarningRegions RegisterWarningRegion (Location location)
+ {
+ if (warning_regions_table == null)
+ warning_regions_table = new Hashtable ();
+
+ WarningRegions regions = (WarningRegions)warning_regions_table [location.Name];
+ if (regions == null) {
+ regions = new WarningRegions ();
+ warning_regions_table.Add (location.Name, regions);
+ }
+ return regions;
+ }
+
+ static public void Warning (int code, int level, Location loc, string format, params object[] args)
+ {
+ WarningMessage w = new WarningMessage (level);
+ w.Print (code, loc, String.Format (format, args));
+ }
+
+ static public void Warning (int code, Location loc, string format, params object[] args)
+ {
+ WarningMessage w = new WarningMessage ();
+ w.Print (code, loc, String.Format (format, args));
+ }
+
+ static public void Warning (int code, string format, params object[] args)
+ {
+ Warning (code, Location.Null, String.Format (format, args));
+ }
+
+ /// <summary>
+ /// Did you test your WarningLevel, that you use this method
+ /// </summary>
+ static public void Warning (int code, string text)
+ {
+ Warning (code, Location.Null, text);
+ }
+
+ static public void Error (int code, string format, params object[] args)
+ {
+ Error (code, Location.Null, String.Format (format, args));
+ }
+
+ static public void Error (int code, Location loc, string format, params object[] args)
+ {
+ ErrorMessage e = new ErrorMessage ();
+ e.Print (code, loc, String.Format (format, args));
+ }
+
+ 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 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)
+ {
+ }
+ }
+
+ /// <summary>
+ /// Handles #pragma warning
+ /// </summary>
+ public class WarningRegions {
+
+ abstract class PragmaCmd
+ {
+ public int Line;
+
+ protected PragmaCmd (int line)
+ {
+ Line = line;
+ }
+
+ public abstract bool IsEnabled (int code, bool previous);
+ }
+
+ class Disable: PragmaCmd
+ {
+ int code;
+ public Disable (int line, int code)
+ : base (line)
+ {
+ this.code = code;
+ }
+
+ public override bool IsEnabled (int code, bool previous)
+ {
+ return this.code == code ? false : previous;
+ }
+ }
+
+ class DisableAll: PragmaCmd
+ {
+ public DisableAll (int line)
+ : base (line) {}
+
+ public override bool IsEnabled(int code, bool previous)
+ {
+ return false;
+ }
+ }
+
+ class Enable: PragmaCmd
+ {
+ int code;
+ public Enable (int line, int code)
+ : base (line)
+ {
+ this.code = code;
+ }
+
+ public override bool IsEnabled(int code, bool previous)
+ {
+ return this.code == code ? true : previous;
+ }
+ }
+
+ class EnableAll: PragmaCmd
+ {
+ public EnableAll (int line)
+ : base (line) {}
+
+ public override bool IsEnabled(int code, bool previous)
+ {
+ return true;
+ }
+ }
+
+
+ ArrayList regions = new ArrayList ();
+
+ public void WarningDisable (int line)
+ {
+ regions.Add (new DisableAll (line));
+ }
+
+ public void WarningDisable (Location location, int code)
+ {
+ if (CheckWarningCode (code, location))
+ regions.Add (new Disable (location.Row, code));
+ }
+
+ public void WarningEnable (int line)
+ {
+ regions.Add (new EnableAll (line));
+ }
+
+ public void WarningEnable (Location location, int code)
+ {
+ if (CheckWarningCode (code, location))
+ regions.Add (new Enable (location.Row, code));
+ }
+
+ public bool IsWarningEnabled (int code, int src_line)
+ {
+ bool result = true;
+ foreach (PragmaCmd pragma in regions) {
+ if (src_line < pragma.Line)
+ break;
+
+ result = pragma.IsEnabled (code, result);
+ }
+ return result;
+ }
+
+ bool CheckWarningCode (int code, Location loc)
+ {
+ if (Report.IsValidWarning (code))
+ return true;
+
+ Report.Warning (1691, 1, loc, "'{0}' is not a valid warning number", code);
+ return false;
+ }
+ }
+}
--- /dev/null
+//
+// 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)
+// (C) 2004 Novell, Inc
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.Xml;
+
+namespace Mono.CSharp {
+
+ public enum LanguageVersion
+ {
+ Default = 0,
+ ISO_1 = 1
+ }
+
+ 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 ();
+
+ //
+ // 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 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;
+
+ public static Target Target = Target.Exe;
+ public static string TargetExt = ".exe";
+
+ public static bool VerifyClsCompliance = true;
+
+ public static LanguageVersion Version = LanguageVersion.Default;
+
+ //
+ // We keep strongname related info here because
+ // it's also used as complier options from CSC 8.x
+ //
+ public static string StrongNameKeyFile;
+ public static string StrongNameKeyContainer;
+ public static bool StrongNameDelaySign = false;
+
+ //
+ // If set, enable XML documentation generation
+ //
+ public static Documentation Documentation;
+
+ //
+ // Constructor
+ //
+ static RootContext ()
+ {
+ tree = new Tree ();
+ type_container_resolve_order = new ArrayList ();
+ }
+
+ public static bool NeedsEntryPoint {
+ get {
+ return RootContext.Target == Target.Exe || RootContext.Target == Target.WinExe;
+ }
+ }
+
+ static public Tree Tree {
+ get {
+ return tree;
+ }
+ }
+
+ static public string MainClass;
+
+ 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 (1);
+ }
+
+ 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.Runtime.InteropServices._Exception",
+
+ "System.Reflection.IReflect",
+ "System.Reflection.ICustomAttributeProvider",
+
+ //
+ // Generic types
+ //
+ "System.Collections.Generic.IEnumerator`1",
+ "System.Collections.Generic.IEnumerable`1"
+ };
+
+ 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.RuntimeArgumentHandle",
+ "System.RuntimeTypeHandle",
+ "System.IntPtr",
+ "System.TypedReference",
+ "System.ArgIterator"
+ };
+
+ 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",
+ "System.Activator",
+
+ //
+ // 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.Runtime.CompilerServices.NewConstraintAttribute",
+ "System.Diagnostics.ConditionalAttribute",
+ "System.ObsoleteAttribute",
+ "System.ParamArrayAttribute",
+ "System.CLSCompliantAttribute",
+ "System.Security.UnverifiableCodeAttribute",
+ "System.Security.Permissions.SecurityAttribute",
+ "System.Runtime.CompilerServices.IndexerNameAttribute",
+ "System.Runtime.CompilerServices.DecimalConstantAttribute",
+ "System.Runtime.InteropServices.InAttribute",
+ "System.Runtime.InteropServices.StructLayoutAttribute",
+ "System.Runtime.InteropServices.FieldOffsetAttribute",
+ "System.InvalidOperationException",
+ "System.NotSupportedException",
+ "System.MarshalByRefObject",
+ "System.Security.CodeAccessPermission"
+ };
+
+ // 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;
+
+ if (root.Enums != null)
+ foreach (Enum en in root.Enums)
+ en.CloseType ();
+
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.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.Kind == Kind.Struct && tc.Parent == tree.Types){
+ tc.CloseType ();
+ }
+ }
+
+ foreach (TypeContainer tc in type_container_resolve_order){
+ if (!(tc.Kind == Kind.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 ();
+ }
+
+ attribute_types = null;
+ type_container_resolve_order = null;
+ helper_classes = null;
+ //tree = null;
+ TypeManager.CleanUp ();
+ }
+
+ /// <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, int num_type_args, Location loc)
+ {
+ IAlias result = ds.NamespaceEntry.LookupNamespaceOrType (ds, name, loc);
+ if (result == null)
+ return null;
+
+ if (!result.IsType)
+ return null;
+
+ TypeExpr texpr = result.ResolveAsType (ds.EmitContext);
+ if (texpr == null)
+ return null;
+
+ return texpr.Type;
+ }
+
+ static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc)
+ {
+ return LookupType (ds, name, silent, 0, loc);
+ }
+
+ //
+ // 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,
+ int num_type_params, 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
+ //
+ Type type = TypeManager.LookupType (current_type.FullName + "." + name);
+ if (type != null){
+ t = ds.ResolveNestedType (type, loc);
+ ds.Cache [name] = t;
+ return t;
+ }
+
+ current_type = current_type.BaseType;
+ }
+
+ containing_ds = containing_ds.Parent;
+ }
+
+ t = NamespaceLookup (ds, name, num_type_params, loc);
+ if (!silent || 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 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 ();
+ }
+
+ 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 (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);
+ }
+
+ //
+ // Check for cycles in the struct layout
+ //
+ if (type_container_resolve_order != null){
+ Hashtable seen = new Hashtable ();
+ foreach (TypeContainer tc in type_container_resolve_order)
+ TypeManager.CheckStructCycles (tc, seen);
+ }
+ }
+
+ //
+ // 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 ();
+
+ 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 ();
+ }
+ }
+
+ ArrayList delegates = root.Delegates;
+ if (delegates != null){
+ foreach (Delegate d in delegates)
+ if ((d.ModFlags & Modifiers.NEW) == 0)
+ d.Define ();
+ }
+
+ ArrayList enums = root.Enums;
+ if (enums != null){
+ foreach (Enum en in enums)
+ if ((en.ModFlags & Modifiers.NEW) == 0)
+ en.Define ();
+ }
+ }
+
+ static public void EmitCode ()
+ {
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.EmitType ();
+
+ CodeGen.Assembly.Emit (Tree.Types);
+ CodeGen.Module.Emit (Tree.Types);
+
+ if (Tree.Types.Enums != null) {
+ foreach (Enum e in Tree.Types.Enums)
+ e.Emit ();
+ }
+
+ if (type_container_resolve_order != null) {
+ foreach (TypeContainer tc in type_container_resolve_order)
+ tc.EmitType ();
+ }
+
+ if (Tree.Types.Delegates != null) {
+ foreach (Delegate d in Tree.Types.Delegates)
+ d.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 ();
+ }
+
+ //
+ // 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;
+
+ if (impl_details_class == null){
+ impl_details_class = CodeGen.Module.Builder.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;
+ }
+ }
+}
+
+
--- /dev/null
+using System;
+using Generics;
+
+namespace Test
+{
+ public class Bar : Foo
+ {
+ public void Hello (Stack<int> stack)
+ {
+ Console.WriteLine ("Hello Generic World!");
+ Console.WriteLine (stack);
+ Console.WriteLine (stack.GetType ());
+ }
+
+ public Stack<int> Test ()
+ {
+ return Driver.int_stack;
+ }
+
+ public static void Main ()
+ {
+ Foo foo = new Bar ();
+ Driver.Init (foo);
+ Stack<int> a = Driver.int_stack;
+ Console.WriteLine ("STACK: {0}", a);
+ foo.Hello (a);
+ }
+ }
+}
--- /dev/null
+//
+// statement.cs: Statement representation for the IL tree.
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+// Martin Baulig (martin@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, 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;
+
+ /// <summary>
+ /// Resolves the statement, true means that all sub-statements
+ /// did resolve ok.
+ // </summary>
+ public virtual bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// We already know that the statement is unreachable, but we still
+ /// need to resolve it to catch errors.
+ /// </summary>
+ public virtual bool ResolveUnreachable (EmitContext ec, bool warn)
+ {
+ //
+ // This conflicts with csc's way of doing this, but IMHO it's
+ // the right thing to do.
+ //
+ // If something is unreachable, we still check whether it's
+ // correct. This means that you cannot use unassigned variables
+ // in unreachable code, for instance.
+ //
+
+ if (warn && (RootContext.WarningLevel >= 2))
+ Report.Warning (162, loc, "Unreachable code detected");
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+ bool ok = Resolve (ec);
+ ec.KillFlowBranching ();
+
+ return ok;
+ }
+
+ protected void CheckObsolete (Type type)
+ {
+ ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
+ if (obsolete_attr == null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc);
+ }
+
+ /// <summary>
+ /// Return value indicates whether all code paths emitted return.
+ /// </summary>
+ protected abstract void DoEmit (EmitContext ec);
+
+ /// <summary>
+ /// Utility wrapper routine for Error, just to beautify the code
+ /// </summary>
+ public void Error (int error, string format, params object[] args)
+ {
+ Error (error, String.Format (format, args));
+ }
+
+ public void Error (int error, string s)
+ {
+ if (!Location.IsNull (loc))
+ Report.Error (error, loc, s);
+ else
+ Report.Error (error, s);
+ }
+
+ /// <summary>
+ /// Return value indicates whether all code paths emitted return.
+ /// </summary>
+ public virtual void Emit (EmitContext ec)
+ {
+ ec.Mark (loc, true);
+ DoEmit (ec);
+ }
+ }
+
+ public sealed class EmptyStatement : Statement {
+
+ private EmptyStatement () {}
+
+ public static readonly EmptyStatement Value = new EmptyStatement ();
+
+ public override bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ }
+ }
+
+ public class If : Statement {
+ Expression expr;
+ public Statement TrueStatement;
+ public Statement FalseStatement;
+
+ bool is_true_ret;
+
+ 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;
+ }
+
+ //
+ // Dead code elimination
+ //
+ if (expr is BoolConstant){
+ bool take = ((BoolConstant) expr).Value;
+
+ if (take){
+ if (!TrueStatement.Resolve (ec))
+ return false;
+
+ if ((FalseStatement != null) &&
+ !FalseStatement.ResolveUnreachable (ec, true))
+ return false;
+ FalseStatement = null;
+ } else {
+ if (!TrueStatement.ResolveUnreachable (ec, true))
+ return false;
+ TrueStatement = null;
+
+ if ((FalseStatement != null) &&
+ !FalseStatement.Resolve (ec))
+ return false;
+ }
+
+ return true;
+ }
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
+
+ bool ok = TrueStatement.Resolve (ec);
+
+ is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
+
+ ec.CurrentBranching.CreateSibling ();
+
+ if ((FalseStatement != null) && !FalseStatement.Resolve (ec))
+ ok = false;
+
+ ec.EndFlowBranching ();
+
+ Report.Debug (1, "END IF BLOCK", loc);
+
+ return ok;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ Label false_target = ig.DefineLabel ();
+ Label end;
+
+ //
+ // If we're a boolean expression, Resolve() already
+ // eliminated dead code for us.
+ //
+ if (expr is BoolConstant){
+ bool take = ((BoolConstant) expr).Value;
+
+ if (take)
+ TrueStatement.Emit (ec);
+ else if (FalseStatement != null)
+ FalseStatement.Emit (ec);
+
+ return;
+ }
+
+ expr.EmitBranchable (ec, false_target, false);
+
+ TrueStatement.Emit (ec);
+
+ 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);
+ FalseStatement.Emit (ec);
+
+ if (branch_emitted)
+ ig.MarkLabel (end);
+ } else {
+ ig.MarkLabel (false_target);
+ }
+ }
+ }
+
+ public class Do : Statement {
+ public Expression expr;
+ public readonly Statement EmbeddedStatement;
+ bool infinite;
+
+ 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 (FlowBranching.BranchingType.Loop, 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;
+ ec.EndFlowBranching ();
+
+ return ok;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ Label loop = ig.DefineLabel ();
+ Label old_begin = ec.LoopBegin;
+ Label old_end = ec.LoopEnd;
+
+ ec.LoopBegin = ig.DefineLabel ();
+ ec.LoopEnd = ig.DefineLabel ();
+
+ 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
+ expr.EmitBranchable (ec, loop, true);
+
+ ig.MarkLabel (ec.LoopEnd);
+
+ ec.LoopBegin = old_begin;
+ ec.LoopEnd = old_end;
+ }
+ }
+
+ public class While : Statement {
+ public Expression expr;
+ public readonly Statement Statement;
+ bool infinite, empty;
+
+ 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;
+
+ //
+ // Inform whether we are infinite or not
+ //
+ if (expr is BoolConstant){
+ BoolConstant bc = (BoolConstant) expr;
+
+ if (bc.Value == false){
+ if (!Statement.ResolveUnreachable (ec, true))
+ return false;
+ empty = true;
+ return true;
+ } else
+ infinite = true;
+ }
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
+
+ if (!Statement.Resolve (ec))
+ ok = false;
+
+ ec.CurrentBranching.Infinite = infinite;
+ ec.EndFlowBranching ();
+
+ return ok;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (empty)
+ return;
+
+ ILGenerator ig = ec.ig;
+ Label old_begin = ec.LoopBegin;
+ Label old_end = ec.LoopEnd;
+
+ ec.LoopBegin = ig.DefineLabel ();
+ ec.LoopEnd = ig.DefineLabel ();
+
+ //
+ // Inform whether we are infinite or not
+ //
+ if (expr is BoolConstant){
+ 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.
+ //
+ 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);
+
+ expr.EmitBranchable (ec, while_loop, true);
+
+ ig.MarkLabel (ec.LoopEnd);
+ }
+
+ ec.LoopBegin = old_begin;
+ ec.LoopEnd = old_end;
+ }
+ }
+
+ public class For : Statement {
+ Expression Test;
+ readonly Statement InitStatement;
+ readonly Statement Increment;
+ readonly Statement Statement;
+ bool 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){
+ if (!Statement.ResolveUnreachable (ec, true))
+ return false;
+ if ((Increment != null) &&
+ !Increment.ResolveUnreachable (ec, false))
+ return false;
+ empty = true;
+ return true;
+ } else
+ infinite = true;
+ }
+ } else
+ infinite = true;
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
+ if (!infinite)
+ ec.CurrentBranching.CreateSibling ();
+
+ if (!Statement.Resolve (ec))
+ ok = false;
+
+ if (Increment != null){
+ if (!Increment.Resolve (ec))
+ ok = false;
+ }
+
+ ec.CurrentBranching.Infinite = infinite;
+ ec.EndFlowBranching ();
+
+ return ok;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (empty)
+ return;
+
+ ILGenerator ig = ec.ig;
+ Label old_begin = ec.LoopBegin;
+ Label old_end = ec.LoopEnd;
+ Label loop = ig.DefineLabel ();
+ Label test = ig.DefineLabel ();
+
+ if (InitStatement != null && InitStatement != EmptyStatement.Value)
+ InitStatement.Emit (ec);
+
+ ec.LoopBegin = ig.DefineLabel ();
+ ec.LoopEnd = ig.DefineLabel ();
+
+ ig.Emit (OpCodes.Br, test);
+ ig.MarkLabel (loop);
+ Statement.Emit (ec);
+
+ ig.MarkLabel (ec.LoopBegin);
+ if (Increment != EmptyStatement.Value)
+ 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
+ Test.EmitBranchable (ec, loop, true);
+
+ } else
+ ig.Emit (OpCodes.Br, loop);
+ ig.MarkLabel (ec.LoopEnd);
+
+ ec.LoopBegin = old_begin;
+ ec.LoopEnd = old_end;
+ }
+ }
+
+ public class StatementExpression : Statement {
+ public 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 void DoEmit (EmitContext ec)
+ {
+ expr.EmitStatement (ec);
+ }
+
+ 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;
+ }
+
+ bool in_exc;
+
+ public override bool Resolve (EmitContext ec)
+ {
+ if (ec.ReturnType == null){
+ if (Expr != null){
+ if (ec.CurrentAnonymousMethod != null){
+ Report.Error (1662, loc, String.Format (
+ "Anonymous method could not be converted to delegate " +
+ "since the return value does not match the delegate value"));
+ }
+ Error (127, "Return with a value not allowed here");
+ return false;
+ }
+ } else {
+ if (Expr == null){
+ Error (126, "An object of type `{0}' is expected " +
+ "for the return statement",
+ TypeManager.CSharpName (ec.ReturnType));
+ return false;
+ }
+
+ Expr = Expr.Resolve (ec);
+ if (Expr == null)
+ return false;
+
+ if (Expr.Type != ec.ReturnType) {
+ Expr = Convert.ImplicitConversionRequired (
+ ec, Expr, ec.ReturnType, loc);
+ if (Expr == null)
+ return false;
+ }
+ }
+
+ if (ec.InIterator){
+ Error (-206, "Return statement not allowed inside iterators");
+ return false;
+ }
+
+ FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+ if (ec.CurrentBranching.InTryOrCatch (true)) {
+ ec.CurrentBranching.AddFinallyVector (vector);
+ in_exc = true;
+ } else if (ec.CurrentBranching.InFinally (true)) {
+ Error (157, "Control can not leave the body of the finally block");
+ return false;
+ } else
+ vector.CheckOutParameters (ec.CurrentBranching);
+
+ if (in_exc)
+ ec.NeedReturnLabel ();
+
+ ec.CurrentBranching.CurrentUsageVector.Return ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (Expr != null) {
+ Expr.Emit (ec);
+
+ if (in_exc)
+ ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
+ }
+
+ if (in_exc)
+ ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+ else
+ ec.ig.Emit (OpCodes.Ret);
+ }
+ }
+
+ public class Goto : Statement {
+ string target;
+ Block block;
+ LabeledStatement label;
+
+ public override bool Resolve (EmitContext ec)
+ {
+ label = ec.CurrentBranching.LookupLabel (target, loc);
+ if (label == null)
+ return false;
+
+ // If this is a forward goto.
+ if (!label.IsDefined)
+ label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
+
+ ec.CurrentBranching.CurrentUsageVector.Goto ();
+
+ 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 void DoEmit (EmitContext ec)
+ {
+ Label l = label.LabelTarget (ec);
+ ec.ig.Emit (OpCodes.Br, l);
+ }
+ }
+
+ public class LabeledStatement : Statement {
+ public readonly Location Location;
+ bool defined;
+ bool referenced;
+ Label label;
+
+ FlowBranching.UsageVector vectors;
+
+ public LabeledStatement (string label_name, Location l)
+ {
+ 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)
+ {
+ vector = vector.Clone ();
+ vector.Next = vectors;
+ vectors = vector;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ ec.CurrentBranching.Label (vectors);
+
+ referenced = true;
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ LabelTarget (ec);
+ ec.ig.MarkLabel (label);
+ }
+ }
+
+
+ /// <summary>
+ /// `goto default' statement
+ /// </summary>
+ public class GotoDefault : Statement {
+
+ public GotoDefault (Location l)
+ {
+ loc = l;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ ec.CurrentBranching.CurrentUsageVector.Goto ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (ec.Switch == null){
+ Report.Error (153, loc, "goto default is only valid in a switch statement");
+ return;
+ }
+
+ if (!ec.Switch.GotDefault){
+ Report.Error (159, loc, "No default target on switch statement");
+ return;
+ }
+ ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
+ }
+ }
+
+ /// <summary>
+ /// `goto case' statement
+ /// </summary>
+ public class GotoCase : Statement {
+ Expression expr;
+ SwitchLabel sl;
+
+ 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;
+
+ sl = (SwitchLabel) ec.Switch.Elements [val];
+
+ if (sl == null){
+ Report.Error (
+ 159, loc,
+ "No such label 'case " + val + "': for the goto case");
+ return false;
+ }
+
+ ec.CurrentBranching.CurrentUsageVector.Goto ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
+ }
+ }
+
+ public class Throw : Statement {
+ Expression expr;
+
+ public Throw (Expression expr, Location l)
+ {
+ this.expr = expr;
+ loc = l;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ bool in_catch = ec.CurrentBranching.InCatch ();
+ ec.CurrentBranching.CurrentUsageVector.Throw ();
+
+ 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 ", loc);
+ return false;
+ }
+
+ Type t = expr.Type;
+
+ if ((t != TypeManager.exception_type) &&
+ !t.IsSubclassOf (TypeManager.exception_type) &&
+ !(expr is NullLiteral)) {
+ Error (155,
+ "The type caught or thrown must be derived " +
+ "from System.Exception");
+ return false;
+ }
+ } else if (!in_catch) {
+ Error (156,
+ "A throw statement with no argument is only " +
+ "allowed in a catch clause");
+ return false;
+ }
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (expr == null)
+ ec.ig.Emit (OpCodes.Rethrow);
+ else {
+ expr.Emit (ec);
+
+ ec.ig.Emit (OpCodes.Throw);
+ }
+ }
+ }
+
+ public class Break : Statement {
+
+ public Break (Location l)
+ {
+ loc = l;
+ }
+
+ bool crossing_exc;
+
+ public override bool Resolve (EmitContext ec)
+ {
+ if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+ Error (139, "No enclosing loop or switch to continue to");
+ return false;
+ } else if (ec.CurrentBranching.InFinally (false)) {
+ Error (157, "Control can not leave the body of the finally block");
+ return false;
+ } else if (ec.CurrentBranching.InTryOrCatch (false))
+ ec.CurrentBranching.AddFinallyVector (
+ ec.CurrentBranching.CurrentUsageVector);
+ else if (ec.CurrentBranching.InLoop ())
+ ec.CurrentBranching.AddBreakVector (
+ ec.CurrentBranching.CurrentUsageVector);
+
+ crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
+ if (!crossing_exc)
+ ec.NeedReturnLabel ();
+
+ ec.CurrentBranching.CurrentUsageVector.Break ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (crossing_exc)
+ ig.Emit (OpCodes.Leave, ec.LoopEnd);
+ else {
+ ig.Emit (OpCodes.Br, ec.LoopEnd);
+ }
+ }
+ }
+
+ public class Continue : Statement {
+
+ public Continue (Location l)
+ {
+ loc = l;
+ }
+
+ bool crossing_exc;
+
+ public override bool Resolve (EmitContext ec)
+ {
+ if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+ Error (139, "No enclosing loop to continue to");
+ return false;
+ } else if (ec.CurrentBranching.InFinally (false)) {
+ Error (157, "Control can not leave the body of the finally block");
+ return false;
+ } else if (ec.CurrentBranching.InTryOrCatch (false))
+ ec.CurrentBranching.AddFinallyVector (ec.CurrentBranching.CurrentUsageVector);
+
+ crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
+ ec.CurrentBranching.CurrentUsageVector.Goto ();
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ Label begin = ec.LoopBegin;
+
+ if (crossing_exc)
+ ec.ig.Emit (OpCodes.Leave, begin);
+ else
+ ec.ig.Emit (OpCodes.Br, begin);
+ }
+ }
+
+ //
+ // The information about a user-perceived local variable
+ //
+ public class LocalInfo {
+ public Expression Type;
+
+ //
+ // Most of the time a variable will be stored in a LocalBuilder
+ //
+ // But sometimes, it will be stored in a field (variables that have been
+ // hoisted by iterators or by anonymous methods). 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;
+
+ enum Flags : byte {
+ Used = 1,
+ ReadOnly = 2,
+ Pinned = 4,
+ IsThis = 8,
+ Captured = 16,
+ AddressTaken = 32
+ }
+
+ Flags flags;
+
+ public LocalInfo (Expression type, string name, Block block, Location l)
+ {
+ Type = type;
+ Name = name;
+ Block = block;
+ Location = l;
+ }
+
+ public LocalInfo (TypeContainer tc, Block block, Location l)
+ {
+ VariableType = tc.TypeBuilder;
+ Block = block;
+ Location = l;
+ }
+
+ public bool IsThisAssigned (EmitContext ec, Location loc)
+ {
+ if (VariableInfo == null)
+ throw new Exception ();
+
+ if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
+ return true;
+
+ return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, loc);
+ }
+
+ public bool IsAssigned (EmitContext ec)
+ {
+ if (VariableInfo == null)
+ throw new Exception ();
+
+ return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
+ }
+
+ public bool Resolve (EmitContext ec)
+ {
+ if (VariableType == null) {
+ TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return false;
+
+ VariableType = texpr.Type;
+ }
+
+ if (VariableType == TypeManager.void_type) {
+ Report.Error (1547, Location,
+ "Keyword 'void' cannot be used in this context");
+ return false;
+ }
+
+ if (VariableType.IsAbstract && VariableType.IsSealed) {
+ Report.Error (723, Location, "Cannot declare variable of static type '{0}'", TypeManager.CSharpName (VariableType));
+ return false;
+ }
+// TODO: breaks the build
+// if (VariableType.IsPointer && !ec.InUnsafe)
+// Expression.UnsafeError (Location);
+
+ return true;
+ }
+
+ //
+ // Whether the variable is Fixed (because its Pinned or its a value type)
+ //
+ public bool IsFixed {
+ get {
+ if (((flags & Flags.Pinned) != 0) || TypeManager.IsValueType (VariableType))
+ return true;
+
+ return false;
+ }
+ }
+
+ public bool IsCaptured {
+ get {
+ return (flags & Flags.Captured) != 0;
+ }
+
+ set {
+ flags |= Flags.Captured;
+ }
+ }
+
+ public bool AddressTaken {
+ get {
+ return (flags & Flags.AddressTaken) != 0;
+ }
+
+ set {
+ flags |= Flags.AddressTaken;
+ }
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("LocalInfo ({0},{1},{2},{3})",
+ Name, Type, VariableInfo, Location);
+ }
+
+ public bool Used {
+ get {
+ return (flags & Flags.Used) != 0;
+ }
+ set {
+ flags = value ? (flags | Flags.Used) : (unchecked (flags & ~Flags.Used));
+ }
+ }
+
+ public bool ReadOnly {
+ get {
+ return (flags & Flags.ReadOnly) != 0;
+ }
+ set {
+ flags = value ? (flags | Flags.ReadOnly) : (unchecked (flags & ~Flags.ReadOnly));
+ }
+ }
+
+ //
+ // Whether the variable is pinned, if Pinned the variable has been
+ // allocated in a pinned slot with DeclareLocal.
+ //
+ public bool Pinned {
+ get {
+ return (flags & Flags.Pinned) != 0;
+ }
+ set {
+ flags = value ? (flags | Flags.Pinned) : (flags & ~Flags.Pinned);
+ }
+ }
+
+ public bool IsThis {
+ get {
+ return (flags & Flags.IsThis) != 0;
+ }
+ set {
+ flags = value ? (flags | Flags.IsThis) : (flags & ~Flags.IsThis);
+ }
+ }
+ }
+
+ /// <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.
+ ///
+ /// Top-level blocks derive from Block, and they are called ToplevelBlock
+ /// they contain extra information that is not necessary on normal blocks.
+ /// </remarks>
+ public class Block : Statement {
+ public Block Parent;
+ public readonly Location StartLocation;
+ public Location EndLocation = Location.Null;
+
+ [Flags]
+ public enum Flags {
+ Implicit = 1,
+ Unchecked = 2,
+ BlockUsed = 4,
+ VariablesInitialized = 8,
+ HasRet = 16,
+ IsDestructor = 32,
+ HasVarargs = 64,
+ IsToplevel = 128,
+ Unsafe = 256
+ }
+ Flags flags;
+
+ public bool Implicit {
+ get {
+ return (flags & Flags.Implicit) != 0;
+ }
+ }
+
+ public bool Unchecked {
+ get {
+ return (flags & Flags.Unchecked) != 0;
+ }
+ set {
+ flags |= Flags.Unchecked;
+ }
+ }
+
+ public bool Unsafe {
+ get {
+ return (flags & Flags.Unsafe) != 0;
+ }
+ set {
+ flags |= Flags.Unsafe;
+ }
+ }
+
+ public bool HasVarargs {
+ get {
+ if (Parent != null)
+ return Parent.HasVarargs;
+ else
+ return (flags & Flags.HasVarargs) != 0;
+ }
+ set {
+ flags |= Flags.HasVarargs;
+ }
+ }
+
+ //
+ // The statements in this block
+ //
+ public ArrayList statements;
+ int num_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;
+
+ //
+ // The parameters for the block, this is only needed on the toplevel block really
+ // TODO: move `parameters' into ToplevelBlock
+ Parameters parameters;
+
+ //
+ // If this is a switch section, the enclosing switch block.
+ //
+ Block switch_block;
+
+ protected 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 ();
+
+ if (parent != null && Implicit) {
+ if (parent.child_variable_names == null)
+ parent.child_variable_names = new Hashtable();
+ // share with parent
+ child_variable_names = parent.child_variable_names;
+ }
+
+ }
+
+ 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, Location loc)
+ {
+ if (switch_block != null)
+ return switch_block.AddLabel (name, target, loc);
+
+ Block cur = this;
+ while (cur != null) {
+ if (cur.DoLookupLabel (name) != null) {
+ Report.Error (
+ 140, loc, "The label '{0}' is a duplicate",
+ name);
+ return false;
+ }
+
+ if (!Implicit)
+ break;
+
+ cur = cur.Parent;
+ }
+
+ while (cur != null) {
+ if (cur.DoLookupLabel (name) != null) {
+ Report.Error (
+ 158, loc,
+ "The label '{0}' shadows another label " +
+ "by the same name in a containing scope.",
+ name);
+ return false;
+ }
+
+ if (children != null) {
+ foreach (Block b in children) {
+ LabeledStatement s = b.DoLookupLabel (name);
+ if (s == null)
+ continue;
+
+ Report.Error (
+ 158, s.Location,
+ "The label '{0}' shadows another " +
+ "label by the same name in a " +
+ "containing scope.",
+ name);
+ return false;
+ }
+ }
+
+
+ cur = cur.Parent;
+ }
+
+ if (labels == null)
+ labels = new Hashtable ();
+
+ labels.Add (name, target);
+ return true;
+ }
+
+ public LabeledStatement LookupLabel (string name)
+ {
+ LabeledStatement s = DoLookupLabel (name);
+ if (s != null)
+ return s;
+
+ if (children == null)
+ return null;
+
+ foreach (Block child in children) {
+ if (!child.Implicit)
+ continue;
+
+ s = child.LookupLabel (name);
+ if (s != null)
+ return s;
+ }
+
+ return null;
+ }
+
+ LabeledStatement DoLookupLabel (string name)
+ {
+ if (switch_block != null)
+ return switch_block.LookupLabel (name);
+
+ if (labels != null)
+ if (labels.Contains (name))
+ return ((LabeledStatement) labels [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 ();
+
+ child_variable_names [name] = null;
+ }
+
+ // <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);
+ this_variable.Used = true;
+ this_variable.IsThis = true;
+
+ 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;
+ 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);
+
+ // Mark 'name' as "used by a child block" in every surrounding block
+ Block cur = this;
+ while (cur != null && cur.Implicit)
+ cur = cur.Parent;
+ if (cur != null)
+ for (Block par = cur.Parent; par != null; par = par.Parent)
+ par.AddChildVariableName (name);
+
+ if ((flags & Flags.VariablesInitialized) != 0)
+ 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)
+ {
+ for (Block b = this; b != null; b = b.Parent) {
+ if (b.variables != null) {
+ LocalInfo ret = b.variables [name] as LocalInfo;
+ if (ret != null)
+ return ret;
+ }
+ }
+ return null;
+ }
+
+ public Expression GetVariableType (string name)
+ {
+ LocalInfo vi = GetLocalInfo (name);
+
+ if (vi != null)
+ return vi.Type;
+
+ return null;
+ }
+
+ public Expression GetConstantExpression (string name)
+ {
+ for (Block b = this; b != null; b = b.Parent) {
+ if (b.constants != null) {
+ Expression ret = b.constants [name] as Expression;
+ if (ret != null)
+ return ret;
+ }
+ }
+ 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;
+ }
+
+ //
+ // Returns a `ParameterReference' for the given name, or null if there
+ // is no such parameter
+ //
+ public ParameterReference GetParameterReference (string name, Location loc)
+ {
+ Block b = this;
+
+ do {
+ Parameters pars = b.parameters;
+
+ if (pars != null){
+ Parameter par;
+ int idx;
+
+ par = pars.GetParameterByName (name, out idx);
+ if (par != null){
+ ParameterReference pr;
+
+ pr = new ParameterReference (pars, this, idx, name, loc);
+ return pr;
+ }
+ }
+ b = b.Parent;
+ } while (b != null);
+ return null;
+ }
+
+ //
+ // Whether the parameter named `name' is local to this block,
+ // or false, if the parameter belongs to an encompassing block.
+ //
+ public bool IsLocalParameter (string name)
+ {
+ Block b = this;
+ int toplevel_count = 0;
+
+ do {
+ if (this is ToplevelBlock)
+ toplevel_count++;
+
+ Parameters pars = b.parameters;
+ if (pars != null){
+ if (pars.GetParameterByName (name) != null)
+ return true;
+ return false;
+ }
+ if (toplevel_count > 0)
+ return false;
+ b = b.Parent;
+ } while (b != null);
+ return false;
+ }
+
+ //
+ // Whether the `name' is a parameter reference
+ //
+ public bool IsParameterReference (string name)
+ {
+ Block b = this;
+
+ do {
+ Parameters pars = b.parameters;
+
+ if (pars != null)
+ if (pars.GetParameterByName (name) != null)
+ return true;
+ b = b.Parent;
+ } while (b != null);
+ return false;
+ }
+
+ /// <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);
+ flags |= Flags.BlockUsed;
+ }
+
+ public bool Used {
+ get {
+ return (flags & Flags.BlockUsed) != 0;
+ }
+ }
+
+ public void Use ()
+ {
+ flags |= Flags.BlockUsed;
+ }
+
+ public bool HasRet {
+ get {
+ return (flags & Flags.HasRet) != 0;
+ }
+ }
+
+ public bool IsDestructor {
+ get {
+ return (flags & Flags.IsDestructor) != 0;
+ }
+ }
+
+ public void SetDestructor ()
+ {
+ flags |= Flags.IsDestructor;
+ }
+
+ VariableMap param_map, local_map;
+
+ public VariableMap ParameterMap {
+ get {
+ if ((flags & Flags.VariablesInitialized) == 0)
+ throw new Exception ("Variables have not been initialized yet");
+
+ return param_map;
+ }
+ }
+
+ public VariableMap LocalMap {
+ get {
+ if ((flags & Flags.VariablesInitialized) == 0)
+ throw new Exception ("Variables have not been initialized yet");
+
+ 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:
+ /// </remarks>
+ public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
+ {
+ ILGenerator ig = ec.ig;
+
+ bool old_unsafe = ec.InUnsafe;
+
+ // If some parent block was unsafe, we remain unsafe even if this block
+ // isn't explicitly marked as such.
+ ec.InUnsafe |= Unsafe;
+
+ //
+ // 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);
+
+ 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);
+ flags |= Flags.VariablesInitialized;
+
+ bool old_check_state = ec.ConstantCheckState;
+ ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
+
+ //
+ // 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 false
+ if (remap_locals)
+ vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
+ else if (vi.Pinned)
+ //
+ // This is needed to compile on both .NET 1.x and .NET 2.x
+ // the later introduced `DeclareLocal (Type t, bool pinned)'
+ //
+ vi.LocalBuilder = TypeManager.DeclareLocalPinned (ig, vi.VariableType);
+ else if (!vi.IsThis)
+ vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+#endif
+
+ 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;
+
+ Constant ce = e as Constant;
+ if (ce == null){
+ Report.Error (133, vi.Location,
+ "The expression being assigned to `" +
+ name + "' must be constant (" + e + ")");
+ continue;
+ }
+
+ if (e.Type != variable_type){
+ e = Const.ChangeType (vi.Location, ce, variable_type);
+ if (e == null)
+ 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.ResolveMeta (toplevel, ec, ip);
+ }
+ ec.InUnsafe = old_unsafe;
+ }
+
+ //
+ // Emits the local variable declarations for a block
+ //
+ public void EmitMeta (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (variables != null){
+ bool have_captured_vars = ec.HaveCapturedVariables ();
+ bool remap_locals = ec.RemapToProxy;
+
+ foreach (DictionaryEntry de in variables){
+ LocalInfo vi = (LocalInfo) de.Value;
+
+ if (have_captured_vars && ec.IsCaptured (vi))
+ continue;
+
+ if (remap_locals){
+ vi.FieldBuilder = ec.MapVariable (vi.Name, vi.VariableType);
+ } else {
+ if (vi.Pinned)
+ //
+ // This is needed to compile on both .NET 1.x and .NET 2.x
+ // the later introduced `DeclareLocal (Type t, bool pinned)'
+ //
+ vi.LocalBuilder = TypeManager.DeclareLocalPinned (ig, vi.VariableType);
+ else if (!vi.IsThis)
+ vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+ }
+ }
+ }
+
+ if (children != null){
+ foreach (Block b in children)
+ b.EmitMeta (ec);
+ }
+ }
+
+ void UsageWarning (FlowBranching.UsageVector vector)
+ {
+ string name;
+
+ if ((variables != null) && (RootContext.WarningLevel >= 3)) {
+ foreach (DictionaryEntry de in variables){
+ LocalInfo vi = (LocalInfo) de.Value;
+
+ if (vi.Used)
+ continue;
+
+ name = (string) de.Key;
+
+ if (vector.IsAssigned (vi.VariableInfo)){
+ Report.Warning (219, vi.Location, "The variable '{0}' is assigned but its value is never used", name);
+ } else {
+ Report.Warning (168, vi.Location, "The variable '{0}' is declared but never used", name);
+ }
+ }
+ }
+ }
+
+ bool unreachable_shown;
+
+ public override bool Resolve (EmitContext ec)
+ {
+ Block prev_block = ec.CurrentBlock;
+ bool ok = true;
+
+ int errors = Report.Errors;
+
+ ec.CurrentBlock = this;
+ ec.StartFlowBranching (this);
+
+ Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+
+ bool unreachable = false;
+
+ int statement_count = statements.Count;
+ for (int ix = 0; ix < statement_count; ix++){
+ Statement s = (Statement) statements [ix];
+
+ if (unreachable && !(s is LabeledStatement)) {
+ if (s == EmptyStatement.Value)
+ s.loc = EndLocation;
+
+ if (!s.ResolveUnreachable (ec, !unreachable_shown))
+ ok = false;
+
+ if (s != EmptyStatement.Value)
+ unreachable_shown = true;
+ else
+ s.loc = Location.Null;
+
+ statements [ix] = EmptyStatement.Value;
+ continue;
+ }
+
+ if (s.Resolve (ec) == false) {
+ ok = false;
+ statements [ix] = EmptyStatement.Value;
+ continue;
+ }
+
+ num_statements = ix + 1;
+
+ if (s is LabeledStatement)
+ unreachable = false;
+ else
+ unreachable = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
+ }
+
+ Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
+ ec.CurrentBranching, statement_count, num_statements);
+
+
+ FlowBranching.UsageVector vector = ec.DoEndFlowBranching ();
+
+ 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) &&
+ (vector.Reachability.Throws != FlowBranching.FlowReturns.Always) &&
+ !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");
+ }
+
+ Report.Debug (4, "RESOLVE BLOCK DONE #2", StartLocation, vector);
+
+ if ((vector.Reachability.Returns == FlowBranching.FlowReturns.Always) ||
+ (vector.Reachability.Throws == FlowBranching.FlowReturns.Always) ||
+ (vector.Reachability.Reachable == FlowBranching.FlowReturns.Never))
+ flags |= Flags.HasRet;
+
+ if (ok && (errors == Report.Errors)) {
+ if (RootContext.WarningLevel >= 3)
+ UsageWarning (vector);
+ }
+
+ return ok;
+ }
+
+ public override bool ResolveUnreachable (EmitContext ec, bool warn)
+ {
+ unreachable_shown = true;
+ return base.ResolveUnreachable (ec, warn);
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ for (int ix = 0; ix < num_statements; ix++){
+ Statement s = (Statement) statements [ix];
+
+ // Check whether we are the last statement in a
+ // top-level block.
+
+ if ((Parent == null) && (ix+1 == num_statements))
+ ec.IsLastStatement = true;
+ else
+ ec.IsLastStatement = false;
+
+ s.Emit (ec);
+ }
+ }
+
+ public override void 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;
+
+ ec.DefineLocalVariable (name, vi.LocalBuilder);
+ }
+ }
+ }
+
+ ec.Mark (StartLocation, true);
+ DoEmit (ec);
+ ec.Mark (EndLocation, true);
+
+ if (emit_debug_info && is_lexical_block)
+ ec.ig.EndScope ();
+
+ ec.CurrentBlock = prev_block;
+ }
+
+ public ToplevelBlock Toplevel {
+ get {
+ Block b = this;
+ while (b.Parent != null){
+ if ((b.flags & Flags.IsToplevel) != 0)
+ break;
+ b = b.Parent;
+ }
+
+ return (ToplevelBlock) b;
+ }
+ }
+
+ //
+ // Returns true if we ar ea child of `b'.
+ //
+ public bool IsChildOf (Block b)
+ {
+ Block current = this;
+
+ do {
+ if (current.Parent == b)
+ return true;
+ current = current.Parent;
+ } while (current != null);
+ return false;
+ }
+ }
+
+ //
+ // A toplevel block contains extra information, the split is done
+ // only to separate information that would otherwise bloat the more
+ // lightweight Block.
+ //
+ // In particular, this was introduced when the support for Anonymous
+ // Methods was implemented.
+ //
+ public class ToplevelBlock : Block {
+ //
+ // Pointer to the host of this anonymous method, or null
+ // if we are the topmost block
+ //
+ public ToplevelBlock Container;
+ CaptureContext capture_context;
+
+ Hashtable capture_contexts;
+
+ static int did = 0;
+
+ int my_id = did++;
+
+
+ public void RegisterCaptureContext (CaptureContext cc)
+ {
+ if (capture_contexts == null)
+ capture_contexts = new Hashtable ();
+ capture_contexts [cc] = cc;
+ }
+
+ public void CompleteContexts ()
+ {
+ if (capture_contexts == null)
+ return;
+
+ foreach (CaptureContext cc in capture_contexts.Keys){
+ cc.AdjustScopes ();
+ }
+ }
+
+ public CaptureContext ToplevelBlockCaptureContext {
+ get {
+ return capture_context;
+ }
+ }
+
+ //
+ // Parent is only used by anonymous blocks to link back to their
+ // parents
+ //
+ public ToplevelBlock (ToplevelBlock container, Parameters parameters, Location start) :
+ base (null, Flags.IsToplevel, parameters, start, Location.Null)
+ {
+ Container = container;
+ }
+
+ public ToplevelBlock (Parameters parameters, Location start) :
+ base (null, Flags.IsToplevel, parameters, start, Location.Null)
+ {
+ }
+
+ public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
+ base (null, flags | Flags.IsToplevel, parameters, start, Location.Null)
+ {
+ }
+
+ public ToplevelBlock (Location loc) : base (null, Flags.IsToplevel, loc, loc)
+ {
+ }
+
+ public void SetHaveAnonymousMethods (Location loc, AnonymousMethod host)
+ {
+ if (capture_context == null)
+ capture_context = new CaptureContext (this, loc, host);
+ }
+
+ public CaptureContext CaptureContext {
+ get {
+ return capture_context;
+ }
+ }
+ }
+
+ public class SwitchLabel {
+ Expression label;
+ object converted;
+ public Location loc;
+
+ Label il_label;
+ bool il_label_set;
+ Label il_label_code;
+ bool il_label_code_set;
+
+ //
+ // 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;
+ }
+ }
+
+ public Label GetILLabel (EmitContext ec)
+ {
+ if (!il_label_set){
+ il_label = ec.ig.DefineLabel ();
+ il_label_set = true;
+ }
+ return il_label;
+ }
+
+ public Label GetILLabelCode (EmitContext ec)
+ {
+ if (!il_label_code_set){
+ il_label_code = ec.ig.DefineLabel ();
+ il_label_code_set = true;
+ }
+ return il_label_code;
+ }
+
+ //
+ // 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)
+ {
+ 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;
+ 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;
+ bool is_constant;
+ SwitchSection constant_section;
+
+ //
+ // 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.int32_type,
+ TypeManager.uint32_type,
+ TypeManager.sbyte_type,
+ TypeManager.byte_type,
+ TypeManager.short_type,
+ TypeManager.ushort_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;
+
+ //
+ // Ignore over-worked ImplicitUserConversions that do
+ // an implicit conversion in addition to the user conversion.
+ //
+ if (e is UserCast){
+ UserCast ue = e as UserCast;
+
+ if (ue.Source != Expr)
+ e = null;
+ }
+
+ if (converted != null){
+ Report.ExtraInformation (
+ loc,
+ String.Format ("reason: more than one conversion to an integral type exist for type {0}",
+ TypeManager.CSharpName (Expr.Type)));
+ return null;
+ } else {
+ converted = e;
+ }
+ }
+ return converted;
+ }
+
+ static string Error152 {
+ get {
+ return "The label '{0}:' already occurs in 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){
+ Report.Error (152, sl.loc, 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){
+ Report.Error (152, sl.loc, 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;
+ // how many items are in the bucket
+ public int Size = 1;
+ 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>
+ void 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.Size + kb.Size) * 2 >= KeyBlock.TotalLength (kbCurr, kb))
+ {
+ // merge blocks
+ kbCurr.nLast = kb.nLast;
+ kbCurr.Size += kb.Size;
+ }
+ 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
+
+ Type compare_type;
+
+ if (TypeManager.IsEnumType (SwitchType))
+ compare_type = TypeManager.EnumToUnderlying (SwitchType);
+ else
+ compare_type = SwitchType;
+
+ 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.GetILLabel (ec));
+ }
+ }
+ 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 (compare_type == TypeManager.int64_type ||
+ compare_type == 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.nLast, 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.GetILLabel (ec);
+ 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;
+ foreach (SwitchSection ss in Sections)
+ {
+ foreach (SwitchLabel sl in ss.Labels)
+ {
+ ig.MarkLabel (sl.GetILLabel (ec));
+ ig.MarkLabel (sl.GetILLabelCode (ec));
+ if (sl.Label == null)
+ {
+ ig.MarkLabel (lblDefault);
+ fFoundDefault = true;
+ }
+ }
+ ss.Block.Emit (ec);
+ //ig.Emit (OpCodes.Br, lblEnd);
+ }
+
+ if (!fFoundDefault) {
+ ig.MarkLabel (lblDefault);
+ }
+ ig.MarkLabel (lblEnd);
+ }
+ //
+ // 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?
+ //
+ void 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 null_found;
+ bool default_at_end = false;
+
+ 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;
+ bool mark_default = false;
+ null_found = false;
+ for (int label = 0; label < label_count; label++){
+ SwitchLabel sl = (SwitchLabel) ss.Labels [label];
+ ig.MarkLabel (sl.GetILLabel (ec));
+
+ if (!first_test){
+ ig.MarkLabel (next_test);
+ next_test = ig.DefineLabel ();
+ }
+ //
+ // If we are the default target
+ //
+ if (sl.Label == null){
+ if (label+1 == label_count)
+ default_at_end = true;
+ mark_default = true;
+ 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.GetILLabelCode (ec));
+
+ if (mark_default)
+ ig.MarkLabel (default_target);
+ ss.Block.Emit (ec);
+ pending_goto_end = !ss.Block.HasRet;
+ first_test = false;
+ }
+ ig.MarkLabel (next_test);
+ if (default_found){
+ if (!default_at_end)
+ ig.Emit (OpCodes.Br, default_target);
+ } else
+ ig.MarkLabel (default_target);
+ ig.MarkLabel (end_of_switch);
+ }
+
+ SwitchSection FindSection (SwitchLabel label)
+ {
+ foreach (SwitchSection ss in Sections){
+ foreach (SwitchLabel sl in ss.Labels){
+ if (label == sl)
+ return ss;
+ }
+ }
+
+ return null;
+ }
+
+ bool ResolveConstantSwitch (EmitContext ec)
+ {
+ object key = ((Constant) new_expr).GetValue ();
+ SwitchLabel label = (SwitchLabel) Elements [key];
+
+ if (label == null)
+ return true;
+
+ constant_section = FindSection (label);
+ if (constant_section == null)
+ return true;
+
+ if (constant_section.Block.Resolve (ec) != true)
+ return false;
+
+ return true;
+ }
+
+ 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;
+
+ Report.Debug (1, "START OF SWITCH BLOCK", loc, ec.CurrentBranching);
+ ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
+
+ is_constant = new_expr is Constant;
+ if (is_constant) {
+ object key = ((Constant) new_expr).GetValue ();
+ SwitchLabel label = (SwitchLabel) Elements [key];
+
+ constant_section = FindSection (label);
+ }
+
+ bool first = true;
+ foreach (SwitchSection ss in Sections){
+ if (!first)
+ ec.CurrentBranching.CreateSibling (
+ null, FlowBranching.SiblingType.SwitchSection);
+ else
+ first = false;
+
+ if (is_constant && (ss != constant_section)) {
+ // If we're a constant switch, we're only emitting
+ // one single section - mark all the others as
+ // unreachable.
+ ec.CurrentBranching.CurrentUsageVector.Goto ();
+ if (!ss.Block.ResolveUnreachable (ec, true))
+ return false;
+ } else {
+ if (!ss.Block.Resolve (ec))
+ return false;
+ }
+ }
+
+ if (!got_default)
+ ec.CurrentBranching.CreateSibling (
+ null, FlowBranching.SiblingType.SwitchSection);
+
+ FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+ ec.Switch = old_switch;
+
+ Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching,
+ reachability);
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ // Store variable for comparission purposes
+ LocalBuilder value;
+ if (!is_constant) {
+ value = ig.DeclareLocal (SwitchType);
+ new_expr.Emit (ec);
+ ig.Emit (OpCodes.Stloc, value);
+ } else
+ value = null;
+
+ 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.
+ if (is_constant) {
+ if (constant_section != null)
+ constant_section.Block.Emit (ec);
+ } else if (SwitchType == TypeManager.string_type)
+ SimpleSwitchEmit (ec, value);
+ else
+ TableSwitchEmit (ec, value);
+
+ // Restore context state.
+ ig.MarkLabel (ec.LoopEnd);
+
+ //
+ // Restore the previous context
+ //
+ ec.LoopEnd = old_end;
+ ec.Switch = old_switch;
+ }
+ }
+
+ public abstract class ExceptionStatement : Statement
+ {
+ public abstract void EmitFinally (EmitContext ec);
+
+ protected bool emit_finally = true;
+ ArrayList parent_vectors;
+
+ protected void DoEmitFinally (EmitContext ec)
+ {
+ if (emit_finally)
+ ec.ig.BeginFinallyBlock ();
+ else
+ ec.CurrentIterator.MarkFinally (ec, parent_vectors);
+ EmitFinally (ec);
+ }
+
+ protected void ResolveFinally (FlowBranchingException branching)
+ {
+ emit_finally = branching.EmitFinally;
+ if (!emit_finally)
+ branching.Parent.StealFinallyClauses (ref parent_vectors);
+ }
+ }
+
+ public class Lock : ExceptionStatement {
+ Expression expr;
+ Statement Statement;
+ LocalBuilder temp;
+
+ 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);
+ if (expr == null)
+ return false;
+
+ if (expr.Type.IsValueType){
+ Error (185, "lock statement requires the expression to be " +
+ " a reference type (type is: `{0}'",
+ TypeManager.CSharpName (expr.Type));
+ return false;
+ }
+
+ FlowBranchingException branching = ec.StartFlowBranching (this);
+ bool ok = Statement.Resolve (ec);
+ if (!ok) {
+ ec.KillFlowBranching ();
+ return false;
+ }
+
+ ResolveFinally (branching);
+
+ FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+ if (reachability.Returns != FlowBranching.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.NeedReturnLabel ();
+ }
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ Type type = expr.Type;
+
+ ILGenerator ig = ec.ig;
+ 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
+ if (emit_finally)
+ ig.BeginExceptionBlock ();
+ Statement.Emit (ec);
+
+ // finally
+ DoEmitFinally (ec);
+ if (emit_finally)
+ ig.EndExceptionBlock ();
+ }
+
+ public override void EmitFinally (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ ig.Emit (OpCodes.Ldloc, temp);
+ ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
+ }
+ }
+
+ 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 void DoEmit (EmitContext ec)
+ {
+ bool previous_state = ec.CheckState;
+ bool previous_state_const = ec.ConstantCheckState;
+
+ ec.CheckState = false;
+ ec.ConstantCheckState = false;
+ Block.Emit (ec);
+ ec.CheckState = previous_state;
+ ec.ConstantCheckState = previous_state_const;
+ }
+ }
+
+ 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 void DoEmit (EmitContext ec)
+ {
+ bool previous_state = ec.CheckState;
+ bool previous_state_const = ec.ConstantCheckState;
+
+ ec.CheckState = true;
+ ec.ConstantCheckState = true;
+ Block.Emit (ec);
+ ec.CheckState = previous_state;
+ ec.ConstantCheckState = previous_state_const;
+ }
+ }
+
+ public class Unsafe : Statement {
+ public readonly Block Block;
+
+ public Unsafe (Block b)
+ {
+ Block = b;
+ Block.Unsafe = true;
+ }
+
+ 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 void DoEmit (EmitContext ec)
+ {
+ bool previous_state = ec.InUnsafe;
+
+ ec.InUnsafe = true;
+ Block.Emit (ec);
+ ec.InUnsafe = previous_state;
+ }
+ }
+
+ //
+ // Fixed statement
+ //
+ public class Fixed : Statement {
+ Expression type;
+ ArrayList declarators;
+ Statement statement;
+ Type expr_type;
+ FixedData[] data;
+ bool has_ret;
+
+ 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;
+ }
+
+ TypeExpr texpr = type.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return false;
+
+ expr_type = texpr.Type;
+
+ CheckObsolete (expr_type);
+
+ 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.SetAssigned (ec);
+ vi.ReadOnly = true;
+
+ //
+ // 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.
+ //
+
+ if (e is Cast){
+ Report.Error (254, loc, "Cast expression not allowed as right hand expression in fixed statement");
+ return false;
+ }
+
+ //
+ // Case 1: & object.
+ //
+ if (e is Unary && ((Unary) e).Oper == Unary.Operator.AddressOf){
+ Expression child = ((Unary) e).Expr;
+
+ 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);
+
+ //
+ // 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++;
+ continue;
+ }
+
+ //
+ // For other cases, flag a `this is already fixed expression'
+ //
+ if (e is LocalVariableReference || e is ParameterReference ||
+ Convert.ImplicitConversionExists (ec, e, vi.VariableType)){
+
+ Report.Error (245, loc, "right hand expression is already fixed, no need to use fixed statement ");
+ return false;
+ }
+
+ Report.Error (245, loc, "Fixed statement only allowed on strings, arrays or address-of expressions");
+ return false;
+ }
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
+
+ if (!statement.Resolve (ec)) {
+ ec.KillFlowBranching ();
+ return false;
+ }
+
+ FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+ has_ret = reachability.IsUnreachable;
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ 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 = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
+ 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);
+ }
+ }
+
+ statement.Emit (ec);
+
+ if (has_ret)
+ return;
+
+ //
+ // Clear the pinned variable
+ //
+ for (int i = 0; i < data.Length; i++) {
+ 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]);
+ }
+ }
+ }
+ }
+
+ public class Catch: Statement {
+ public readonly string Name;
+ public readonly Block Block;
+
+ Expression type_expr;
+ Type type;
+
+ public Catch (Expression type, string name, Block block, Location l)
+ {
+ type_expr = type;
+ Name = name;
+ Block = block;
+ loc = l;
+ }
+
+ public Type CatchType {
+ get {
+ return type;
+ }
+ }
+
+ public bool IsGeneral {
+ get {
+ return type_expr == null;
+ }
+ }
+
+ protected override void DoEmit(EmitContext ec)
+ {
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ if (type_expr != null) {
+ TypeExpr te = type_expr.ResolveAsTypeTerminal (ec);
+ if (te == null)
+ return false;
+
+ type = te.Type;
+
+ CheckObsolete (type);
+
+ if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
+ Error (155, "The type caught or thrown must be derived from System.Exception");
+ return false;
+ }
+ } else
+ type = null;
+
+ return Block.Resolve (ec);
+ }
+ }
+
+ public class Try : ExceptionStatement {
+ public readonly Block Fini, Block;
+ public readonly ArrayList Specific;
+ public readonly Catch General;
+
+ bool need_exc_block;
+
+ //
+ // 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;
+
+ FlowBranchingException branching = ec.StartFlowBranching (this);
+
+ Report.Debug (1, "START OF TRY BLOCK", Block.StartLocation);
+
+ if (!Block.Resolve (ec))
+ ok = false;
+
+ FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+ Report.Debug (1, "START OF CATCH BLOCKS", vector);
+
+ Type[] prevCatches = new Type [Specific.Count];
+ int last_index = 0;
+ foreach (Catch c in Specific){
+ ec.CurrentBranching.CreateSibling (
+ c.Block, FlowBranching.SiblingType.Catch);
+
+ 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;
+ }
+
+ if (!c.Resolve (ec))
+ return false;
+
+ Type resolvedType = c.CatchType;
+ for (int ii = 0; ii < last_index; ++ii) {
+ if (resolvedType == prevCatches [ii] || resolvedType.IsSubclassOf (prevCatches [ii])) {
+ Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type '{0}'", prevCatches [ii].FullName);
+ return false;
+ }
+ }
+
+ prevCatches [last_index++] = resolvedType;
+ need_exc_block = true;
+ }
+
+ Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
+
+ if (General != null){
+ ec.CurrentBranching.CreateSibling (
+ General.Block, FlowBranching.SiblingType.Catch);
+
+ Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
+
+ if (!General.Resolve (ec))
+ ok = false;
+
+ need_exc_block = true;
+ }
+
+ Report.Debug (1, "END OF GENERAL CATCH BLOCKS", ec.CurrentBranching);
+
+ if (Fini != null) {
+ if (ok)
+ ec.CurrentBranching.CreateSibling (
+ Fini, FlowBranching.SiblingType.Finally);
+
+ Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
+
+ if (!Fini.Resolve (ec))
+ ok = false;
+ }
+
+ ResolveFinally (branching);
+ need_exc_block |= emit_finally;
+
+ FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+
+ FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
+
+ Report.Debug (1, "END OF TRY", ec.CurrentBranching, reachability, vector, f_vector);
+
+ if (reachability.Returns != FlowBranching.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.NeedReturnLabel ();
+ }
+
+ return ok;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (need_exc_block)
+ ig.BeginExceptionBlock ();
+ Block.Emit (ec);
+
+ 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);
+
+ c.Block.Emit (ec);
+ }
+
+ if (General != null){
+ ig.BeginCatchBlock (TypeManager.object_type);
+ ig.Emit (OpCodes.Pop);
+ General.Block.Emit (ec);
+ }
+
+ DoEmitFinally (ec);
+ if (need_exc_block)
+ ig.EndExceptionBlock ();
+ }
+
+ public override void EmitFinally (EmitContext ec)
+ {
+ if (Fini != null){
+ Fini.Emit (ec);
+ }
+ }
+ }
+
+ public class Using : ExceptionStatement {
+ object expression_or_block;
+ Statement Statement;
+ ArrayList var_list;
+ Expression expr;
+ Type expr_type;
+ Expression conv;
+ Expression [] resolved_vars;
+ Expression [] converted_vars;
+ ExpressionStatement [] assign;
+ LocalBuilder local_copy;
+
+ 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)
+ {
+ int i = 0;
+
+ TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return false;
+
+ expr_type = texpr.Type;
+
+ //
+ // The type must be an IDisposable or an implicit conversion
+ // must exist.
+ //
+ converted_vars = new Expression [var_list.Count];
+ resolved_vars = new Expression [var_list.Count];
+ assign = new ExpressionStatement [var_list.Count];
+
+ bool need_conv = !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;
+
+ resolved_vars [i] = var;
+
+ if (!need_conv) {
+ i++;
+ continue;
+ }
+
+ converted_vars [i] = Convert.ImplicitConversionRequired (
+ ec, var, TypeManager.idisposable_type, loc);
+
+ if (converted_vars [i] == null)
+ return false;
+
+ i++;
+ }
+
+ i = 0;
+ foreach (DictionaryEntry e in var_list){
+ Expression var = resolved_vars [i];
+ 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.
+ //
+ void EmitLocalVariableDecls (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ int i = 0;
+
+ for (i = 0; i < assign.Length; i++) {
+ assign [i].EmitStatement (ec);
+
+ if (emit_finally)
+ ig.BeginExceptionBlock ();
+ }
+ Statement.Emit (ec);
+
+ var_list.Reverse ();
+
+ DoEmitFinally (ec);
+ }
+
+ void EmitLocalVariableDeclFinally (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ int i = assign.Length;
+ foreach (DictionaryEntry e in var_list){
+ Expression var = resolved_vars [--i];
+ Label skip = ig.DefineLabel ();
+
+ ig.BeginFinallyBlock ();
+
+ if (!var.Type.IsValueType) {
+ var.Emit (ec);
+ ig.Emit (OpCodes.Brfalse, skip);
+ converted_vars [i].Emit (ec);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ } else {
+ Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, var.Type, "Dispose", Mono.CSharp.Location.Null);
+
+ if (!(ml is MethodGroupExpr)) {
+ var.Emit (ec);
+ ig.Emit (OpCodes.Box, var.Type);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ } else {
+ MethodInfo mi = null;
+
+ foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+ if (TypeManager.GetArgumentTypes (mk).Length == 0) {
+ mi = mk;
+ break;
+ }
+ }
+
+ if (mi == null) {
+ Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+ return;
+ }
+
+ IMemoryLocation mloc = (IMemoryLocation) var;
+
+ mloc.AddressOf (ec, AddressOp.Load);
+ ig.Emit (OpCodes.Call, mi);
+ }
+ }
+
+ ig.MarkLabel (skip);
+
+ if (emit_finally) {
+ ig.EndExceptionBlock ();
+ if (i > 0)
+ ig.BeginFinallyBlock ();
+ }
+ }
+ }
+
+ void EmitExpression (EmitContext ec)
+ {
+ //
+ // Make a copy of the expression and operate on that.
+ //
+ ILGenerator ig = ec.ig;
+ local_copy = ig.DeclareLocal (expr_type);
+ if (conv != null)
+ conv.Emit (ec);
+ else
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Stloc, local_copy);
+
+ if (emit_finally)
+ ig.BeginExceptionBlock ();
+
+ Statement.Emit (ec);
+
+ DoEmitFinally (ec);
+ if (emit_finally)
+ ig.EndExceptionBlock ();
+ }
+
+ void EmitExpressionFinally (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ if (!local_copy.LocalType.IsValueType) {
+ Label skip = ig.DefineLabel ();
+ 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);
+ } else {
+ Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, local_copy.LocalType, "Dispose", Mono.CSharp.Location.Null);
+
+ if (!(ml is MethodGroupExpr)) {
+ ig.Emit (OpCodes.Ldloc, local_copy);
+ ig.Emit (OpCodes.Box, local_copy.LocalType);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ } else {
+ MethodInfo mi = null;
+
+ foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+ if (TypeManager.GetArgumentTypes (mk).Length == 0) {
+ mi = mk;
+ break;
+ }
+ }
+
+ if (mi == null) {
+ Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+ return;
+ }
+
+ ig.Emit (OpCodes.Ldloca, local_copy);
+ ig.Emit (OpCodes.Call, mi);
+ }
+ }
+ }
+
+ 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;
+ }
+
+ FlowBranchingException branching = ec.StartFlowBranching (this);
+
+ bool ok = Statement.Resolve (ec);
+
+ if (!ok) {
+ ec.KillFlowBranching ();
+ return false;
+ }
+
+ ResolveFinally (branching);
+ FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+
+ if (reachability.Returns != FlowBranching.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.NeedReturnLabel ();
+ }
+
+ return true;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ if (expression_or_block is DictionaryEntry)
+ EmitLocalVariableDecls (ec);
+ else if (expression_or_block is Expression)
+ EmitExpression (ec);
+ }
+
+ public override void EmitFinally (EmitContext ec)
+ {
+ if (expression_or_block is DictionaryEntry)
+ EmitLocalVariableDeclFinally (ec);
+ else if (expression_or_block is Expression)
+ EmitExpressionFinally (ec);
+ }
+ }
+
+ /// <summary>
+ /// Implementation of the foreach C# statement
+ /// </summary>
+ public class Foreach : ExceptionStatement {
+ Expression type;
+ Expression variable;
+ Expression expr;
+ Statement statement;
+ ForeachHelperMethods hm;
+ Expression empty, conv;
+ Type array_type, element_type;
+ Type var_type;
+ VariableStorage enumerator;
+
+ 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;
+
+ TypeExpr texpr = type.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return false;
+
+ var_type = texpr.Type;
+
+ //
+ // 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);
+ }
+
+ bool ok = true;
+
+ ec.StartFlowBranching (FlowBranching.BranchingType.Loop, 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)
+ ok = false;
+
+ variable = variable.ResolveLValue (ec, empty);
+ if (variable == null)
+ ok = false;
+
+ bool disposable = (hm != null) && hm.is_disposable;
+ FlowBranchingException branching = null;
+ if (disposable)
+ branching = ec.StartFlowBranching (this);
+
+ if (!statement.Resolve (ec))
+ ok = false;
+
+ if (disposable) {
+ ResolveFinally (branching);
+ ec.EndFlowBranching ();
+ } else
+ emit_finally = true;
+
+ ec.EndFlowBranching ();
+
+ return ok;
+ }
+
+ //
+ // 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 (TypeManager.TypeToCoreType (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 get_current_list;
+
+ get_current_list = TypeContainer.FindMembers (
+ t, MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.Instance,
+ Type.FilterName, "get_Current");
+ if (get_current_list.Count == 0)
+ return null;
+
+ foreach (MemberInfo m in get_current_list){
+ MethodInfo mi = (MethodInfo) m;
+ Type [] args;
+
+ args = TypeManager.GetArgumentTypes (mi);
+ if (args != null && args.Length == 0)
+ return mi;
+ }
+ return null;
+ }
+
+ //
+ // Retrieves a `public void Dispose ()' method from the Type `t'
+ //
+ static MethodInfo FetchMethodDispose (Type t)
+ {
+ MemberList dispose_list;
+
+ dispose_list = TypeContainer.FindMembers (
+ t, MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.Instance,
+ Type.FilterName, "Dispose");
+ if (dispose_list.Count == 0)
+ return null;
+
+ foreach (MemberInfo m in dispose_list){
+ MethodInfo mi = (MethodInfo) m;
+ Type [] args;
+
+ args = TypeManager.GetArgumentTypes (mi);
+ if (args != null && args.Length == 0){
+ if (mi.ReturnType == TypeManager.void_type)
+ 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 public
+ if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
+ return false;
+
+ if ((mi.ReturnType == TypeManager.ienumerator_type) && (mi.DeclaringType == 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'
+ //
+
+ Type return_type = mi.ReturnType;
+ if (mi.ReturnType == TypeManager.ienumerator_type ||
+ TypeManager.ienumerator_type.IsAssignableFrom (return_type) ||
+ (!RootContext.StdLib && TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type))) {
+
+ //
+ // If it is not an interface, lets try to find the methods ourselves.
+ // For example, if we have:
+ // public class Foo : IEnumerator { public bool MoveNext () {} public int Current { get {}}}
+ // We can avoid the iface call. This is a runtime perf boost.
+ // even bigger if we have a ValueType, because we avoid the cost
+ // of boxing.
+ //
+ // We have to make sure that both methods exist for us to take
+ // this path. If one of the methods does not exist, we will just
+ // use the interface. Sadly, this complex if statement is the only
+ // way I could do this without a goto
+ //
+
+ if (return_type.IsInterface ||
+ (hm.move_next = FetchMethodMoveNext (return_type)) == null ||
+ (hm.get_current = FetchMethodGetCurrent (return_type)) == null) {
+
+ hm.move_next = TypeManager.bool_movenext_void;
+ hm.get_current = TypeManager.object_getcurrent_void;
+ return true;
+ }
+
+ } else {
+
+ //
+ // Ok, so they dont return an IEnumerable, we will have to
+ // find if they support the GetEnumerator pattern.
+ //
+
+ 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 | BindingFlags.DeclaredOnly,
+ 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);
+
+ for (Type tt = t; tt != null && tt != TypeManager.object_type;){
+ if (TryType (tt, hm))
+ return hm;
+ tt = tt.BaseType;
+ }
+
+ //
+ // 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;
+
+ enumerator = new VariableStorage (ec, hm.enumerator_type);
+ enumerator.EmitThis (ig);
+ //
+ // Instantiate the enumerator
+ //
+ if (expr.Type.IsValueType){
+ IMemoryLocation ml = expr as IMemoryLocation;
+ // Load the address of the value type.
+ if (ml == null) {
+ // This happens if, for example, you have a property
+ // returning a struct which is IEnumerable
+ LocalBuilder t = ec.GetTemporaryLocal (expr.Type);
+ expr.Emit(ec);
+ ig.Emit (OpCodes.Stloc, t);
+ ig.Emit (OpCodes.Ldloca, t);
+ ec.FreeTemporaryLocal (t, expr.Type);
+ } else {
+ ml.AddressOf (ec, AddressOp.Load);
+ }
+
+ // Emit the call.
+ if (hm.get_enumerator.DeclaringType.IsValueType) {
+ // the method is declared on the value type
+ ig.Emit (OpCodes.Call, hm.get_enumerator);
+ } else {
+ // it is an interface method, so we must box
+ ig.Emit (OpCodes.Box, expr.Type);
+ ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
+ }
+ } else {
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
+ }
+ enumerator.EmitStore (ig);
+
+ //
+ // Protect the code in a try/finalize block, so that
+ // if the beast implement IDisposable, we get rid of it
+ //
+ if (hm.is_disposable && emit_finally)
+ ig.BeginExceptionBlock ();
+
+ Label end_try = ig.DefineLabel ();
+
+ ig.MarkLabel (ec.LoopBegin);
+
+ enumerator.EmitCall (ig, hm.move_next);
+
+ ig.Emit (OpCodes.Brfalse, end_try);
+
+ if (ec.InIterator)
+ enumerator.EmitThis (ig);
+ enumerator.EmitCall (ig, hm.get_current);
+
+ if (ec.InIterator){
+ conv.Emit (ec);
+ ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
+ } else
+ ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
+
+ statement.Emit (ec);
+ ig.Emit (OpCodes.Br, ec.LoopBegin);
+ ig.MarkLabel (end_try);
+
+ // The runtime provides this for us.
+ // ig.Emit (OpCodes.Leave, end);
+
+ //
+ // Now the finally block
+ //
+ if (hm.is_disposable) {
+ DoEmitFinally (ec);
+ if (emit_finally)
+ ig.EndExceptionBlock ();
+ }
+
+ ig.MarkLabel (ec.LoopEnd);
+ return false;
+ }
+
+ public override void EmitFinally (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (hm.enumerator_type.IsValueType) {
+ enumerator.EmitThis (ig);
+
+ MethodInfo mi = FetchMethodDispose (hm.enumerator_type);
+ if (mi != null) {
+ enumerator.EmitLoadAddress (ig);
+ ig.Emit (OpCodes.Call, mi);
+ } else {
+ enumerator.EmitLoad (ig);
+ ig.Emit (OpCodes.Box, hm.enumerator_type);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ }
+ } else {
+ Label call_dispose = ig.DefineLabel ();
+
+ enumerator.EmitThis (ig);
+ enumerator.EmitLoad (ig);
+ ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
+ ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Brtrue_S, call_dispose);
+ ig.Emit (OpCodes.Pop);
+
+ Label end_finally = ig.DefineLabel ();
+ ig.Emit (OpCodes.Br, end_finally);
+
+ ig.MarkLabel (call_dispose);
+ ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+ ig.MarkLabel (end_finally);
+
+ if (emit_finally)
+ ig.Emit (OpCodes.Endfinally);
+ }
+ }
+
+ //
+ // 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;
+
+ VariableStorage copy = new VariableStorage (ec, array_type);
+
+ //
+ // Make our copy of the array
+ //
+ copy.EmitThis (ig);
+ expr.Emit (ec);
+ copy.EmitStore (ig);
+
+ if (rank == 1){
+ VariableStorage counter = new VariableStorage (ec,TypeManager.int32_type);
+
+ Label loop, test;
+
+ counter.EmitThis (ig);
+ ig.Emit (OpCodes.Ldc_I4_0);
+ counter.EmitStore (ig);
+ test = ig.DefineLabel ();
+ ig.Emit (OpCodes.Br, test);
+
+ loop = ig.DefineLabel ();
+ ig.MarkLabel (loop);
+
+ if (ec.InIterator)
+ ec.EmitThis ();
+
+ copy.EmitThis (ig);
+ copy.EmitLoad (ig);
+ counter.EmitThis (ig);
+ counter.EmitLoad (ig);
+
+ //
+ // 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);
+ if (ec.InIterator){
+ conv.Emit (ec);
+ ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
+ } else
+ ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
+
+ statement.Emit (ec);
+
+ ig.MarkLabel (ec.LoopBegin);
+ counter.EmitThis (ig);
+ counter.EmitThis (ig);
+ counter.EmitLoad (ig);
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Add);
+ counter.EmitStore (ig);
+
+ ig.MarkLabel (test);
+ counter.EmitThis (ig);
+ counter.EmitLoad (ig);
+ copy.EmitThis (ig);
+ copy.EmitLoad (ig);
+ ig.Emit (OpCodes.Ldlen);
+ ig.Emit (OpCodes.Conv_I4);
+ ig.Emit (OpCodes.Blt, loop);
+ } else {
+ VariableStorage [] dim_len = new VariableStorage [rank];
+ VariableStorage [] dim_count = new VariableStorage [rank];
+ Label [] loop = new Label [rank];
+ Label [] test = new Label [rank];
+ int dim;
+
+ for (dim = 0; dim < rank; dim++){
+ dim_len [dim] = new VariableStorage (ec, TypeManager.int32_type);
+ dim_count [dim] = new VariableStorage (ec, TypeManager.int32_type);
+ test [dim] = ig.DefineLabel ();
+ loop [dim] = ig.DefineLabel ();
+ }
+
+ for (dim = 0; dim < rank; dim++){
+ dim_len [dim].EmitThis (ig);
+ copy.EmitThis (ig);
+ copy.EmitLoad (ig);
+ IntLiteral.EmitInt (ig, dim);
+ ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
+ dim_len [dim].EmitStore (ig);
+
+ }
+
+ for (dim = 0; dim < rank; dim++){
+ dim_count [dim].EmitThis (ig);
+ ig.Emit (OpCodes.Ldc_I4_0);
+ dim_count [dim].EmitStore (ig);
+ ig.Emit (OpCodes.Br, test [dim]);
+ ig.MarkLabel (loop [dim]);
+ }
+
+ if (ec.InIterator)
+ ec.EmitThis ();
+ copy.EmitThis (ig);
+ copy.EmitLoad (ig);
+ for (dim = 0; dim < rank; dim++){
+ dim_count [dim].EmitThis (ig);
+ dim_count [dim].EmitLoad (ig);
+ }
+
+ //
+ // 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.Module.Builder;
+ get = mb.GetArrayMethod (
+ array_type, "Get",
+ CallingConventions.HasThis| CallingConventions.Standard,
+ var_type, args);
+ ig.Emit (OpCodes.Call, get);
+ if (ec.InIterator){
+ conv.Emit (ec);
+ ig.Emit (OpCodes.Stfld, ((LocalVariableReference) variable).local_info.FieldBuilder);
+ } else
+ ((IAssignMethod)variable).EmitAssign (ec, conv, false, false);
+ statement.Emit (ec);
+ ig.MarkLabel (ec.LoopBegin);
+ for (dim = rank - 1; dim >= 0; dim--){
+ dim_count [dim].EmitThis (ig);
+ dim_count [dim].EmitThis (ig);
+ dim_count [dim].EmitLoad (ig);
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Add);
+ dim_count [dim].EmitStore (ig);
+
+ ig.MarkLabel (test [dim]);
+ dim_count [dim].EmitThis (ig);
+ dim_count [dim].EmitLoad (ig);
+ dim_len [dim].EmitThis (ig);
+ dim_len [dim].EmitLoad (ig);
+ ig.Emit (OpCodes.Blt, loop [dim]);
+ }
+ }
+ ig.MarkLabel (ec.LoopEnd);
+
+ return false;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
+ ec.LoopBegin = ig.DefineLabel ();
+ ec.LoopEnd = ig.DefineLabel ();
+
+ if (hm != null)
+ EmitCollectionForeach (ec);
+ else
+ EmitArrayForeach (ec);
+
+ ec.LoopBegin = old_begin;
+ ec.LoopEnd = old_end;
+ }
+ }
+}
--- /dev/null
+//
+// 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.IO;
+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);
+ GenericConstraints GenericConstraints (int pos);
+ int Count { get; }
+ bool HasParams { get; }
+ string ParameterName (int pos);
+ string ParameterDesc (int pos);
+ Parameter.Modifier ParameterModifier (int pos);
+ }
+
+ public class ReflectionParameters : ParameterData {
+ ParameterInfo [] pi;
+ Type[] type_params;
+ bool last_arg_is_params = false;
+ bool is_varargs = false;
+ ParameterData gpd;
+
+ public ReflectionParameters (MethodBase mb)
+ {
+ object [] attrs;
+
+ ParameterInfo [] pi = mb.GetParameters ();
+ is_varargs = (mb.CallingConvention & CallingConventions.VarArgs) != 0;
+
+ this.pi = pi;
+ int count = pi.Length-1;
+
+ if (count < 0)
+ return;
+
+ if (mb.Mono_IsInflatedMethod) {
+ MethodInfo generic = mb.GetGenericMethodDefinition ();
+ gpd = Invocation.GetParameterData (generic);
+
+ last_arg_is_params = gpd.HasParams;
+ return;
+ }
+
+ if (mb.IsGenericMethodDefinition)
+ type_params = mb.GetGenericArguments ();
+
+ 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 if (is_varargs && pos >= pi.Length)
+ return TypeManager.runtime_argument_handle_type;
+ else {
+ Type t = pi [pos].ParameterType;
+
+ return t;
+ }
+ }
+
+ public GenericConstraints GenericConstraints (int pos)
+ {
+ if (gpd != null)
+ return gpd.GenericConstraints (pos);
+
+ if (type_params == null)
+ return null;
+
+ return new ReflectionConstraints (type_params [pos]);
+ }
+
+ public string ParameterName (int pos)
+ {
+ if (gpd != null)
+ return gpd.ParameterName (pos);
+
+ if (last_arg_is_params && pos >= pi.Length - 1)
+ return pi [pi.Length - 1].Name;
+ else if (is_varargs && pos >= pi.Length)
+ return "__arglist";
+ else
+ return pi [pos].Name;
+ }
+
+ public string ParameterDesc (int pos)
+ {
+ if (is_varargs && pos >= pi.Length)
+ return "";
+
+ 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 (last_arg_is_params && pos >= pi.Length - 1)
+ return Parameter.Modifier.PARAMS;
+ else if (is_varargs && pos >= pi.Length)
+ return Parameter.Modifier.ARGLIST;
+
+ if (gpd != null)
+ return gpd.ParameterModifier (pos);
+
+ 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 is_varargs ? pi.Length + 1 : pi.Length;
+ }
+ }
+
+ public bool HasParams {
+ get {
+ return this.last_arg_is_params;
+ }
+ }
+ }
+
+ public class InternalParameters : ParameterData {
+ Type [] param_types;
+ bool has_varargs;
+ int count;
+
+ public readonly Parameters Parameters;
+ public readonly TypeParameter[] TypeParameters;
+
+ public InternalParameters (Type [] param_types, Parameters parameters)
+ {
+ this.param_types = param_types;
+ this.Parameters = parameters;
+
+ has_varargs = parameters.HasArglist;
+
+ if (param_types == null)
+ count = 0;
+ else
+ count = param_types.Length;
+ }
+
+ public InternalParameters (Type [] param_types, Parameters parameters,
+ TypeParameter [] type_params)
+ : this (param_types, parameters)
+ {
+ this.TypeParameters = type_params;
+ }
+
+ public int Count {
+ get {
+ return has_varargs ? count + 1 : count;
+ }
+ }
+
+ public bool HasParams {
+ get {
+ return Parameters.ArrayParameter != null;
+ }
+ }
+
+ 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 (has_varargs && pos >= count)
+ return TypeManager.runtime_argument_handle_type;
+
+ if (param_types == null)
+ return null;
+
+ return GetParameter (pos).ExternalType ();
+ }
+
+ public GenericConstraints GenericConstraints (int pos)
+ {
+ if (TypeParameters == null)
+ return null;
+
+ return TypeParameters [pos].Constraints;
+ }
+
+ public string ParameterName (int pos)
+ {
+ if (has_varargs && pos >= count)
+ return "__arglist";
+
+ return GetParameter (pos).Name;
+ }
+
+ public string ParameterDesc (int pos)
+ {
+ if (has_varargs && pos >= count)
+ return "__arglist";
+
+ 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)
+ {
+ if (has_varargs && pos >= count)
+ return Parameter.Modifier.ARGLIST;
+
+ Parameter.Modifier mod = GetParameter (pos).ModFlags;
+
+ if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+ mod |= Parameter.Modifier.ISBYREF;
+
+ return mod;
+ }
+
+ }
+
+ public class ReflectionConstraints : GenericConstraints
+ {
+ GenericParameterAttributes attrs;
+ Type base_type;
+ Type class_constraint;
+ Type[] iface_constraints;
+
+ public ReflectionConstraints (Type t)
+ {
+ Type[] constraints = t.GetGenericParameterConstraints ();
+ if ((constraints.Length > 0) && !constraints [0].IsInterface) {
+ class_constraint = constraints [0];
+ iface_constraints = new Type [constraints.Length - 1];
+ Array.Copy (constraints, 1, iface_constraints, 0, constraints.Length - 1);
+ } else
+ iface_constraints = constraints;
+ attrs = t.GenericParameterAttributes;
+
+ if (HasValueTypeConstraint)
+ base_type = TypeManager.value_type;
+ else if (class_constraint != null)
+ base_type = class_constraint;
+ else
+ base_type = TypeManager.object_type;
+ }
+
+ public override GenericParameterAttributes Attributes {
+ get { return attrs; }
+ }
+
+ public override Type ClassConstraint {
+ get { return class_constraint; }
+ }
+
+ public override Type EffectiveBaseClass {
+ get { return base_type; }
+ }
+
+ public override Type[] InterfaceConstraints {
+ get { return iface_constraints; }
+ }
+ }
+
+ class PtrHashtable : Hashtable {
+ sealed class PtrComparer : IComparer {
+ private PtrComparer () {}
+
+ public static PtrComparer Instance = new PtrComparer ();
+
+ public int Compare (object x, object y)
+ {
+ if (x == y)
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ public PtrHashtable ()
+ {
+ comparer = PtrComparer.Instance;
+ }
+ }
+
+ /*
+ * Hashtable whose keys are character arrays with the same length
+ */
+ class CharArrayHashtable : Hashtable {
+ sealed class ArrComparer : IComparer {
+ private int len;
+
+ public ArrComparer (int len) {
+ this.len = len;
+ }
+
+ public int Compare (object x, object y)
+ {
+ char[] a = (char[])x;
+ char[] b = (char[])y;
+
+ for (int i = 0; i < len; ++i)
+ if (a [i] != b [i])
+ return 1;
+ return 0;
+ }
+ }
+
+ private int len;
+
+ protected override int GetHash (Object key)
+ {
+ char[] arr = (char[])key;
+ int h = 0;
+
+ for (int i = 0; i < len; ++i)
+ h = (h << 5) - h + arr [i];
+
+ return h;
+ }
+
+ public CharArrayHashtable (int len)
+ {
+ this.len = len;
+ comparer = new ArrComparer (len);
+ }
+ }
+
+ struct Pair {
+ public object First;
+ public object Second;
+
+ public Pair (object f, object s)
+ {
+ First = f;
+ Second = s;
+ }
+ }
+
+ /// <summary>
+ /// This is a wrapper around StreamReader which is seekable.
+ /// </summary>
+ public class SeekableStreamReader
+ {
+ public SeekableStreamReader (StreamReader reader)
+ {
+ this.reader = reader;
+ this.buffer = new char [DefaultCacheSize];
+
+ // Compute the preamble size
+
+ // Let the StreamWriter autodetect the encoder
+ reader.Peek ();
+
+ reader.BaseStream.Position = 0;
+ Encoding enc = reader.CurrentEncoding;
+ // First of all, get at least a char
+
+ byte[] auxb = new byte [50];
+ int num_bytes = 0;
+ int num_chars = 0;
+ int br = 0;
+ do {
+ br = reader.BaseStream.Read (auxb, num_bytes, auxb.Length - num_bytes);
+ num_bytes += br;
+ num_chars = enc.GetCharCount (auxb, 0, num_bytes);
+ }
+ while (num_chars == 0 && br > 0);
+
+ if (num_chars != 0)
+ {
+ // Now, check which bytes at the beginning have no effect in the
+ // char count
+
+ int p = 0;
+ while (enc.GetCharCount (auxb, p, num_bytes-p) >= num_chars)
+ p++;
+
+ preamble_size = p - 1;
+ reader.BaseStream.Position = 0;
+ reader.DiscardBufferedData ();
+
+ buffer_start = preamble_size;
+ }
+ }
+
+ public SeekableStreamReader (Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks)
+ : this (new StreamReader (stream, encoding, detect_encoding_from_bytemarks))
+ { }
+
+ StreamReader reader;
+
+ private const int DefaultCacheSize = 1024;
+
+ char[] buffer;
+ int buffer_start; // in bytes
+ int buffer_size; // in bytes
+ int char_count; // count buffer[] valid characters
+ int pos; // index into buffer[]
+ int preamble_size;
+
+ /// <remarks>
+ /// The difference to the StreamReader's BaseStream.Position is that this one is reliable; ie. it
+ // always reports the correct position and if it's modified, it also takes care of the buffered data.
+ /// </remarks>
+ public int Position {
+ get {
+ return buffer_start + reader.CurrentEncoding.GetByteCount (buffer, 0, pos);
+ }
+
+ set {
+ // This one is easy: we're modifying the position within our current
+ // buffer.
+ if ((value >= buffer_start) && (value < buffer_start + buffer_size)) {
+ int byte_offset = value - buffer_start;
+ pos = byte_offset;
+ // encoded characters can take more than 1 byte length
+ while (reader.CurrentEncoding.GetByteCount (buffer, 0, pos) > byte_offset)
+ pos--;
+
+ return;
+ }
+
+ if (value == 0) // Skip preamble
+ value = preamble_size;
+
+ // Ok, now we need to seek.
+ reader.DiscardBufferedData ();
+ reader.BaseStream.Position = buffer_start = value;
+ char_count = buffer_size = pos = 0;
+ }
+ }
+
+ private bool ReadBuffer ()
+ {
+ pos = 0;
+ buffer_start += buffer_size;
+ char_count = reader.Read (buffer, 0, buffer.Length);
+ buffer_size = reader.CurrentEncoding.GetByteCount (buffer, 0, char_count);
+ return buffer_size > 0;
+ }
+
+ public int Peek ()
+ {
+ if ((pos >= char_count) && !ReadBuffer ())
+ return -1;
+
+ return buffer [pos];
+ }
+
+ public int Read ()
+ {
+ if ((pos >= char_count) && !ReadBuffer ())
+ return -1;
+
+ return buffer [pos++];
+ }
+ }
+
+ public class DoubleHash {
+ const int DEFAULT_INITIAL_BUCKETS = 100;
+
+ public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {}
+
+ public DoubleHash (int size)
+ {
+ count = size;
+ buckets = new Entry [size];
+ }
+
+ int count;
+ Entry [] buckets;
+ int size = 0;
+
+ class Entry {
+ public object key1;
+ public object key2;
+ public int hash;
+ public object value;
+ public Entry next;
+
+ public Entry (object key1, object key2, int hash, object value, Entry next)
+ {
+ this.key1 = key1;
+ this.key2 = key2;
+ this.hash = hash;
+ this.next = next;
+ this.value = value;
+ }
+ }
+
+ public bool Lookup (object a, object b, out object res)
+ {
+ int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
+
+ for (Entry e = buckets [h % count]; e != null; e = e.next) {
+ if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) {
+ res = e.value;
+ return true;
+ }
+ }
+ res = null;
+ return false;
+ }
+
+ public void Insert (object a, object b, object value)
+ {
+ // Is it an existing one?
+
+ int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF;
+
+ for (Entry e = buckets [h % count]; e != null; e = e.next) {
+ if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b))
+ e.value = value;
+ }
+
+ int bucket = h % count;
+ buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]);
+
+ // Grow whenever we double in size
+ if (size++ == count) {
+ count <<= 1;
+ count ++;
+
+ Entry [] newBuckets = new Entry [count];
+ foreach (Entry root in buckets) {
+ Entry e = root;
+ while (e != null) {
+ int newLoc = e.hash % count;
+ Entry n = e.next;
+ e.next = newBuckets [newLoc];
+ newBuckets [newLoc] = e;
+ e = n;
+ }
+ }
+
+ buckets = newBuckets;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// 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 Mono.CompilerServices.SymbolWriter;
+
+namespace Mono.CSharp {
+ public class SymbolWriter : MonoSymbolWriter {
+ delegate int GetILOffsetFunc (ILGenerator ig);
+ delegate Guid GetGuidFunc (ModuleBuilder mb);
+
+ GetILOffsetFunc get_il_offset_func;
+ GetGuidFunc get_guid_func;
+
+ ModuleBuilder module_builder;
+
+ protected SymbolWriter (ModuleBuilder module_builder, string filename)
+ : base (filename)
+ {
+ this.module_builder = module_builder;
+ }
+
+ bool Initialize ()
+ {
+ MethodInfo mi = typeof (ILGenerator).GetMethod (
+ "Mono_GetCurrentOffset",
+ BindingFlags.Static | BindingFlags.NonPublic);
+ if (mi == null)
+ return false;
+
+ get_il_offset_func = (GetILOffsetFunc) System.Delegate.CreateDelegate (
+ typeof (GetILOffsetFunc), mi);
+
+ mi = typeof (ModuleBuilder).GetMethod (
+ "Mono_GetGuid",
+ BindingFlags.Static | BindingFlags.NonPublic);
+ if (mi == null)
+ return false;
+
+ get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate (
+ typeof (GetGuidFunc), mi);
+
+ Location.DefineSymbolDocuments (this);
+ Namespace.DefineNamespaces (this);
+
+ return true;
+ }
+
+ public void DefineLocalVariable (string name, LocalBuilder builder)
+ {
+ SignatureHelper sighelper = SignatureHelper.GetLocalVarSigHelper (
+ module_builder);
+ sighelper.AddArgument (builder.LocalType);
+ byte[] signature = sighelper.GetSignature ();
+
+ DefineLocalVariable (name, signature);
+ }
+
+ public void MarkSequencePoint (ILGenerator ig, int row, int column)
+ {
+ int offset = get_il_offset_func (ig);
+ MarkSequencePoint (offset, row, column);
+ }
+
+ public void WriteSymbolFile ()
+ {
+ Guid guid = get_guid_func (module_builder);
+ WriteSymbolFile (guid);
+ }
+
+ public static SymbolWriter GetSymbolWriter (ModuleBuilder module,
+ string filename)
+ {
+ SymbolWriter writer = new SymbolWriter (module, filename);
+ if (!writer.Initialize ())
+ return null;
+
+ return writer;
+ }
+ }
+}
--- /dev/null
+//
+// 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 all the types definied (classes, structs, ifaces, enums)
+ // </summary>
+ Hashtable decls;
+
+ public Tree ()
+ {
+ root_types = new RootTypes ();
+
+ decls = new Hashtable ();
+ }
+
+ DoubleHash decl_ns_name = new DoubleHash ();
+
+ public void RecordDecl (string name, DeclSpace ds)
+ {
+ DeclSpace other = (DeclSpace) decls [name];
+ if (other != null){
+ PartialContainer other_pc = other as PartialContainer;
+ if ((ds is TypeContainer) && (other_pc != null)) {
+ Report.Error (
+ 260, ds.Location, "Missing partial modifier " +
+ "on declaration of type `{0}'; another " +
+ "partial implementation of this type exists",
+ name);
+
+ Report.LocationOfPreviousError (other.Location);
+ return;
+ }
+
+ Report.SymbolRelatedToPreviousError (
+ other.Location, other.GetSignatureForError ());
+
+ Report.Error (
+ 101, ds.Location,
+ "There is already a definition for `" + name + "'");
+ return;
+ }
+
+ ds.RecordDecl ();
+
+ int p = name.LastIndexOf ('.');
+ if (p == -1)
+ decl_ns_name.Insert ("", name, ds);
+ else {
+ decl_ns_name.Insert (name.Substring (0, p), name.Substring (p+1), ds);
+ }
+
+ decls.Add (name, ds);
+ }
+
+ public DeclSpace LookupByNamespace (string ns, string name)
+ {
+ object res;
+
+ decl_ns_name.Lookup (ns, name, out res);
+ return (DeclSpace) res;
+ }
+
+ //
+ // FIXME: Why are we using Types?
+ //
+ public TypeContainer Types {
+ get {
+ return root_types;
+ }
+ }
+
+ public Hashtable Decls {
+ get {
+ return decls;
+ }
+ }
+ }
+
+ public class RootTypes : TypeContainer
+ {
+ public RootTypes ()
+ : base (null, null, MemberName.Null, null, Kind.Root, Location.Null)
+ {
+ ec = new EmitContext (null, this, Location.Null, null, null, 0, false);
+ }
+
+ public override void Register ()
+ {
+ throw new InvalidOperationException ();
+ }
+
+ public override PendingImplementation GetPendingImplementations ()
+ {
+ throw new InvalidOperationException ();
+ }
+ }
+}
--- /dev/null
+//
+// 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 partial 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 null_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 iconvertible_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 runtime_argument_handle_type;
+ static public Type attribute_type;
+ static public Type attribute_usage_type;
+ static public Type decimal_constant_attribute_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 Type not_supported_exception_type;
+ static public Type obsolete_attribute_type;
+ static public Type conditional_attribute_type;
+ static public Type in_attribute_type;
+ static public Type anonymous_method_type;
+ static public Type cls_compliant_attribute_type;
+ static public Type typed_reference_type;
+ static public Type arg_iterator_type;
+ static public Type mbr_type;
+ static public Type struct_layout_attribute_type;
+ static public Type field_offset_attribute_type;
+ static public Type security_attr_type;
+
+ //
+ // An empty array of types
+ //
+ static public Type [] NoTypes;
+ static public TypeExpr [] NoTypeExprs;
+
+
+ //
+ // Expressions representing the internal types. Used during declaration
+ // definition.
+ //
+ static public TypeExpr system_object_expr, system_string_expr;
+ static public TypeExpr system_boolean_expr, system_decimal_expr;
+ static public TypeExpr system_single_expr, system_double_expr;
+ static public TypeExpr system_sbyte_expr, system_byte_expr;
+ static public TypeExpr system_int16_expr, system_uint16_expr;
+ static public TypeExpr system_int32_expr, system_uint32_expr;
+ static public TypeExpr system_int64_expr, system_uint64_expr;
+ static public TypeExpr system_char_expr, system_void_expr;
+ static public TypeExpr system_asynccallback_expr;
+ static public TypeExpr system_iasyncresult_expr;
+ static public TypeExpr system_valuetype_expr;
+ static public TypeExpr system_intptr_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_string_dot_dot_dot;
+ static public MethodInfo string_concat_object_object;
+ static public MethodInfo string_concat_object_object_object;
+ static public MethodInfo string_concat_object_dot_dot_dot;
+ 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 void_decimal_ctor_int_arg;
+ static public ConstructorInfo unverifiable_code_ctor;
+ static public ConstructorInfo invalid_operation_ctor;
+ static public ConstructorInfo default_member_ctor;
+ static public ConstructorInfo decimal_constant_attribute_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 modules. We used this to do lookups
+ // on the module using GetType -- needed for arrays
+ // </remarks>
+ static Module [] 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;
+
+ static PtrHashtable builder_to_member_cache;
+
+ // <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 methods
+ // </remarks>
+
+ static Hashtable builder_to_method;
+
+ // <remarks>
+ // Contains all public types from referenced assemblies.
+ // This member is used only if CLS Compliance verification is required.
+ // </remarks>
+ public static Hashtable all_imported_types;
+
+ struct Signature {
+ public string name;
+ public Type [] args;
+ }
+
+ public static void CleanUp ()
+ {
+ // Lets get everything clean so that we can collect before generating code
+ assemblies = null;
+ modules = null;
+ types = null;
+ typecontainers = null;
+ user_types = null;
+ builder_to_declspace = null;
+ builder_to_member_cache = null;
+ builder_to_ifaces = null;
+ method_arguments = null;
+ indexer_arguments = null;
+ method_internal_params = null;
+ builder_to_method = null;
+
+ fields = null;
+ references = null;
+ negative_hits = null;
+ builder_to_constant = null;
+ fieldbuilders_to_fields = null;
+ events = null;
+ priv_fields_events = null;
+ properties = null;
+
+ CleanUpGenerics ();
+ TypeHandle.CleanUp ();
+ }
+
+ /// <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");
+ system_valuetype_expr = new TypeLookupExpression ("System.ValueType");
+ system_intptr_expr = new TypeLookupExpression ("System.IntPtr");
+ }
+
+ 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_member_cache = 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];
+ NoTypeExprs = new TypeExpr [0];
+
+ signature_filter = new MemberFilter (SignatureFilter);
+ InitGenerics ();
+ 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;
+ }
+
+ 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)
+ {
+ try {
+ types.Add (name, t);
+ } catch {
+ HandleDuplicate (name, t);
+ }
+ user_types.Add (t);
+ }
+
+ //
+ // This entry point is used by types that we define under the covers
+ //
+ public static void RegisterBuilder (Type tb, Type [] ifaces)
+ {
+ if (ifaces != null)
+ builder_to_ifaces [tb] = ifaces;
+ }
+
+ public static void AddUserType (string name, TypeBuilder t, TypeContainer tc)
+ {
+ builder_to_declspace.Add (t, tc);
+ typecontainers.Add (name, tc);
+ AddUserType (name, t);
+ }
+
+ 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 AddMethod (MethodBase builder, IMethodData method)
+ {
+ builder_to_method.Add (builder, method);
+ }
+
+ public static IMethodData GetMethod (MethodBase builder)
+ {
+ return (IMethodData) builder_to_method [builder];
+ }
+
+ /// <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 MemberCache LookupMemberCache (Type t)
+ {
+ if (t is TypeBuilder) {
+ IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
+ if (container != null)
+ return container.MemberCache;
+ }
+
+ if (t is GenericTypeParameterBuilder) {
+ IMemberContainer container = builder_to_type_param [t] as IMemberContainer;
+
+ if (container != null)
+ return container.MemberCache;
+ }
+
+ return TypeHandle.GetMemberCache (t);
+ }
+
+ public static MemberCache LookupParentInterfacesCache (Type t)
+ {
+ Type [] ifaces = t.GetInterfaces ();
+
+ if (ifaces != null && ifaces.Length == 1)
+ return LookupMemberCache (ifaces [0]);
+
+ // TODO: the builder_to_member_cache should be indexed by 'ifaces', not 't'
+ MemberCache cache = builder_to_member_cache [t] as MemberCache;
+ if (cache != null)
+ return cache;
+
+ cache = new MemberCache (ifaces);
+ builder_to_member_cache.Add (t, cache);
+ return cache;
+ }
+
+ public static TypeContainer LookupInterface (Type t)
+ {
+ TypeContainer tc = (TypeContainer) builder_to_declspace [t];
+ if ((tc == null) || (tc.Kind != Kind.Interface))
+ return null;
+
+ return tc;
+ }
+
+ 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 Class LookupClass (Type t)
+ {
+ return (Class) builder_to_declspace [t];
+ }
+
+ /// <summary>
+ /// Registers an assembly to load types from.
+ /// </summary>
+ public static void AddAssembly (Assembly a)
+ {
+ foreach (Assembly assembly in assemblies) {
+ if (a == assembly)
+ return;
+ }
+
+ int top = assemblies.Length;
+ Assembly [] n = new Assembly [top + 1];
+
+ assemblies.CopyTo (n, 0);
+
+ n [top] = a;
+ assemblies = n;
+ }
+
+ public static Assembly [] GetAssemblies ()
+ {
+ return assemblies;
+ }
+
+ /// <summary>
+ /// Registers a module builder to lookup types from
+ /// </summary>
+ public static void AddModule (Module mb)
+ {
+ int top = modules != null ? modules.Length : 0;
+ Module [] n = new Module [top + 1];
+
+ if (modules != null)
+ modules.CopyTo (n, 0);
+ n [top] = mb;
+ modules = n;
+ }
+
+ public static Module[] Modules {
+ get {
+ return modules;
+ }
+ }
+
+ static Hashtable references = new Hashtable ();
+
+ //
+ // Gets the reference to T version of the Type (T&)
+ //
+ public static Type GetReferenceType (Type t)
+ {
+ return t.MakeByRefType ();
+ }
+
+ 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.Module.Builder.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;
+
+ do {
+ TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
+ if (ta == TypeAttributes.NotPublic ||
+ ta == TypeAttributes.NestedPrivate ||
+ ta == TypeAttributes.NestedAssembly ||
+ ta == TypeAttributes.NestedFamANDAssem){
+
+ //
+ // In .NET pointers turn out to be private, even if their
+ // element type is not
+ //
+ if (t.IsPointer){
+ t = t.GetElementType ();
+ continue;
+ } else
+ t = null;
+ } else {
+ return t;
+ }
+ } while (t != null);
+ }
+
+ foreach (Module 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;
+ }
+
+ static readonly char [] dot_array = { '.' };
+
+ /// <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;
+
+ // Sadly, split takes a param array, so this ends up allocating *EVERY TIME*
+ string [] elements = name.Split (dot_array);
+ 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] = null;
+ 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] = null;
+ else
+ types [name] = t;
+ return t;
+ }
+ negative_hits [name] = null;
+ 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", BindingFlags.Instance|BindingFlags.NonPublic);
+
+ //
+ // First add the assembly namespaces
+ //
+ if (assembly_get_namespaces != null){
+ int count = assemblies.Length;
+
+ 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 {
+ Hashtable cache = new Hashtable ();
+ cache.Add ("", null);
+ foreach (Assembly a in assemblies) {
+ foreach (Type t in a.GetExportedTypes ()) {
+ string ns = t.Namespace;
+ if (ns == null || cache.Contains (ns))
+ continue;
+
+ Namespace.LookupNamespace (ns, true);
+ cache.Add (ns, null);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Fills static table with exported types from all referenced assemblies.
+ /// This information is required for CLS Compliance tests.
+ /// </summary>
+ public static void LoadAllImportedTypes ()
+ {
+ all_imported_types = new Hashtable ();
+ foreach (Assembly a in assemblies) {
+ foreach (Type t in a.GetExportedTypes ()) {
+ all_imported_types [t.FullName] = t;
+ }
+ }
+ }
+
+ 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)
+ {
+ if (t.FullName == null)
+ return t.Name;
+
+ return Regex.Replace (t.FullName,
+ @"^System\." +
+ @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
+ @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
+ @"Boolean|String|Void|Null)" +
+ @"(\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 with full namespace classification
+ /// </summary>
+ static public string GetFullNameSignature (MemberInfo mi)
+ {
+ return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
+ }
+
+ static public string GetFullNameSignature (MethodBase mb)
+ {
+ string name = mb.Name;
+ if (name == ".ctor")
+ name = mb.DeclaringType.Name;
+
+ if (mb.IsSpecialName) {
+ if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
+ name = name.Remove (0, 4);
+ }
+
+ if (name == "Item")
+ name = "this";
+ }
+
+ return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
+ }
+
+ static public string GetFullName (Type t)
+ {
+ if (t.FullName == null)
+ return t.Name;
+
+ string name = t.FullName.Replace ('+', '.');
+
+ DeclSpace tc = LookupDeclSpace (t);
+ if ((tc != null) && tc.IsGeneric) {
+ TypeParameter[] tparam = tc.TypeParameters;
+
+ StringBuilder sb = new StringBuilder (name);
+ sb.Append ("<");
+ for (int i = 0; i < tparam.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (tparam [i].Name);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ } else if (t.HasGenericArguments && !t.IsGenericInstance) {
+ Type[] tparam = t.GetGenericArguments ();
+
+ StringBuilder sb = new StringBuilder (name);
+ sb.Append ("<");
+ for (int i = 0; i < tparam.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (tparam [i].Name);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ }
+
+ return name;
+ }
+
+ /// <summary>
+ /// Returns the signature of the property and indexer
+ /// </summary>
+ static public string CSharpSignature (PropertyBuilder pb, bool is_indexer)
+ {
+ if (!is_indexer) {
+ return GetFullNameSignature (pb);
+ }
+
+ MethodBase mb = pb.GetSetMethod (true) != null ? pb.GetSetMethod (true) : pb.GetGetMethod (true);
+ string signature = GetFullNameSignature (mb);
+ string arg = TypeManager.LookupParametersByBuilder (mb).ParameterDesc (0);
+ return String.Format ("{0}.this[{1}]", signature.Substring (0, signature.LastIndexOf ('.')), arg);
+ }
+
+ /// <summary>
+ /// Returns the signature of the method
+ /// </summary>
+ static public string CSharpSignature (MethodBase mb)
+ {
+ StringBuilder sig = new StringBuilder ("(");
+
+ //
+ // 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)
+ iparams = new ReflectionParameters (mb);
+
+ // Is property
+ if (mb.IsSpecialName && iparams.Count == 0 && !mb.IsConstructor)
+ return GetFullNameSignature (mb);
+
+ for (int i = 0; i < iparams.Count; i++) {
+ if (i > 0) {
+ sig.Append (", ");
+ }
+ sig.Append (iparams.ParameterDesc (i));
+ }
+ sig.Append (")");
+
+ // Is indexer
+ if (mb.IsSpecialName && iparams.Count == 1 && !mb.IsConstructor) {
+ sig.Replace ('(', '[');
+ sig.Replace (')', ']');
+ }
+
+ return GetFullNameSignature (mb) + sig.ToString ();
+ }
+
+ public static string GetMethodName (MethodInfo m)
+ {
+ if (!IsGenericMethod (m))
+ return m.Name;
+
+ return MemberName.MakeName (m.Name, m.GetGenericArguments ().Length);
+ }
+
+ /// <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 (1);
+ }
+
+ 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 is_private, bool report_errors)
+ {
+ MemberList list;
+ Signature sig;
+ BindingFlags flags = instance_and_static | BindingFlags.Public;
+
+ sig.name = name;
+ sig.args = args;
+
+ if (is_private)
+ flags |= BindingFlags.NonPublic;
+
+ list = FindMembers (t, MemberTypes.Method, flags, 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, bool report_errors)
+ {
+ return GetMethod (t, name, args, false, report_errors);
+ }
+
+ 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_argument_handle_type = CoreLookupType ("System.RuntimeArgumentHandle");
+ 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");
+ iconvertible_type = CoreLookupType ("System.IConvertible");
+ 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");
+ typed_reference_type = CoreLookupType ("System.TypedReference");
+ arg_iterator_type = CoreLookupType ("System.ArgIterator");
+ mbr_type = CoreLookupType ("System.MarshalByRefObject");
+ decimal_constant_attribute_type = CoreLookupType ("System.Runtime.CompilerServices.DecimalConstantAttribute");
+
+ //
+ // 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");
+ not_supported_exception_type = CoreLookupType ("System.NotSupportedException");
+
+ //
+ // Attribute types
+ //
+ obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
+ conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
+ cls_compliant_attribute_type = CoreLookupType ("System.CLSCompliantAttribute");
+ struct_layout_attribute_type = CoreLookupType ("System.Runtime.InteropServices.StructLayoutAttribute");
+ field_offset_attribute_type = CoreLookupType ("System.Runtime.InteropServices.FieldOffsetAttribute");
+ security_attr_type = CoreLookupType ("System.Security.Permissions.SecurityAttribute");
+
+ InitGenericCoreTypes ();
+
+ //
+ // 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, true, 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.Assembly.Builder, 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, 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.Assembly.Builder, args);
+ }
+ }
+
+ system_object_expr.Type = object_type;
+ system_string_expr.Type = string_type;
+ system_boolean_expr.Type = bool_type;
+ system_decimal_expr.Type = decimal_type;
+ system_single_expr.Type = float_type;
+ system_double_expr.Type = double_type;
+ system_sbyte_expr.Type = sbyte_type;
+ system_byte_expr.Type = byte_type;
+ system_int16_expr.Type = short_type;
+ system_uint16_expr.Type = ushort_type;
+ system_int32_expr.Type = int32_type;
+ system_uint32_expr.Type = uint32_type;
+ system_int64_expr.Type = int64_type;
+ system_uint64_expr.Type = uint64_type;
+ system_char_expr.Type = char_type;
+ system_void_expr.Type = void_type;
+ system_asynccallback_expr.Type = asynccallback_type;
+ system_iasyncresult_expr.Type = iasyncresult_type;
+ system_valuetype_expr.Type = value_type;
+
+ //
+ // These are only used for compare purposes
+ //
+ anonymous_method_type = typeof (AnonymousMethod);
+ null_type = typeof (NullType);
+ }
+
+ //
+ // 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[] params_string = { TypeManager.LookupType ("System.String[]") };
+ string_concat_string_dot_dot_dot = GetMethod (
+ string_type, "Concat", params_string);
+
+ Type [] object_object = { object_type, object_type };
+ string_concat_object_object = GetMethod (
+ string_type, "Concat", object_object);
+ Type [] object_object_object = { object_type, object_type, object_type };
+ string_concat_object_object_object = GetMethod (
+ string_type, "Concat", object_object_object);
+ Type[] params_object = { TypeManager.LookupType ("System.Object[]") };
+ string_concat_object_dot_dot_dot = GetMethod (
+ string_type, "Concat", params_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);
+
+ void_decimal_ctor_int_arg = GetConstructor (decimal_type, int_arg);
+
+ //
+ // Attributes
+ //
+ cons_param_array_attribute = GetConstructor (
+ param_array_type, void_arg);
+
+ unverifiable_code_ctor = GetConstructor (
+ unverifiable_code_type, void_arg);
+
+ decimal_constant_attribute_ctor = GetConstructor (decimal_constant_attribute_type, new Type []
+ { byte_type, byte_type, uint32_type, uint32_type, uint32_type } );
+
+ default_member_ctor = GetConstructor (default_member_type, string_);
+
+ //
+ // InvalidOperationException
+ //
+ invalid_operation_ctor = GetConstructor (
+ invalid_operation_exception_type, void_arg);
+
+
+ // Object
+ object_ctor = GetConstructor (object_type, void_arg);
+
+ InitGenericCodeHelpers ();
+ }
+
+ const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
+
+ /// <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));
+
+ if (t is GenericTypeParameterBuilder) {
+ TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
+
+ Timer.StartTimer (TimerType.FindMembers);
+ MemberList list = tparam.FindMembers (
+ mt, bf | BindingFlags.DeclaredOnly, filter, criteria);
+ Timer.StopTimer (TimerType.FindMembers);
+ return list;
+ }
+
+ //
+ // 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 MemberInfo [] MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+ string name, out bool used_cache)
+ {
+ MemberCache cache;
+
+ //
+ // 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];
+ 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.
+ // Note, this is a VERY uncommon route!
+
+ MemberList list;
+ Timer.StartTimer (TimerType.FindMembers);
+ list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+ FilterWithClosure_delegate, name);
+ Timer.StopTimer (TimerType.FindMembers);
+ used_cache = false;
+ return (MemberInfo []) list;
+ }
+
+ if (t is GenericTypeParameterBuilder) {
+ TypeParameter tparam = (TypeParameter) builder_to_type_param [t];
+
+ MemberList list;
+ Timer.StartTimer (TimerType.FindMembers);
+ list = tparam.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+ FilterWithClosure_delegate, name);
+ Timer.StopTimer (TimerType.FindMembers);
+ used_cache = false;
+ return (MemberInfo []) list;
+ }
+
+ //
+ // This call will always succeed. There is exactly one TypeHandle instance per
+ // type, TypeHandle.GetMemberCache() will, if necessary, create a new one, and return
+ // the corresponding MemberCache.
+ //
+ cache = TypeHandle.GetMemberCache (t);
+
+ used_cache = true;
+ return cache.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;
+ }
+
+ public static bool IsBuiltinType (TypeContainer tc)
+ {
+ return IsBuiltinType (tc.TypeBuilder);
+ }
+
+ //
+ // 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.IsGenericInstance)
+ t = t.GetGenericTypeDefinition ();
+
+ if (t.IsSubclassOf (TypeManager.delegate_type))
+ return true;
+ else
+ return false;
+ }
+
+ public static bool IsEnumType (Type t)
+ {
+ if (t.IsSubclassOf (TypeManager.enum_type))
+ return true;
+ else
+ return false;
+ }
+ public static bool IsBuiltinOrEnum (Type t)
+ {
+ if (IsBuiltinType (t))
+ return true;
+
+ if (IsEnumType (t))
+ return true;
+
+ return false;
+ }
+
+ public static bool IsNullType (Type t)
+ {
+ return t == null_type;
+ }
+
+ //
+ // 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);
+
+ if (tc.Fields != null){
+ foreach (Field f in tc.Fields){
+ if (f.FieldBuilder.IsStatic)
+ continue;
+ if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+ return false;
+ }
+ } else
+ return true;
+ } 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)
+ {
+ return t.IsGenericParameter || t.IsValueType;
+ }
+
+ public static bool IsInterfaceType (Type t)
+ {
+ TypeContainer tc = (TypeContainer) builder_to_declspace [t];
+ if (tc == null)
+ return false;
+
+ return tc.Kind == Kind.Interface;
+ }
+
+ public static bool IsSubclassOf (Type type, Type parent)
+ {
+ TypeParameter tparam = LookupTypeParameter (type);
+ TypeParameter pparam = LookupTypeParameter (parent);
+
+ if ((tparam != null) && (pparam != null)) {
+ if (tparam == pparam)
+ return true;
+
+ return tparam.IsSubclassOf (parent);
+ }
+
+ do {
+ if (type.Equals (parent))
+ return true;
+
+ type = type.BaseType;
+ } while (type != null);
+
+ return false;
+ }
+
+ public static bool IsPrivateAccessible (Type type, Type parent)
+ {
+ if (type.Equals (parent))
+ return true;
+
+ if ((type is TypeBuilder) && type.IsGenericTypeDefinition && parent.IsGenericInstance) {
+ //
+ // `a' is a generic type definition's TypeBuilder and `b' is a
+ // generic instance of the same type.
+ //
+ // Example:
+ //
+ // class Stack<T>
+ // {
+ // void Test (Stack<T> stack) { }
+ // }
+ //
+ // The first argument of `Test' will be the generic instance
+ // "Stack<!0>" - which is the same type than the "Stack" TypeBuilder.
+ //
+ //
+ // We hit this via Closure.Filter() for gen-82.cs.
+ //
+ if (type != parent.GetGenericTypeDefinition ())
+ return false;
+
+ return true;
+ }
+
+ if (type.IsGenericInstance && parent.IsGenericInstance) {
+ Type tdef = type.GetGenericTypeDefinition ();
+ Type pdef = parent.GetGenericTypeDefinition ();
+
+ if (type.GetGenericTypeDefinition () != parent.GetGenericTypeDefinition ())
+ return false;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public static bool IsFamilyAccessible (Type type, Type parent)
+ {
+ TypeParameter tparam = LookupTypeParameter (type);
+ TypeParameter pparam = LookupTypeParameter (parent);
+
+ if ((tparam != null) && (pparam != null)) {
+ if (tparam == pparam)
+ return true;
+
+ return tparam.IsSubclassOf (parent);
+ }
+
+ do {
+ if (IsEqualGenericInstance (type, parent))
+ return true;
+
+ type = type.BaseType;
+ } while (type != null);
+
+ return false;
+ }
+
+ //
+ // Checks whether `type' is a subclass or nested child of `parent'.
+ //
+ public static bool IsNestedFamilyAccessible (Type type, Type parent)
+ {
+ do {
+ if (IsFamilyAccessible (type, 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 (IsEqual (type, parent))
+ return false;
+
+ type = type.DeclaringType;
+ while (type != null) {
+ if (IsEqual (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 are compiling corlib or not
+ //
+ 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 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 void RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
+ {
+ if (args == null)
+ args = NoTypes;
+
+ method_arguments.Add (mb, args);
+ method_internal_params.Add (mb, ip);
+ }
+
+ 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)
+ {
+ object t = method_arguments [mb];
+ if (t != null)
+ return (Type []) t;
+
+ ParameterInfo [] pi = mb.GetParameters ();
+ int c = pi.Length;
+ Type [] types;
+
+ if (c == 0) {
+ types = NoTypes;
+ } else {
+ 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;
+ }
+
+ //
+ // The return value can be null; This will be the case for
+ // auxiliary FieldBuilders created by the compiler that have no
+ // real field being declared on the source code
+ //
+ static public FieldBase GetField (FieldInfo fb)
+ {
+ return (FieldBase) fieldbuilders_to_fields [fb];
+ }
+
+ static Hashtable events;
+
+ static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
+ {
+ if (events == null)
+ events = new Hashtable ();
+
+ if (!events.Contains (eb)) {
+ events.Add (eb, new Pair (add, remove));
+ }
+ }
+
+ static public MethodInfo GetAddMethod (EventInfo ei)
+ {
+ if (ei is MyEventBuilder) {
+ Pair pair = (Pair) events [ei];
+
+ return (MethodInfo) pair.First;
+ }
+ return ei.GetAddMethod (true);
+ }
+
+ static public MethodInfo GetRemoveMethod (EventInfo ei)
+ {
+ if (ei is MyEventBuilder) {
+ Pair pair = (Pair) events [ei];
+
+ return (MethodInfo) pair.Second;
+ }
+ return ei.GetRemoveMethod (true);
+ }
+
+ 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;
+ }
+
+ public static bool CheckStructCycles (TypeContainer tc, Hashtable seen)
+ {
+ Hashtable hash = new Hashtable ();
+ return CheckStructCycles (tc, seen, hash);
+ }
+
+ public static bool CheckStructCycles (TypeContainer tc, Hashtable seen,
+ Hashtable hash)
+ {
+ if ((tc.Kind != Kind.Struct) || IsBuiltinType (tc))
+ return true;
+
+ //
+ // `seen' contains all types we've already visited.
+ //
+ if (seen.Contains (tc))
+ return true;
+ seen.Add (tc, null);
+
+ if (tc.Fields == null)
+ return true;
+
+ foreach (Field field in tc.Fields) {
+ if (field.FieldBuilder.IsStatic)
+ continue;
+
+ Type ftype = field.FieldBuilder.FieldType;
+ TypeContainer ftc = LookupTypeContainer (ftype);
+ if (ftc == null)
+ continue;
+
+ if (hash.Contains (ftc)) {
+ Report.Error (523, tc.Location,
+ "Struct member `{0}.{1}' of type `{2}' " +
+ "causes a cycle in the struct layout",
+ tc.Name, field.Name, ftc.Name);
+ return false;
+ }
+
+ //
+ // `hash' contains all types in the current path.
+ //
+ hash.Add (tc, null);
+
+ bool ok = CheckStructCycles (ftc, seen, hash);
+
+ hash.Remove (tc);
+
+ if (!ok)
+ return false;
+
+ if (!seen.Contains (ftc))
+ seen.Add (ftc, null);
+ }
+
+ 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 (EmitContext ec, TypeExpr [] base_interfaces)
+ {
+ ArrayList new_ifaces = new ArrayList ();
+
+ foreach (TypeExpr iface in base_interfaces){
+ TypeExpr texpr = iface.ResolveAsTypeTerminal (ec);
+ if (texpr == null)
+ return null;
+
+ if (!new_ifaces.Contains (texpr.Type))
+ new_ifaces.Add (texpr.Type);
+
+ Type [] implementing = texpr.Type.GetInterfaces ();
+
+ 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;
+ }
+
+ static PtrHashtable iface_cache = new PtrHashtable ();
+
+ /// <summary>
+ /// This function returns the interfaces in the type `t'. Works with
+ /// both types and TypeBuilders.
+ /// </summary>
+ public static Type [] GetInterfaces (Type t)
+ {
+
+ Type [] cached = iface_cache [t] as Type [];
+ if (cached != null)
+ return cached;
+
+ //
+ // 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);
+
+ iface_cache [t] = result;
+ return result;
+ } else if (t is GenericTypeParameterBuilder){
+ Type[] type_ifaces = (Type []) builder_to_ifaces [t];
+ if (type_ifaces == null)
+ type_ifaces = NoTypes;
+
+ iface_cache [t] = type_ifaces;
+ return type_ifaces;
+ } else {
+ Type[] ifaces = t.GetInterfaces ();
+ iface_cache [t] = ifaces;
+ return ifaces;
+ }
+ }
+
+ //
+ // gets the interfaces that are declared explicitly on t
+ //
+ public static Type [] GetExplicitInterfaces (TypeBuilder t)
+ {
+ return (Type []) builder_to_ifaces [t];
+ }
+
+ /// <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;
+ }
+
+ static NumberFormatInfo nf_provider = CultureInfo.CurrentCulture.NumberFormat;
+
+ // 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)
+ {
+ IConvertible convert_value = value as IConvertible;
+
+ if (convert_value == null){
+ error = true;
+ return null;
+ }
+
+ //
+ // 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)(convert_value.ToBoolean (nf_provider));
+ else if (conversionType.Equals (typeof (Byte)))
+ return (object)(convert_value.ToByte (nf_provider));
+ else if (conversionType.Equals (typeof (Char)))
+ return (object)(convert_value.ToChar (nf_provider));
+ else if (conversionType.Equals (typeof (DateTime)))
+ return (object)(convert_value.ToDateTime (nf_provider));
+ else if (conversionType.Equals (TypeManager.decimal_type)) // typeof (Decimal)))
+ return (object)(convert_value.ToDecimal (nf_provider));
+ else if (conversionType.Equals (typeof (Double)))
+ return (object)(convert_value.ToDouble (nf_provider));
+ else if (conversionType.Equals (typeof (Int16)))
+ return (object)(convert_value.ToInt16 (nf_provider));
+ else if (conversionType.Equals (typeof (Int32)))
+ return (object)(convert_value.ToInt32 (nf_provider));
+ else if (conversionType.Equals (typeof (Int64)))
+ return (object)(convert_value.ToInt64 (nf_provider));
+ else if (conversionType.Equals (typeof (SByte)))
+ return (object)(convert_value.ToSByte (nf_provider));
+ else if (conversionType.Equals (typeof (Single)))
+ return (object)(convert_value.ToSingle (nf_provider));
+ else if (conversionType.Equals (typeof (String)))
+ return (object)(convert_value.ToString (nf_provider));
+ else if (conversionType.Equals (typeof (UInt16)))
+ return (object)(convert_value.ToUInt16 (nf_provider));
+ else if (conversionType.Equals (typeof (UInt32)))
+ return (object)(convert_value.ToUInt32 (nf_provider));
+ else if (conversionType.Equals (typeof (UInt64)))
+ return (object)(convert_value.ToUInt64 (nf_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.Single:
+ return TypeManager.float_type;
+ case TypeCode.Double:
+ return TypeManager.double_type;
+ case TypeCode.String:
+ return TypeManager.string_type;
+ case TypeCode.Decimal:
+ return TypeManager.decimal_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;
+ if (t == typeof (System.IntPtr))
+ return TypeManager.intptr_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 IndexerNameAttribute in the container.
+ ///
+ /// For example, the String class indexer is named `Chars' not `Item'
+ /// </remarks>
+ public static string IndexerPropertyName (Type t)
+ {
+ if (t.IsGenericInstance)
+ t = t.GetGenericTypeDefinition ();
+
+ if (t is TypeBuilder) {
+ TypeContainer tc = t.IsInterface ? LookupInterface (t) : LookupTypeContainer (t);
+ return tc == null ? TypeContainer.DefaultIndexerName : tc.IndexerName;
+ }
+
+ System.Attribute attr = System.Attribute.GetCustomAttribute (
+ t, TypeManager.default_member_type);
+ if (attr != null){
+ DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
+ return dma.MemberName;
+ }
+
+ return TypeContainer.DefaultIndexerName;
+ }
+
+ static MethodInfo declare_local_method = null;
+
+ public static LocalBuilder DeclareLocalPinned (ILGenerator ig, Type t)
+ {
+ if (declare_local_method == null){
+ declare_local_method = typeof (ILGenerator).GetMethod (
+ "DeclareLocal",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type [] { typeof (Type), typeof (bool)},
+ null);
+ if (declare_local_method == null){
+ Report.Warning (-24, new Location (-1),
+ "This version of the runtime does not support making pinned local variables. " +
+ "This code may cause errors on a runtime with a moving GC");
+ return ig.DeclareLocal (t);
+ }
+ }
+ return (LocalBuilder) declare_local_method.Invoke (ig, new object [] { t, true });
+ }
+
+ //
+ // Returns whether the array of memberinfos contains the given method
+ //
+ public 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;
+
+ if (method is MethodInfo && new_method is MethodInfo)
+ if (((MethodInfo) method).ReturnType != ((MethodInfo) new_method).ReturnType)
+ 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, IList 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;
+ }
+
+#region MemberLookup implementation
+
+ //
+ // Whether we allow private members in the result (since FindMembers
+ // uses NonPublic for both protected and private), we need to distinguish.
+ //
+
+ static internal bool FilterNone (MemberInfo m, object filter_criteria)
+ {
+ return true;
+ }
+
+ internal class Closure {
+ internal bool private_ok;
+
+ // Who is invoking us and which type is being queried currently.
+ internal Type invocation_type;
+ internal Type qualifier_type;
+
+ // The assembly that defines the type is that is calling us
+ internal Assembly invocation_assembly;
+ internal IList almost_match;
+
+ private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
+ {
+ if (invocation_type == null)
+ return false;
+
+ if (is_static)
+ return true;
+
+ // A nested class has access to all the protected members visible
+ // to its parent.
+ if (qualifier_type != null
+ && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
+ return true;
+
+ if (invocation_type == m.DeclaringType
+ || invocation_type.IsSubclassOf (m.DeclaringType)) {
+ // Although a derived class can access protected members of
+ // its base class it cannot do so through an instance of the
+ // base class (CS1540).
+ // => Ancestry should be: declaring_type ->* invocation_type
+ // ->* qualified_type
+ if (qualifier_type == null
+ || qualifier_type == invocation_type
+ || qualifier_type.IsSubclassOf (invocation_type))
+ return true;
+ }
+
+ if (almost_match != null)
+ almost_match.Add (m);
+ return false;
+ }
+
+ bool Filter (MethodBase mb, object filter_criteria)
+ {
+ MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
+
+ if (ma == MethodAttributes.Private)
+ return private_ok ||
+ IsPrivateAccessible (invocation_type, mb.DeclaringType) ||
+ IsNestedChildOf (invocation_type, mb.DeclaringType);
+
+ //
+ // FamAndAssem requires that we not only derivate, but we are on the
+ // same assembly.
+ //
+ if (ma == MethodAttributes.FamANDAssem){
+ if (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 (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 (invocation_type == null)
+ return false;
+
+ if (!IsNestedFamilyAccessible (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 && (qualifier_type != null) &&
+ !IsEqualGenericInstance (invocation_type, qualifier_type) &&
+ TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
+ !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
+ return false;
+
+ return true;
+ }
+
+ // Public.
+ return true;
+ }
+
+ bool Filter (FieldInfo fi, object filter_criteria)
+ {
+ FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
+
+ if (fa == FieldAttributes.Private)
+ return private_ok ||
+ IsPrivateAccessible (invocation_type, fi.DeclaringType) ||
+ IsNestedChildOf (invocation_type, fi.DeclaringType);
+
+ //
+ // FamAndAssem requires that we not only derivate, but we are on the
+ // same assembly.
+ //
+ if (fa == FieldAttributes.FamANDAssem){
+ if (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 (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 (invocation_type == null)
+ return false;
+
+ if (!IsNestedFamilyAccessible (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 && (qualifier_type != null) &&
+ !IsEqualGenericInstance (invocation_type, qualifier_type) &&
+ TypeManager.IsFamilyAccessible (invocation_type, qualifier_type) &&
+ !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
+ return false;
+
+ return true;
+ }
+
+ // Public.
+ return true;
+ }
+
+ //
+ // This filter filters by name + whether it is ok to include private
+ // members in the search
+ //
+ internal bool Filter (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 (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
+ (invocation_type != null) &&
+ IsPrivateAccessible (m.DeclaringType, 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)
+ return Filter ((MethodBase) m, filter_criteria);
+
+ if (m is FieldInfo)
+ return Filter ((FieldInfo) m, filter_criteria);
+
+ //
+ // EventInfos and PropertyInfos, return true because they lack
+ // permission information, so we need to check later on the methods.
+ //
+ return true;
+ }
+ }
+
+ static Closure closure = new Closure ();
+ static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
+
+ //
+ // 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.
+ //
+ // The 'almost_match' argument is used for reporting error CS1540.
+ //
+ // 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, IList almost_match)
+ {
+ Timer.StartTimer (TimerType.MemberLookup);
+
+ MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
+ queried_type, mt, original_bf, name, almost_match);
+
+ 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, IList almost_match)
+ {
+ 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.invocation_type = invocation_type;
+ closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
+ closure.qualifier_type = qualifier_type;
+ closure.almost_match = almost_match;
+
+ //
+ // 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 != null) && (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;
+ }
+ }
+ }
+
+ // This is from the first time we find a method
+ // in most cases, we do not actually find a method in the base class
+ // so we can just ignore it, and save the arraylist allocation
+ MemberInfo [] first_members_list = null;
+ bool use_first_members_list = false;
+
+ do {
+ MemberInfo [] 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;
+
+ 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;
+ searching = true;
+ }
+ }
+
+ if (list.Length == 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.Length == 1 && !(list [0] is MethodBase)){
+ return list;
+ }
+
+ //
+ // Multiple properties: we query those just to find out the indexer
+ // name
+ //
+ if (list [0] is PropertyInfo)
+ return list;
+
+ //
+ // We found an event: the cache lookup returns both the event and
+ // its private field.
+ //
+ if (list [0] is EventInfo) {
+ if ((list.Length == 2) && (list [1] is FieldInfo))
+ return new MemberInfo [] { list [0] };
+
+ // Oooops
+ return null;
+ }
+
+ //
+ // We found methods, turn the search into "method scan"
+ // mode.
+ //
+
+ if (first_members_list != null) {
+ if (use_first_members_list) {
+ method_list = CopyNewMethods (method_list, first_members_list);
+ use_first_members_list = false;
+ }
+
+ method_list = CopyNewMethods (method_list, list);
+ } else {
+ first_members_list = list;
+ use_first_members_list = true;
+
+ mt &= (MemberTypes.Method | MemberTypes.Constructor);
+ }
+ } while (searching);
+
+ if (use_first_members_list) {
+ foreach (MemberInfo mi in first_members_list) {
+ if (! (mi is MethodBase)) {
+ method_list = CopyNewMethods (method_list, first_members_list);
+ return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
+ }
+ }
+ return (MemberInfo []) first_members_list;
+ }
+
+ 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, null);
+ if (x != null)
+ return x;
+ }
+
+ return null;
+ }
+
+ // Tests whether external method is really special
+ public static bool IsSpecialMethod (MethodBase mb)
+ {
+ string name = mb.Name;
+ if (name.StartsWith ("get_") || name.StartsWith ("set_"))
+ return mb.DeclaringType.GetProperty (name.Substring (4)) != null;
+
+ if (name.StartsWith ("add_"))
+ return mb.DeclaringType.GetEvent (name.Substring (4)) != null;
+
+ if (name.StartsWith ("remove_"))
+ return mb.DeclaringType.GetEvent (name.Substring (7)) != null;
+
+ if (name.StartsWith ("op_")){
+ foreach (string oname in Unary.oper_names) {
+ if (oname == name)
+ return true;
+ }
+
+ foreach (string oname in Binary.oper_names) {
+ if (oname == 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>
+ private 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;
+ }
+
+ public static MemberCache GetMemberCache (Type t)
+ {
+ return GetTypeHandle (t).MemberCache;
+ }
+
+ public static void CleanUp ()
+ {
+ type_hash = null;
+ }
+
+ /// <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 string full_name;
+ private bool is_interface;
+ private MemberCache member_cache;
+ private MemberCache parent_cache;
+
+ private TypeHandle (Type type)
+ {
+ this.type = type;
+ full_name = type.FullName != null ? type.FullName : type.Name;
+ if (type.BaseType != null) {
+ BaseType = GetTypeHandle (type.BaseType);
+ parent_cache = BaseType.MemberCache;
+ } else if (type.IsInterface)
+ parent_cache = TypeManager.LookupParentInterfacesCache (type);
+ this.is_interface = type.IsInterface || type.IsGenericParameter;
+ this.member_cache = new MemberCache (this);
+ }
+
+ // IMemberContainer methods
+
+ public string Name {
+ get {
+ return full_name;
+ }
+ }
+
+ public Type Type {
+ get {
+ return type;
+ }
+ }
+
+ public MemberCache ParentCache {
+ get {
+ return parent_cache;
+ }
+ }
+
+ public bool IsInterface {
+ get {
+ return is_interface;
+ }
+ }
+
+ public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ MemberInfo [] members;
+ if (type is GenericTypeParameterBuilder)
+ return MemberList.Empty;
+ if (mt == MemberTypes.Event)
+ members = type.GetEvents (bf | BindingFlags.DeclaredOnly);
+ else
+ members = type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+ null, null);
+ Array.Reverse (members);
+
+ return new MemberList (members);
+ }
+
+ // IMemberFinder methods
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+ MemberFilter filter, object criteria)
+ {
+ return new MemberList (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 + ")";
+ }
+}
+
+}