internal override Node Bind(Binder b)
        {
            b.OpenScope();
            if (Expr != null)
            {
                b.Bind(ref Expr);
                Expr.RequireGetAccess();
            }
            else
            {
                b.Bind(ref Decl);
            }
            b.Bind(ref Stmt);
            b.CloseScope();

            var u     = Decl != null ? Decl.VarDecls[0].Var : b.AddLocal(Expr.Datatype);
            var udecl = Decl ?? DeclStmt.Bound(VarDecl.Bound(u, Expr, b.Options.Binding));

            Expr du = AsTypeExpr.Bound(IdExpr.Bound(u), IdExpr.Bound(Compilation.Get(WellKnownTypes.System_IDisposable)));

            b.Cache(ref du);
            var cond = BinaryExpr.Bound(du, Expr.Token, LiteralExpr.Bound(Constant.Null), BinaryOperatorKind.NotEqual, b.Options.Binding);
            var exit = IfStmt.Bound(cond,
                                    ExprStmt.Bound(MethodCallExpr.Bound(b, null, Compilation.Get(WellKnownMembers.System_IDisposable_Dispose), du, ArgList.Empty)),
                                    null);

            return(StmtBlock.Bound(udecl,
                                   TryStmt.Bound(b,
                                                 Stmt,
                                                 exit)));
        }
        internal override Node Bind(Binder b)
        {
            b.OpenScope();
            b.Bind(ref Key);
            Key.RequireGetAccess();
            if (Key.Datatype.IsValueType)
            {
                throw Error(ErrorCode.RequireReferenceType);
            }
            b.Bind(ref Stmt);
            b.CloseScope();

            var k = b.AddLocal(Compilation.Get(NativeType.Object));

            b.Convert(ref Key, Compilation.Get(NativeType.Object));
            var kdecl = DeclStmt.Bound(VarDecl.Bound(k, Key, b.Options.Binding));

            var l     = b.AddLocal(Compilation.Get(NativeType.Boolean));
            var ldecl = DeclStmt.Bound(VarDecl.Bound(l, LiteralExpr.Bound(Constant.Create(false)), b.Options.Binding));

            var enter = ExprStmt.Bound(MethodCallExpr.Bound(b, null, Compilation.Get(WellKnownMembers.System_Threading_Monitor_Enter), null, ArgList.Bound(IdExpr.Bound(k), IdExpr.Bound(l))));
            var exit  = IfStmt.Bound(IdExpr.Bound(l),
                                     ExprStmt.Bound(MethodCallExpr.Bound(b, null, Compilation.Get(WellKnownMembers.System_Threading_Monitor_Exit), null, ArgList.Bound(IdExpr.Bound(k)))),
                                     null);

            return(StmtBlock.Bound(kdecl, ldecl,
                                   TryStmt.Bound(b,
                                                 StmtBlock.Bound(enter, Stmt),
                                                 exit)));
        }