 
 : recover-fail ( try fail -- )
     [ drop call ] [
-        >r nip r> dup fail?
+        [ nip ] dip dup fail?
         [ drop call ] [ nip throw ] if
     ] recover ; inline
 

    [ drop swap-inverse ] [ pull-inverse ] if ;

M: pop-inverse inverse
    [ "pop-length" word-prop cut-slice swap >quotation ] keep
    "pop-inverse" word-prop compose call ;

: (undo) ( revquot -- )
    [ unclip-slice inverse % (undo) ] unless-empty ;

    pick 1quotation 3array "math-inverse" set-word-prop ;

: define-pop-inverse ( word n quot -- )
    [ dupd "pop-length" set-word-prop ] dip
    "pop-inverse" set-word-prop ;

ERROR: no-inverse word ;
M: no-inverse summary
    drop "The word cannot be used in pattern matching" ;

ERROR: bad-math-inverse ;

: next ( revquot -- revquot* first )
    [ bad-math-inverse ]
    [ unclip-slice ] if-empty ;

: constant-word? ( word -- ? )
    stack-effect
    [ out>> length 1 = ]
    [ in>> empty? ] bi and ;

: assure-constant ( constant -- quot )
    dup word? [ bad-math-inverse ] when 1quotation ;

: swap-inverse ( math-inverse revquot -- revquot* quot )
    next assure-constant rot second '[ @ swap @ ] ;
