     [ load-error. nl ] each ;
 
 SYMBOL: blacklist
+SYMBOL: failures
 
 : require-all ( vocabs -- failures )
     [
         V{ } clone blacklist set
+        V{ } clone failures set
         [
             [ require ]
-            [ >r vocab-name r> 2array blacklist get push ]
+            [ swap vocab-name failures get set-at ]
             recover
         ] each
-        blacklist get
+        failures get
     ] with-compiler-errors ;
 
 : do-refresh ( modified-sources modified-docs -- )

M: vocab-link (load-vocab)
    vocab-name (load-vocab) ;

TUPLE: blacklisted-vocab name ;

: blacklisted-vocab ( name -- * )
    \ blacklisted-vocab construct-boa throw ;

M: blacklisted-vocab error.
    "This vocabulary depends on the " write
    blacklisted-vocab-name write
    " vocabulary which failed to load" print ;

[
    dup vocab-name blacklist get key? [
        vocab-name blacklisted-vocab
    ] [
        [
            dup vocab [ ] [ ] ?if (load-vocab)
        ] with-compiler-errors
    ] if
] load-vocab-hook set-global

: vocab-where ( vocab -- loc )

: refresh-all ( -- ) "" refresh ;

GENERIC: (load-vocab) ( name -- vocab )

: add-to-blacklist ( error vocab -- )
    vocab-name blacklist get dup [ set-at ] [ 3drop ] if ;

M: vocab (load-vocab)
    [
        dup vocab-root [
            dup vocab-source-loaded? [ dup load-source ] unless
            dup vocab-docs-loaded? [ dup load-docs ] unless
        ] when
    ] [ [ swap add-to-blacklist ] keep rethrow ] recover ;

M: string (load-vocab)
    [ ".private" ?tail drop reload ] keep vocab ;
