?? expression.cs
字號(hào):
} 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, false); if (texpr == null) return null; probe_type = texpr.ResolveType (ec); 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 && !(e is NullCast)){ expr = e; if (etype.IsValueType) action = Action.AlwaysTrue; else action = Action.LeaveOnStack; warning_always_matches = true; } else if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){ // // Second case: explicit reference convresion // if (expr is NullLiteral) action = Action.AlwaysFalse; else action = Action.Probe; } else { action = Action.AlwaysFalse; warning_never_matches = true; } if (warning_always_matches) Report.Warning (183, 1, loc, "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)) Report.Warning (184, 1, loc, "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; Expression resolved_type; 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, "Cannot convert type `{0}' to `{1}' via a built-in conversion", TypeManager.CSharpName (source), TypeManager.CSharpName (target)); } public override Expression DoResolve (EmitContext ec) { if (resolved_type == null) { resolved_type = base.DoResolve (ec); if (resolved_type == 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 must be used with a reference type (`" + TypeManager.CSharpName (probe_type) + "' is a value type)"); return null; } Expression e = Convert.ImplicitConversion (ec, expr, probe_type, loc); if (e != null){ expr = e; do_isinst = false; return this; } if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){ do_isinst = true; return this; } Error_CannotConvertType (etype, probe_type, loc); return null; } } /// <summary> /// This represents a typecast in the source language. /// /// FIXME: Cast expressions have an unusual set of parsing /// rules, we need to figure those out. /// </summary> public class Cast : Expression { Expression target_type; Expression expr; public Cast (Expression cast_type, Expression expr) : this (cast_type, expr, cast_type.Location) { } 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; } } public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { expr = expr.DoResolveLValue (ec, right_side); if (expr == null) return null; return ResolveRest (ec); } public override Expression DoResolve (EmitContext ec) { expr = expr.Resolve (ec); if (expr == null) return null; return ResolveRest (ec); } Expression ResolveRest (EmitContext ec) { TypeExpr target = target_type.ResolveAsTypeTerminal (ec, false); if (target == null) return null; type = target.ResolveType (ec); if (type.IsAbstract && type.IsSealed) { Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); return null; } eclass = ExprClass.Value; Constant c = expr as Constant; if (c != null) { c = c.TryReduce (ec, type, loc); if (c != null) return c; } 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) { this.oper = oper; this.left = left; this.right = right; this.loc = left.Location; } 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> public 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:
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -