ICSharpCode.NRefactory.MonoCSharp.Nullable.NullCoalescingOperator.Emit C# (CSharp) Method

Emit() public method

public Emit ( EmitContext ec ) : void
ec EmitContext
return void
		public override void Emit (EmitContext ec)
		{
			Label end_label = ec.DefineLabel ();

			if (unwrap != null) {
				Label is_null_label = ec.DefineLabel ();

				unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brfalse, is_null_label);

				//
				// When both expressions are nullable the unwrap
				// is needed only for null check not for value uwrap
				//
				if (type.IsNullableType && TypeSpecComparer.IsEqual (NullableInfo.GetUnderlyingType (type), unwrap.Type))
					unwrap.Load (ec);
				else
					left.Emit (ec);

				ec.Emit (OpCodes.Br, end_label);

				ec.MarkLabel (is_null_label);
				right.Emit (ec);

				ec.MarkLabel (end_label);
				return;
			}

			//
			// Null check is done on original expression not after expression is converted to
			// result type. This is in most cases same but when user conversion is involved
			// we can end up in situation when use operator does the null handling which is
			// not what the operator is supposed to do
			//
			var op_expr = left as UserCast;
			if (op_expr != null) {
				op_expr.Source.Emit (ec);
				LocalTemporary temp;

				// TODO: More load kinds can be special cased
				if (!(op_expr.Source is VariableReference)) {
					temp = new LocalTemporary (op_expr.Source.Type);
					temp.Store (ec);
					temp.Emit (ec);
					op_expr.Source = temp;
				} else {
					temp = null;
				}

				var right_label = ec.DefineLabel ();
				ec.Emit (OpCodes.Brfalse_S, right_label);
				left.Emit (ec);
				ec.Emit (OpCodes.Br, end_label);
				ec.MarkLabel (right_label);

				if (temp != null)
					temp.Release (ec);
			} else {
				//
				// Common case where expression is not modified before null check and
				// we generate better/smaller code
				//
				left.Emit (ec);
				ec.Emit (OpCodes.Dup);

				// Only to make verifier happy
				if (left.Type.IsGenericParameter)
					ec.Emit (OpCodes.Box, left.Type);

				ec.Emit (OpCodes.Brtrue, end_label);

				ec.Emit (OpCodes.Pop);
			}

			right.Emit (ec);

			ec.MarkLabel (end_label);
		}