/src/Libraries/NewNRefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs
C# | 6442 lines | 4510 code | 1065 blank | 867 comment | 1305 complexity | 09d7c15b599589235347866a4446af12 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CPL-1.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- //
- // ecore.cs: Core of the Expression representation for the intermediate tree.
- //
- // Author:
- // Miguel de Icaza (miguel@ximian.com)
- // Marek Safar (marek.safar@seznam.cz)
- //
- // Copyright 2001, 2002, 2003 Ximian, Inc.
- // Copyright 2003-2008 Novell, Inc.
- // Copyright 2011 Xamarin Inc.
- //
- //
- using System;
- using System.Collections.Generic;
- using System.Text;
- using SLE = System.Linq.Expressions;
- using System.Linq;
- #if STATIC
- using IKVM.Reflection;
- using IKVM.Reflection.Emit;
- #else
- using System.Reflection;
- using System.Reflection.Emit;
- #endif
- namespace Mono.CSharp {
- /// <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 {
- Unresolved = 0,
-
- Value,
- Variable,
- Namespace,
- Type,
- TypeParameter,
- 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 = 1 << 1,
- // Returns a method group.
- MethodGroup = 1 << 2,
- TypeParameter = 1 << 3,
- // Mask of all the expression class flags.
- MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
- }
- //
- // 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);
- }
- //
- // An expressions resolved as a direct variable reference
- //
- public interface IVariableReference : IFixedExpression
- {
- bool IsHoisted { get; }
- string Name { get; }
- VariableInfo VariableInfo { get; }
- void SetHasAddressTaken ();
- }
- //
- // Implemented by an expression which could be or is always
- // fixed
- //
- public interface IFixedExpression
- {
- bool IsFixed { get; }
- }
- public interface IExpressionCleanup
- {
- void EmitCleanup (EmitContext ec);
- }
- /// <remarks>
- /// Base class for expressions
- /// </remarks>
- public abstract class Expression {
- public ExprClass eclass;
- protected TypeSpec type;
- protected Location loc;
-
- public TypeSpec Type {
- get { return type; }
- set { type = value; }
- }
- public virtual bool IsSideEffectFree {
- get {
- return false;
- }
- }
- public Location Location {
- get { return loc; }
- }
- public virtual bool IsNull {
- get {
- return false;
- }
- }
- //
- // Returns true when the expression during Emit phase breaks stack
- // by using await expression
- //
- public virtual bool ContainsEmitWithAwait ()
- {
- return false;
- }
- /// <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>
- protected abstract Expression DoResolve (ResolveContext rc);
- public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side)
- {
- return null;
- }
- //
- // This is used if the expression should be resolved as a type or namespace name.
- // the default implementation fails.
- //
- public virtual TypeSpec ResolveAsType (IMemberContext mc)
- {
- ResolveContext ec = new ResolveContext (mc);
- Expression e = Resolve (ec);
- if (e != null)
- e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
- return null;
- }
- public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc)
- {
- rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member);
- }
- public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name)
- {
- rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name);
- }
- public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name)
- {
- rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null",
- name, TypeManager.CSharpName (type));
- }
- public static void Error_InvalidExpressionStatement (Report Report, Location loc)
- {
- Report.Error (201, loc, "Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement");
- }
-
- public void Error_InvalidExpressionStatement (BlockContext ec)
- {
- Error_InvalidExpressionStatement (ec.Report, loc);
- }
- public static void Error_VoidInvalidInTheContext (Location loc, Report Report)
- {
- Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
- }
- public virtual void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
- {
- Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
- }
- protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl)
- {
- // The error was already reported as CS1660
- if (type == InternalType.AnonymousMethod || type == InternalType.ErrorType)
- return;
- string from_type = type.GetSignatureForError ();
- string to_type = target.GetSignatureForError ();
- if (from_type == to_type) {
- from_type = type.GetSignatureForErrorIncludingAssemblyName ();
- to_type = target.GetSignatureForErrorIncludingAssemblyName ();
- }
- if (expl) {
- ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
- from_type, to_type);
- return;
- }
- ec.Report.DisableReporting ();
- bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null;
- ec.Report.EnableReporting ();
- if (expl_exists) {
- ec.Report.Error (266, loc,
- "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
- from_type, to_type);
- } else {
- ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
- from_type, to_type);
- }
- }
- public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc)
- {
- // Better message for possible generic expressions
- if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
- var report = context.Module.Compiler.Report;
- report.SymbolRelatedToPreviousError (member);
- if (member is TypeSpec)
- member = ((TypeSpec) member).GetDefinition ();
- else
- member = ((MethodSpec) member).GetGenericMethodDefinition ();
- string name = member.Kind == MemberKind.Method ? "method" : "type";
- if (member.IsGeneric) {
- report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)",
- name, member.GetSignatureForError (), member.Arity.ToString ());
- } else {
- report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments",
- name, member.GetSignatureForError ());
- }
- } else {
- Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc);
- }
- }
- public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc)
- {
- context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
- exprType, name);
- }
- protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
- {
- Error_TypeDoesNotContainDefinition (ec, loc, type, name);
- }
- public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name)
- {
- ec.Report.SymbolRelatedToPreviousError (type);
- ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
- TypeManager.CSharpName (type), name);
- }
- public virtual void Error_ValueAssignment (ResolveContext rc, Expression rhs)
- {
- if (rhs == EmptyExpression.LValueMemberAccess || rhs == EmptyExpression.LValueMemberOutAccess) {
- rc.Report.SymbolRelatedToPreviousError (type);
- if (rc.CurrentInitializerVariable != null) {
- rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
- type.GetSignatureForError (), GetSignatureForError ());
- } else {
- rc.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
- GetSignatureForError ());
- }
- } else {
- rc.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
- }
- }
- protected void Error_VoidPointerOperation (ResolveContext rc)
- {
- rc.Report.Error (242, loc, "The operation in question is undefined on void pointers");
- }
- public ResolveFlags ExprClassToResolveFlags {
- get {
- switch (eclass) {
- case ExprClass.Type:
- case ExprClass.Namespace:
- return ResolveFlags.Type;
-
- case ExprClass.MethodGroup:
- return ResolveFlags.MethodGroup;
-
- case ExprClass.TypeParameter:
- return ResolveFlags.TypeParameter;
-
- case ExprClass.Value:
- case ExprClass.Variable:
- case ExprClass.PropertyAccess:
- case ExprClass.EventAccess:
- case ExprClass.IndexerAccess:
- return ResolveFlags.VariableOrValue;
-
- default:
- throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve");
- }
- }
- }
- public virtual string GetSignatureForError ()
- {
- return type.GetDefinition ().GetSignatureForError ();
- }
-
- /// <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 (ResolveContext ec, ResolveFlags flags)
- {
- if (eclass != ExprClass.Unresolved)
- return this;
-
- Expression e;
- try {
- e = DoResolve (ec);
- if (e == null)
- return null;
- if ((flags & e.ExprClassToResolveFlags) == 0) {
- e.Error_UnexpectedKind (ec, flags, loc);
- return null;
- }
- if (e.type == null)
- throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
- return e;
- } catch (Exception ex) {
- if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled || ex is FatalException)
- throw;
- ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message);
- return ErrorExpression.Instance; // TODO: Add location
- }
- }
- /// <summary>
- /// Resolves an expression and performs semantic analysis on it.
- /// </summary>
- public Expression Resolve (ResolveContext rc)
- {
- return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
- }
- /// <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 (ResolveContext ec, Expression right_side)
- {
- int errors = ec.Report.Errors;
- bool out_access = right_side == EmptyExpression.OutAccess;
- Expression e = DoResolveLValue (ec, right_side);
- if (e != null && out_access && !(e is IMemoryLocation)) {
- // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
- // Enabling this 'throw' will "only" result in deleting useless code elsewhere,
- //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
- // e.GetType () + " " + e.GetSignatureForError ());
- e = null;
- }
- if (e == null) {
- if (errors == ec.Report.Errors) {
- if (out_access)
- ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
- else
- Error_ValueAssignment (ec, right_side);
- }
- return null;
- }
- if (e.eclass == ExprClass.Unresolved)
- throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
- if ((e.type == null) && !(e is GenericTypeExpr))
- throw new Exception ("Expression " + e + " did not set its type after Resolve");
- return e;
- }
- public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
- {
- rc.Module.Compiler.Report.Error (182, loc,
- "An attribute argument must be a constant expression, typeof expression or array creation expression");
- }
- /// <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);
- // Emit code to branch to @target if this expression is equivalent to @on_true.
- // The default implementation is to emit the value, and then emit a brtrue or brfalse.
- // Subclasses can provide more efficient implementations, but those MUST be equivalent,
- // including the use of conditional branches. Note also that a branch MUST be emitted
- public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
- {
- Emit (ec);
- ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
- }
- // Emit this expression for its side effects, not for its value.
- // The default implementation is to emit the value, and then throw it away.
- // Subclasses can provide more efficient implementations, but those MUST be equivalent
- public virtual void EmitSideEffect (EmitContext ec)
- {
- Emit (ec);
- ec.Emit (OpCodes.Pop);
- }
- //
- // Emits the expression into temporary field variable. The method
- // should be used for await expressions only
- //
- public virtual Expression EmitToField (EmitContext ec)
- {
- //
- // This is the await prepare Emit method. When emitting code like
- // a + b we emit code like
- //
- // a.Emit ()
- // b.Emit ()
- // Opcodes.Add
- //
- // For await a + await b we have to interfere the flow to keep the
- // stack clean because await yields from the expression. The emit
- // then changes to
- //
- // a = a.EmitToField () // a is changed to temporary field access
- // b = b.EmitToField ()
- // a.Emit ()
- // b.Emit ()
- // Opcodes.Add
- //
- //
- // The idea is to emit expression and leave the stack empty with
- // result value still available.
- //
- // Expressions should override this default implementation when
- // optimized version can be provided (e.g. FieldExpr)
- //
- //
- // We can optimize for side-effect free expressions, they can be
- // emitted out of order
- //
- if (IsSideEffectFree)
- return this;
- bool needs_temporary = ContainsEmitWithAwait ();
- if (!needs_temporary)
- ec.EmitThis ();
- // Emit original code
- var field = EmitToFieldSource (ec);
- if (field == null) {
- //
- // Store the result to temporary field when we
- // cannot load `this' directly
- //
- field = ec.GetTemporaryField (type);
- if (needs_temporary) {
- //
- // Create temporary local (we cannot load `this' before Emit)
- //
- var temp = ec.GetTemporaryLocal (type);
- ec.Emit (OpCodes.Stloc, temp);
- ec.EmitThis ();
- ec.Emit (OpCodes.Ldloc, temp);
- field.EmitAssignFromStack (ec);
- ec.FreeTemporaryLocal (temp, type);
- } else {
- field.EmitAssignFromStack (ec);
- }
- }
- return field;
- }
- protected virtual FieldExpr EmitToFieldSource (EmitContext ec)
- {
- //
- // Default implementation calls Emit method
- //
- Emit (ec);
- return null;
- }
- protected static void EmitExpressionsList (EmitContext ec, List<Expression> expressions)
- {
- if (ec.HasSet (BuilderContext.Options.AsyncBody)) {
- bool contains_await = false;
- for (int i = 1; i < expressions.Count; ++i) {
- if (expressions[i].ContainsEmitWithAwait ()) {
- contains_await = true;
- break;
- }
- }
- if (contains_await) {
- for (int i = 0; i < expressions.Count; ++i) {
- expressions[i] = expressions[i].EmitToField (ec);
- }
- }
- }
- for (int i = 0; i < expressions.Count; ++i) {
- expressions[i].Emit (ec);
- }
- }
- /// <summary>
- /// Protected constructor. Only derivate types should
- /// be able to be created
- /// </summary>
- protected Expression ()
- {
- }
- /// <summary>
- /// Returns a fully formed expression after a MemberLookup
- /// </summary>
- ///
- static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc)
- {
- if (spec is EventSpec)
- return new EventExpr ((EventSpec) spec, loc);
- if (spec is ConstSpec)
- return new ConstantExpr ((ConstSpec) spec, loc);
- if (spec is FieldSpec)
- return new FieldExpr ((FieldSpec) spec, loc);
- if (spec is PropertySpec)
- return new PropertyExpr ((PropertySpec) spec, loc);
- if (spec is TypeSpec)
- return new TypeExpression (((TypeSpec) spec), loc);
- return null;
- }
- public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc)
- {
- var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
- if (ctors == null) {
- rc.Report.SymbolRelatedToPreviousError (type);
- if (type.IsStruct) {
- // Report meaningful error for struct as they always have default ctor in C# context
- OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
- } else {
- rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
- type.GetSignatureForError ());
- }
- return null;
- }
- var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc);
- if (!rc.HasSet (ResolveContext.Options.BaseInitializer)) {
- r.InstanceQualifier = new ConstructorInstanceQualifier (type);
- }
- return r.ResolveMember<MethodSpec> (rc, ref args);
- }
- [Flags]
- public enum MemberLookupRestrictions
- {
- None = 0,
- InvocableOnly = 1,
- ExactArity = 1 << 2,
- ReadAccess = 1 << 3
- }
- //
- // 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 (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc)
- {
- var members = MemberCache.FindMembers (queried_type, name, false);
- if (members == null)
- return null;
- MemberSpec non_method = null;
- MemberSpec ambig_non_method = null;
- do {
- for (int i = 0; i < members.Count; ++i) {
- var member = members[i];
- // HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there
- if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event)
- continue;
- if ((member.Modifiers & Modifiers.BACKING_FIELD) != 0)
- continue;
- if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity)
- continue;
- if (!errorMode) {
- if (!member.IsAccessible (rc))
- continue;
- //
- // With runtime binder we can have a situation where queried type is inaccessible
- // because it came via dynamic object, the check about inconsisted accessibility
- // had no effect as the type was unknown during compilation
- //
- // class A {
- // private class N { }
- //
- // public dynamic Foo ()
- // {
- // return new N ();
- // }
- // }
- //
- if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc))
- continue;
- }
- if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) {
- if (member is MethodSpec)
- return new MethodGroupExpr (members, queried_type, loc);
- if (!Invocation.IsMemberInvocable (member))
- continue;
- }
- if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) {
- non_method = member;
- } else if (!errorMode && !member.IsNotCSharpCompatible) {
- ambig_non_method = member;
- }
- }
- if (non_method != null) {
- if (ambig_non_method != null && rc != null) {
- var report = rc.Module.Compiler.Report;
- report.SymbolRelatedToPreviousError (non_method);
- report.SymbolRelatedToPreviousError (ambig_non_method);
- report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
- non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ());
- }
- if (non_method is MethodSpec)
- return new MethodGroupExpr (members, queried_type, loc);
- return ExprClassFromMemberInfo (non_method, loc);
- }
- if (members[0].DeclaringType.BaseType == null)
- members = null;
- else
- members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false);
- } while (members != null);
- return null;
- }
- protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
- {
- throw new NotImplementedException ();
- }
- public virtual void Error_OperatorCannotBeApplied (ResolveContext rc, Location loc, string oper, TypeSpec t)
- {
- if (t == InternalType.ErrorType)
- return;
- rc.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
- oper, t.GetSignatureForError ());
- }
- protected void Error_PointerInsideExpressionTree (ResolveContext ec)
- {
- ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
- }
- /// <summary>
- /// Returns an expression that can be used to invoke operator true
- /// on the expression if it exists.
- /// </summary>
- protected static Expression GetOperatorTrue (ResolveContext 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>
- protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
- {
- return GetOperatorTrueOrFalse (ec, e, false, loc);
- }
- static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
- {
- var op = is_true ? Operator.OpType.True : Operator.OpType.False;
- var methods = MemberCache.GetUserOperator (e.type, op, false);
- if (methods == null)
- return null;
- Arguments arguments = new Arguments (1);
- arguments.Add (new Argument (e));
- var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
- var oper = res.ResolveOperator (ec, ref arguments);
- if (oper == null)
- return null;
- return new UserOperatorCall (oper, arguments, null, loc);
- }
-
- public virtual string ExprClassName
- {
- get {
- switch (eclass){
- case ExprClass.Unresolved:
- return "Unresolved";
- 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";
- case ExprClass.TypeParameter:
- return "type parameter";
- }
- throw new Exception ("Should not happen");
- }
- }
-
- /// <summary>
- /// Reports that we were expecting `expr' to be of class `expected'
- /// </summary>
- public void Error_UnexpectedKind (IMemberContext ctx, Expression memberExpr, string expected, string was, Location loc)
- {
- var name = memberExpr.GetSignatureForError ();
- ctx.Module.Compiler.Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected);
- }
- public virtual void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
- {
- string [] valid = new string [4];
- int count = 0;
- if ((flags & ResolveFlags.VariableOrValue) != 0) {
- valid [count++] = "variable";
- valid [count++] = "value";
- }
- if ((flags & ResolveFlags.Type) != 0)
- valid [count++] = "type";
- if ((flags & ResolveFlags.MethodGroup) != 0)
- valid [count++] = "method group";
- if (count == 0)
- valid [count++] = "unknown";
- StringBuilder sb = new StringBuilder (valid [0]);
- for (int i = 1; i < count - 1; i++) {
- sb.Append ("', `");
- sb.Append (valid [i]);
- }
- if (count > 1) {
- sb.Append ("' or `");
- sb.Append (valid [count - 1]);
- }
- ec.Report.Error (119, loc,
- "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
- }
-
- public static void UnsafeError (ResolveContext ec, Location loc)
- {
- UnsafeError (ec.Report, loc);
- }
- public static void UnsafeError (Report Report, Location loc)
- {
- Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
- }
- //
- // Converts `source' to an int, uint, long or ulong.
- //
- protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source)
- {
- var btypes = ec.BuiltinTypes;
- if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- Arguments args = new Arguments (1);
- args.Add (new Argument (source));
- return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
- }
- Expression converted;
-
- using (ec.Set (ResolveContext.Options.CheckedScope)) {
- converted = Convert.ImplicitConversion (ec, source, btypes.Int, source.loc);
- if (converted == null)
- converted = Convert.ImplicitConversion (ec, source, btypes.UInt, source.loc);
- if (converted == null)
- converted = Convert.ImplicitConversion (ec, source, btypes.Long, source.loc);
- if (converted == null)
- converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc);
- if (converted == null) {
- source.Error_ValueCannotBeConverted (ec, btypes.Int, false);
- return null;
- }
- }
- //
- // Only positive constants are allowed at compile time
- //
- Constant c = converted as Constant;
- if (c != null && c.IsNegative)
- Error_NegativeArrayIndex (ec, source.loc);
- // No conversion needed to array index
- if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
- return converted;
- return new ArrayIndexCast (converted, btypes.Int).Resolve (ec);
- }
- //
- // Derived classes implement this method by cloning the fields that
- // could become altered during the Resolve stage
- //
- // Only expressions that are created for the parser need to implement
- // this.
- //
- protected virtual void CloneTo (CloneContext clonectx, Expression target)
- {
- throw new NotImplementedException (
- String.Format (
- "CloneTo not implemented for expression {0}", this.GetType ()));
- }
- //
- // Clones an expression created by the parser.
- //
- // We only support expressions created by the parser so far, not
- // expressions that have been resolved (many more classes would need
- // to implement CloneTo).
- //
- // This infrastructure is here merely for Lambda expressions which
- // compile the same code using different type values for the same
- // arguments to find the correct overload
- //
- public virtual Expression Clone (CloneContext clonectx)
- {
- Expression cloned = (Expression) MemberwiseClone ();
- CloneTo (clonectx, cloned);
- return cloned;
- }
- //
- // Implementation of expression to expression tree conversion
- //
- public abstract Expression CreateExpressionTree (ResolveContext ec);
- protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args)
- {
- return CreateExpressionFactoryCall (ec, name, null, args, loc);
- }
- protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args)
- {
- return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc);
- }
- public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc)
- {
- return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args);
- }
- protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
- {
- var t = ec.Module.PredefinedTypes.Expression.Resolve ();
- if (t == null)
- return null;
- return new TypeExpression (t, loc);
- }
- //
- // Implemented by all expressions which support conversion from
- // compiler expression to invokable runtime expression. Used by
- // dynamic C# binder.
- //
- public virtual SLE.Expression MakeExpression (BuilderContext ctx)
- {
- throw new NotImplementedException ("MakeExpression for " + GetType ());
- }
-
- public virtual object Accept (StructuralVisitor visitor)
- {
- return visitor.Visit (this);
- }
- }
- /// <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 ExpressionStatement ResolveStatement (BlockContext ec)
- {
- Expression e = Resolve (ec);
- if (e == null)
- return null;
- ExpressionStatement es = e as ExpressionStatement;
- if (es == null)
- Error_InvalidExpressionStatement (ec);
- if (ec.CurrentAnonymousMethod is AsyncInitializer && !(e is Assign) &&
- (e.Type.IsGenericTask || e.Type == ec.Module.PredefinedTypes.Task.TypeSpec)) {
- ec.Report.Warning (4014, 1, e.Location,
- "The statement is not awaited and execution of current method continues before the call is completed. Consider using `await' operator");
- }
- 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);
- public override void EmitSideEffect (EmitContext ec)
- {
- EmitStatement (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 abstract class TypeCast : Expression
- {
- protected readonly Expression child;
- protected TypeCast (Expression child, TypeSpec return_type)
- {
- eclass = child.eclass;
- loc = child.Location;
- type = return_type;
- this.child = child;
- }
- public Expression Child {
- get {
- return child;
- }
- }
- public override bool ContainsEmitWithAwait ()
- {
- return child.ContainsEmitWithAwait ();
- }
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- Arguments args = new Arguments (2);
- args.Add (new Argument (child.CreateExpressionTree (ec)));
- args.Add (new Argument (new TypeOf (type, loc)));
- if (type.IsPointer || child.Type.IsPointer)
- Error_PointerInsideExpressionTree (ec);
- return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
- }
- protected override Expression DoResolve (ResolveContext 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 SLE.Expression MakeExpression (BuilderContext ctx)
- {
- #if STATIC
- return base.MakeExpression (ctx);
- #else
- return ctx.HasSet (BuilderContext.Options.CheckedScope) ?
- SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) :
- SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ());
- #endif
- }
- protected override void CloneTo (CloneContext clonectx, Expression t)
- {
- // Nothing to clone
- }
- public override bool IsNull {
- get { return child.IsNull; }
- }
- }
- public class EmptyCast : TypeCast {
- EmptyCast (Expression child, TypeSpec target_type)
- : base (child, target_type)
- {
- }
- public static Expression Create (Expression child, TypeSpec type)
- {
- Constant c = child as Constant;
- if (c != null)
- return new EmptyConstantCast (c, type);
- EmptyCast e = child as EmptyCast;
- if (e != null)
- return new EmptyCast (e.child, type);
- return new EmptyCast (child, type);
- }
- public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
- {
- child.EmitBranchable (ec, label, on_true);
- }
- public override void EmitSideEffect (EmitContext ec)
- {
- child.EmitSideEffect (ec);
- }
- }
- //
- // Used for predefined type user operator (no obsolete check, etc.)
- //
- public class OperatorCast : TypeCast
- {
- readonly MethodSpec conversion_operator;
- public OperatorCast (Expression expr, TypeSpec target_type)
- : this (expr, target_type, target_type, false)
- {
- }
-
- public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit)
- : this (expr, target_type, target_type, find_explicit)
- {
- }
-
- public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit)
- : base (expr, returnType)
- {
- var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit;
- var mi = MemberCache.GetUserOperator (declaringType, op, true);
- if (mi != null) {
- foreach (MethodSpec oper in mi) {
- if (oper.ReturnType != returnType)
- continue;
- if (oper.Parameters.Types[0] == expr.Type) {
- conversion_operator = oper;
- return;
- }
- }
- }
- throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'",
- returnType.GetSignatureForError (), expr.Type.GetSignatureForError ());
- }
- public override void Emit (EmitContext ec)
- {
- child.Emit (ec);
- ec.Emit (OpCodes.Call, conversion_operator);
- }
- }
-
- //
- // Constant specialization of EmptyCast.
- // We need to special case this since an empty cast of
- // a constant is still a constant.
- //
- public class EmptyConstantCast : Constant
- {
- public readonly Constant child;
- public EmptyConstantCast (Constant child, TypeSpec type)
- : base (child.Location)
- {
- if (child == null)
- throw new ArgumentNullException ("child");
- this.child = child;
- this.eclass = child.eclass;
- this.type = type;
- }
- public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
- {
- if (child.Type == target_type)
- return child;
- // FIXME: check that 'type' can be converted to 'target_type' first
- return child.ConvertExplicitly (in_checked_context, target_type);
- }
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- Arguments args = Arguments.CreateForExpressionTree (ec, null,
- child.CreateExpressionTree (ec),
- new TypeOf (type, loc));
- if (type.IsPointer)
- Error_PointerInsideExpressionTree (ec);
- return CreateExpressionFactoryCall (ec, "Convert", args);
- }
- public override bool IsDefaultValue {
- get { return child.IsDefaultValue; }
- }
- public override bool IsNegative {
- get { return child.IsNegative; }
- }
- public override bool IsNull {
- get { return child.IsNull; }
- }
-
- public override bool IsOneInteger {
- get { return child.IsOneInteger; }
- }
- public override bool IsSideEffectFree {
- get {
- return child.IsSideEffectFree;
- }
- }
- public override bool IsZeroInteger {
- get { return child.IsZeroInteger; }
- }
- public override void Emit (EmitContext ec)
- {
- child.Emit (ec);
- }
- public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
- {
- child.EmitBranchable (ec, label, on_true);
- // Only to make verifier happy
- if (TypeManager.IsGenericParameter (type) && child.IsNull)
- ec.Emit (OpCodes.Unbox_Any, type);
- }
- public override void EmitSideEffect (EmitContext ec)
- {
- child.EmitSideEffect (ec);
- }
- public override object GetValue ()
- {
- return child.GetValue ();
- }
- public override string GetValueAsLiteral ()
- {
- return child.GetValueAsLiteral ();
- }
- public override long GetValueAsLong ()
- {
- return child.GetValueAsLong ();
- }
- public override Constant ConvertImplicitly (TypeSpec target_type)
- {
- if (type == target_type)
- return this;
- // FIXME: Do we need to check user conversions?
- if (!Convert.ImplicitStandardConversionExists (this, target_type))
- return null;
- return child.ConvertImplicitly (target_type);
- }
- }
- /// <summary>
- /// This class is used to wrap literals which belong inside Enums
- /// </summary>
- public class EnumConstant : Constant
- {
- public Constant Child;
- public EnumConstant (Constant child, TypeSpec enum_type)
- : base (child.Location)
- {
- this.Child = child;
- this.eclass = ExprClass.Value;
- this.type = enum_type;
- }
- protected EnumConstant (Location loc)
- : base (loc)
- {
- }
- public override void Emit (EmitContext ec)
- {
- Child.Emit (ec);
- }
- public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
- {
- Child.EncodeAttributeValue (rc, enc, Child.Type);
- }
- public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
- {
- Child.EmitBranchable (ec, label, on_true);
- }
- public override void EmitSideEffect (EmitContext ec)
- {
- Child.EmitSideEffect (ec);
- }
- public override string GetSignatureForError()
- {
- return TypeManager.CSharpName (Type);
- }
- public override object GetValue ()
- {
- return Child.GetValue ();
- }
- #if !STATIC
- public override object GetTypedValue ()
- {
- //
- // The method can be used in dynamic context only (on closed types)
- //
- // System.Enum.ToObject cannot be called on dynamic types
- // EnumBuilder has to be used, but we cannot use EnumBuilder
- // because it does not properly support generics
- //
- return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ());
- }
- #endif
- public override string GetValueAsLiteral ()
- {
- return Child.GetValueAsLiteral ();
- }
- public override long GetValueAsLong ()
- {
- return Child.GetValueAsLong ();
- }
- public EnumConstant Increment()
- {
- return new EnumConstant (((IntegralConstant) Child).Increment (), type);
- }
- public override bool IsDefaultValue {
- get {
- return Child.IsDefaultValue;
- }
- }
- public override bool IsSideEffectFree {
- get {
- return Child.IsSideEffectFree;
- }
- }
- public override bool IsZeroInteger {
- get { return Child.IsZeroInteger; }
- }
- public override bool IsNegative {
- get {
- return Child.IsNegative;
- }
- }
- public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type)
- {
- if (Child.Type == target_type)
- return Child;
- return Child.ConvertExplicitly (in_checked_context, target_type);
- }
- public override Constant ConvertImplicitly (TypeSpec type)
- {
- if (this.type == type) {
- return this;
- }
- if (!Convert.ImplicitStandardConversionExists (this, type)){
- return null;
- }
- return Child.ConvertImplicitly (type);
- }
- }
- /// <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 : TypeCast {
- public BoxedCast (Expression expr, TypeSpec target_type)
- : base (expr, target_type)
- {
- eclass = ExprClass.Value;
- }
-
- protected override Expression DoResolve (ResolveContext ec)
- {
- // This should never be invoked, we are born in fully
- // initialized state.
- return this;
- }
- public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
- {
- // Only boxing to object type is supported
- if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
- base.EncodeAttributeValue (rc, enc, targetType);
- return;
- }
- enc.Encode (child.Type);
- child.EncodeAttributeValue (rc, enc, child.Type);
- }
- public override void Emit (EmitContext ec)
- {
- base.Emit (ec);
-
- ec.Emit (OpCodes.Box, child.Type);
- }
- public override void EmitSideEffect (EmitContext ec)
- {
- // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
- // so, we need to emit the box+pop instructions in most cases
- if (child.Type.IsStruct &&
- (type.BuiltinType == BuiltinTypeSpec.Type.Object || type.BuiltinType == BuiltinTypeSpec.Type.ValueType))
- child.EmitSideEffect (ec);
- else
- base.EmitSideEffect (ec);
- }
- }
- public class UnboxCast : TypeCast {
- public UnboxCast (Expression expr, TypeSpec return_type)
- : base (expr, return_type)
- {
- }
- protected override Expression DoResolve (ResolveContext 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.Emit (OpCodes.Unbox_Any, type);
- }
- }
-
- /// <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 : TypeCast {
- 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, I8_I,
- U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I,
- 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,
- I_I8,
- }
- Mode mode;
-
- public ConvCast (Expression child, TypeSpec return_type, Mode m)
- : base (child, return_type)
- {
- mode = m;
- }
- protected override Expression DoResolve (ResolveContext 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)
- {
- base.Emit (ec);
- if (ec.HasSet (EmitContext.Options.CheckedScope)) {
- switch (mode){
- case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
- case Mode.U1_CH: /* nothing */ break;
- case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
- case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
- case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
- case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
- case Mode.U2_CH: /* nothing */ break;
- case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
- case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
- case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
- case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
- case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
- case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
- case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
- case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
- case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
- case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
- case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
- case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break;
- case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
- case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
- case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
- case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
- case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
- case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break;
- case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
- case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
- case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break;
- case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
- case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
- case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
- case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
- case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
- case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
- case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
- case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
- case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
- case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
- case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
- case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
- case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
- case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
- case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
- case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break;
- case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
- }
- } else {
- switch (mode){
- case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break;
- case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break;
- case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break;
- case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break;
- case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break;
- case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break;
- case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break;
- case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break;
- case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break;
- case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break;
- case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break;
- case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break;
- case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break;
- case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break;
- case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break;
- case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break;
- case Mode.U2_CH: /* nothing */ break;
- case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break;
- case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break;
- case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break;
- …
Large files files are truncated, but you can click here to view the full file