?? expression.cs
字號:
//// expression.cs: Expression representation for the IL tree.//// Author:// Miguel de Icaza (miguel@ximian.com)// Marek Safar (marek.safar@seznam.cz)//// (C) 2001, 2002, 2003 Ximian, Inc.// (C) 2003, 2004 Novell, Inc.//#define USE_OLDnamespace 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) { this.Expr = expr; } public override Expression DoResolve (EmitContext ec) { Expr = Expr.Resolve (ec); return Expr; } public override void Emit (EmitContext ec) { throw new Exception ("Should not happen"); } public override Location Location { get { return Expr.Location; } } } /// <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) { Report.Error (23, loc, "Operator `{0}' cannot be applied to operand of type `{1}'", OperName (Oper), 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, expr.Location); else if (expr is UIntConstant){ uint value = ((UIntConstant) expr).Value; if (value < 2147483649) return new IntConstant (-(int)value, expr.Location); else e = new LongConstant (-value, expr.Location); } else if (expr is LongConstant) e = new LongConstant (-((LongConstant) expr).Value, expr.Location); else if (expr is ULongConstant){ ulong value = ((ULongConstant) expr).Value; if (value < 9223372036854775809) return new LongConstant(-(long)value, expr.Location); } else if (expr is FloatConstant) e = new FloatConstant (-((FloatConstant) expr).Value, expr.Location); else if (expr is DoubleConstant) e = new DoubleConstant (-((DoubleConstant) expr).Value, expr.Location); else if (expr is DecimalConstant) e = new DecimalConstant (-((DecimalConstant) expr).Value, expr.Location); else if (expr is ShortConstant) e = new IntConstant (-((ShortConstant) expr).Value, expr.Location); else if (expr is UShortConstant) e = new IntConstant (-((UShortConstant) expr).Value, expr.Location); else if (expr is SByteConstant) e = new IntConstant (-((SByteConstant) expr).Value, expr.Location); else if (expr is ByteConstant) e = new IntConstant (-((ByteConstant) expr).Value, expr.Location); 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: if (expr_type == TypeManager.bool_type){ result = null; Error23 (expr_type); return false; } 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), b.Location); 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, e.Location); } else if (expr_type == TypeManager.uint32_type){ result = new UIntConstant (~ ((UIntConstant) e).Value, e.Location); } else if (expr_type == TypeManager.int64_type){ result = new LongConstant (~ ((LongConstant) e).Value, e.Location); } else if (expr_type == TypeManager.uint64_type){ result = new ULongConstant (~ ((ULongConstant) e).Value, e.Location); } 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) goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc); if (e != null) goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc); if (e != null) goto ok; e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc); if (e != null) goto ok; Error23 (expr_type); return null; ok: Expr = e; expr_type = e.Type; } type = expr_type; return this; case Operator.AddressOf: if (!ec.InUnsafe) { UnsafeError (loc); return null; } if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){ return null; } IVariable variable = Expr as IVariable; bool is_fixed = variable != null && variable.VerifyFixed (); if (!ec.InFixedInitializer && !is_fixed) { Error (212, "You can only take the address of unfixed expression inside " + "of a fixed statement initializer"); return null; } if (ec.InFixedInitializer && is_fixed) { Error (213, "You cannot use the fixed statement to take the address of 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 must be applied to a pointer"); return null; } // // We create an Indirection expression, because // it can implement the IMemoryLocation. // return new Indirection (Expr, loc); case Operator.UnaryPlus: //
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -