get { return "is"; }
}
+ public LocalVariable Variable { get; set; }
+
public override Expression CreateExpressionTree (ResolveContext ec)
{
+ if (Variable != null)
+ throw new NotSupportedException ();
+
Arguments args = Arguments.CreateForExpressionTree (ec, null,
expr.CreateExpressionTree (ec),
new TypeOf (probe_type_expr, loc));
return CreateExpressionFactoryCall (ec, "TypeIs", args);
}
-
- public override void Emit (EmitContext ec)
+
+ Expression CreateConstantResult (ResolveContext rc, bool result)
{
- if (expr_unwrap != null) {
- expr_unwrap.EmitCheck (ec);
- return;
- }
+ if (result)
+ rc.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
+ probe_type_expr.GetSignatureForError ());
+ else
+ rc.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
+ probe_type_expr.GetSignatureForError ());
- expr.Emit (ec);
+ var c = new BoolConstant (rc.BuiltinTypes, result, loc);
+ return expr.IsSideEffectFree ?
+ ReducedExpression.Create (c, this) :
+ new SideEffectConstant (c, this, loc);
+ }
- // Only to make verifier happy
- if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type))
- ec.Emit (OpCodes.Box, expr.Type);
+ public override void Emit (EmitContext ec)
+ {
+ EmitLoad (ec);
- ec.Emit (OpCodes.Isinst, probe_type_expr);
- ec.EmitNull ();
- ec.Emit (OpCodes.Cgt_Un);
+ if (expr_unwrap == null) {
+ ec.EmitNull ();
+ ec.Emit (OpCodes.Cgt_Un);
+ }
}
public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
{
+ EmitLoad (ec);
+ ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ }
+
+ void EmitLoad (EmitContext ec)
+ {
+ Label no_value_label = new Label ();
+
if (expr_unwrap != null) {
expr_unwrap.EmitCheck (ec);
+
+ if (Variable == null)
+ return;
+
+ ec.Emit (OpCodes.Dup);
+ no_value_label = ec.DefineLabel ();
+ ec.Emit (OpCodes.Brfalse_S, no_value_label);
+ expr_unwrap.Emit (ec);
} else {
expr.Emit (ec);
+
+ // Only to make verifier happy
+ if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type))
+ ec.Emit (OpCodes.Box, expr.Type);
+
ec.Emit (OpCodes.Isinst, probe_type_expr);
- }
- ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ }
+
+ if (Variable != null) {
+ bool value_on_stack;
+ if (probe_type_expr.IsGenericParameter || probe_type_expr.IsNullableType) {
+ ec.Emit (OpCodes.Dup);
+ ec.Emit (OpCodes.Unbox_Any, probe_type_expr);
+ value_on_stack = true;
+ } else {
+ value_on_stack = false;
+ }
+
+ Variable.CreateBuilder (ec);
+ Variable.EmitAssign (ec);
+
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.Emit (ec);
+ }
+ }
}
- Expression CreateConstantResult (ResolveContext rc, bool result)
+ protected override Expression DoResolve (ResolveContext rc)
{
- if (result)
- rc.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
- probe_type_expr.GetSignatureForError ());
- else
- rc.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
- probe_type_expr.GetSignatureForError ());
+ if (base.DoResolve (rc) == null)
+ return null;
- var c = new BoolConstant (rc.BuiltinTypes, result, loc);
- return expr.IsSideEffectFree ?
- ReducedExpression.Create (c, this) :
- new SideEffectConstant (c, this, loc);
+ var res = ResolveResultExpression (rc);
+ if (Variable != null) {
+ if (res is Constant)
+ throw new NotImplementedException ("constant in type pattern matching");
+
+ Variable.Type = probe_type_expr;
+ var bc = rc as BlockContext;
+ if (bc != null)
+ Variable.PrepareAssignmentAnalysis (bc);
+ }
+
+ return res;
}
- protected override Expression DoResolve (ResolveContext ec)
+ public override void FlowAnalysis (FlowAnalysisContext fc)
{
- if (base.DoResolve (ec) == null)
- return null;
+ base.FlowAnalysis (fc);
+
+ if (Variable != null)
+ fc.SetVariableAssigned (Variable.VariableInfo, true);
+ }
+ Expression ResolveResultExpression (ResolveContext ec)
+ {
TypeSpec d = expr.Type;
bool d_is_nullable = false;
// D and T are the same value types but D can be null
//
if (d_is_nullable && !t_is_nullable) {
- expr_unwrap = Nullable.Unwrap.Create (expr, false);
+ expr_unwrap = Nullable.Unwrap.Create (expr, true);
return this;
}