]> gitweb.factorcode.org Git - factor.git/commitdiff
Refactor error code so that error types are registered; listener prints a summary...
authorSlava Pestov <slava@shill.local>
Sun, 12 Apr 2009 21:08:46 +0000 (16:08 -0500)
committerSlava Pestov <slava@shill.local>
Sun, 12 Apr 2009 21:08:46 +0000 (16:08 -0500)
20 files changed:
basis/bootstrap/stage2.factor
basis/compiler/codegen/codegen.factor
basis/compiler/compiler.factor
basis/help/lint/checks/checks.factor
basis/help/lint/lint.factor
basis/listener/listener.factor
basis/memoize/memoize.factor
basis/stack-checker/errors/errors.factor
basis/stack-checker/known-words/known-words.factor
basis/tools/errors/errors-docs.factor
basis/tools/test/test.factor
basis/tools/vocabs/vocabs.factor
basis/ui/tools/error-list/error-list.factor
basis/ui/tools/listener/listener.factor
basis/ui/tools/tools.factor
core/compiler/errors/errors-docs.factor
core/compiler/errors/errors.factor
core/parser/parser.factor
core/source-files/errors/errors.factor
core/vocabs/loader/loader.factor

index fd21c9646c710497d79d5107cdc90788e5c68fcb..74768c74436e962337746bdb98d1122a4e790ee0 100644 (file)
@@ -81,13 +81,11 @@ SYMBOL: bootstrap-time
         "none" require
     ] if
 
-    [
-        load-components
+    load-components
 
-        millis over - core-bootstrap-time set-global
+    millis over - core-bootstrap-time set-global
 
-        run-bootstrap-init
-    ] with-compiler-errors
+    run-bootstrap-init
 
     f error set-global
     f error-continuation set-global
index cf1d81fbc277762dcf0ce87ef1545804602fc22e..a220de476a8ada60287d61d43d5a3082e172604e 100755 (executable)
@@ -380,7 +380,7 @@ TUPLE: no-such-library name ;
 M: no-such-library summary
     drop "Library not found" ;
 
-M: no-such-library source-file-error-type drop +linkage-error+ ;
+M: no-such-library error-type drop +linkage-error+ ;
 
 : no-such-library ( name -- )
     \ no-such-library boa
@@ -391,7 +391,7 @@ TUPLE: no-such-symbol name ;
 M: no-such-symbol summary
     drop "Symbol not found" ;
 
-M: no-such-symbol source-file-error-type drop +linkage-error+ ;
+M: no-such-symbol error-type drop +linkage-error+ ;
 
 : no-such-symbol ( name -- )
     \ no-such-symbol boa
index 2492b6cc230ab8214111489155b4ff079db9ad1f..0afe7f1141fac2f0bc1724e4d760e9addbfa4074 100644 (file)
@@ -53,11 +53,18 @@ SYMBOLS: +optimized+ +unoptimized+ ;
     f swap compiler-error ;
 
 : ignore-error? ( word error -- ? )
-    [ [ inline? ] [ macro? ] bi or ]
-    [ source-file-error-type +compiler-warning+ eq? ] bi* and ;
+    [
+        {
+            [ inline? ]
+            [ macro? ]
+            [ "transform-quot" word-prop ]
+            [ "no-compile" word-prop ]
+            [ "special" word-prop ]
+        } 1||
+    ] [ error-type +compiler-warning+ eq? ] bi* and ;
 
 : fail ( word error -- * )
-    [ 2dup ignore-error? [ 2drop ] [ swap compiler-error ] if ]
+    [ 2dup ignore-error? [ drop f ] when swap compiler-error ]
     [
         drop
         [ compiled-unxref ]
@@ -122,6 +129,8 @@ t compile-dependencies? set-global
 : compile-call ( quot -- )
     [ dup infer define-temp ] with-compilation-unit execute ;
 
+\ compile-call t "no-compile" set-word-prop
+
 SINGLETON: optimizing-compiler
 
 M: optimizing-compiler recompile ( words -- alist )
index 6fa5eae18562e148fa6842da194b5a334c129621..4a15f864a66cc726fdf3806d9cde484399343e9e 100644 (file)
@@ -124,11 +124,11 @@ SYMBOL: vocab-articles
 : check-class-description ( word element -- )
     [ class? not ]
     [ { $class-description } swap elements empty? not ] bi* and
-    [ "A word that is not a class has a $class-description" throw ] when ;
+    [ "A word that is not a class has a $class-description" simple-lint-error ] when ;
 
 : check-article-title ( article -- )
     article-title first LETTER?
-    [ "Article title must begin with a capital letter" throw ] unless ;
+    [ "Article title must begin with a capital letter" simple-lint-error ] unless ;
 
 : check-elements ( element -- )
     {
index e25070126c402a1ef9ecb0bec09ce14559386e64..ec373882a20c23d58085d92438e4fda4aa7f75be 100755 (executable)
@@ -3,7 +3,7 @@
 USING: assocs continuations fry help help.lint.checks
 help.topics io kernel namespaces parser sequences
 source-files.errors tools.vocabs vocabs words classes
-locals ;
+locals tools.errors ;
 FROM: help.lint.checks => all-vocabs ;
 IN: help.lint
 
@@ -15,11 +15,15 @@ TUPLE: help-lint-error < source-file-error ;
 
 SYMBOL: +help-lint-failure+
 
-+help-lint-failure+
-"vocab:ui/tools/error-list/icons/help-lint-error.tiff"
-[ lint-failures get values ] define-error-type
+T{ error-type
+   { type +help-lint-failure+ }
+   { word ":lint-failures" }
+   { plural "help lint failures" }
+   { icon "vocab:ui/tools/error-list/icons/help-lint-error.tiff" }
+   { quot [ lint-failures get values ] }
+} define-error-type
 
-M: help-lint-error source-file-error-type drop +help-lint-failure+ ;
+M: help-lint-error error-type drop +help-lint-failure+ ;
 
 <PRIVATE
 
@@ -66,8 +70,7 @@ PRIVATE>
 
 : check-vocab ( vocab -- )
     "Checking " write dup write "..." print
-    vocab
-    [ check-about ]
+    [ vocab check-about ]
     [ words [ check-word ] each ]
     [ vocab-articles get at [ check-article ] each ]
     tri ;
@@ -84,6 +87,8 @@ PRIVATE>
 
 : help-lint-all ( -- ) "" help-lint ;
 
+: :lint-failures ( -- ) lint-failures get errors. ;
+
 : unlinked-words ( words -- seq )
     all-word-help [ article-parent not ] filter ;
 
index 4f7ccf227e54e12567e6e4d7f47916fa123278d5..1f01388c14ba8e166fa2b098dfe0a6e70e4d72de 100644 (file)
@@ -4,7 +4,7 @@ USING: arrays hashtables io kernel math math.parser memory
 namespaces parser lexer sequences strings io.styles
 vectors words generic system combinators continuations debugger
 definitions compiler.units accessors colors prettyprint fry
-sets vocabs.parser ;
+sets vocabs.parser source-files.errors ;
 IN: listener
 
 GENERIC: stream-read-quot ( stream -- quot/f )
@@ -68,6 +68,8 @@ SYMBOL: max-stack-items
 
 10 max-stack-items set-global
 
+SYMBOL: error-summary-hook
+
 <PRIVATE
 
 : title. ( string -- )
@@ -105,8 +107,10 @@ SYMBOL: max-stack-items
     "( " in get auto-use? get [ " - auto" append ] when " )" 3append
     H{ { background T{ rgba f 1 0.7 0.7 1 } } } format bl flush ;
 
+[ error-summary ] error-summary-hook set-global
+
 : listen ( -- )
-    visible-vars. stacks. prompt.
+    error-summary-hook get call( -- ) visible-vars. stacks. prompt.
     [ read-quot [ [ call-error-hook ] recover ] [ bye ] if* ]
     [ dup lexer-error? [ call-error-hook ] [ rethrow ] if ] recover ;
 
index 4e10fc3de4548e3afc165ad5b8b5a64c055cfb9f..74ca07cda305d0b4322f92d9b8cb36a119d93a63 100644 (file)
@@ -61,3 +61,5 @@ M: memoized reset-word
 
 : invalidate-memoized ( inputs... word -- )
     [ stack-effect in>> packer call ] [ "memoize" word-prop delete-at ] bi ;
+
+\ invalidate-memoized t "no-compile" set-word-prop
\ No newline at end of file
index 799e3f73e3e848f6d5ff7ea5a350def41513aea0..156900f7270758bc17ad5efb19307e71a4392d79 100644 (file)
@@ -11,7 +11,7 @@ IN: stack-checker.errors
 
 TUPLE: inference-error error type word ;
 
-M: inference-error source-file-error-type type>> ;
+M: inference-error error-type type>> ;
 
 : (inference-error) ( ... class type -- * )
     [ boa ] dip
index c55e69a8a275fcda4af42d749345d63880cfad3d..a16701cbd3eab6f9489e6020a3a113a4e5b320a7 100644 (file)
@@ -218,9 +218,6 @@ M: object infer-call*
     alien-callback
 } [ t "special" set-word-prop ] each
 
-{ call execute dispatch load-locals get-local drop-locals }
-[ t "no-compile" set-word-prop ] each
-
 : non-inline-word ( word -- )
     dup called-dependency depends-on
     {
index b66b557a81f3efb7b12d0a41987cadfac64c3d7d..8fff063847e4485374b0f9443476461dc37f2b8a 100644 (file)
@@ -15,18 +15,11 @@ $nl
 "Words to view warnings and errors:"
 { $subsection :errors }
 { $subsection :warnings }
-{ $subsection :linkage }
-"Words such as " { $link require } " use a combinator which counts errors and prints a report at the end:"
-{ $subsection with-compiler-errors } ;
+{ $subsection :linkage } ;
 
 HELP: compiler-error
 { $values { "error" "an error" } { "word" word } }
-{ $description "If inside a " { $link with-compiler-errors } ", saves the error for future persual via " { $link :errors } ", " { $link :warnings } " and " { $link :linkage } ". If not inside a " { $link with-compiler-errors } ", ignores the error." } ;
-
-HELP: with-compiler-errors
-{ $values { "quot" quotation } }
-{ $description "Calls the quotation and collects any compiler warnings and errors. Compiler warnings and errors are summarized at the end and can be viewed with " { $link :errors } ", " { $link :warnings } ", and " { $link :linkage } "." }
-{ $notes "Nested calls to " { $link with-compiler-errors } " are ignored, and only the outermost call collects warnings and errors." } ;
+{ $description "Saves the error for future persual via " { $link :errors } ", " { $link :warnings } " and " { $link :linkage } "." } ;
 
 HELP: :errors
 { $description "Prints all serious compiler errors from the most recent compile to " { $link output-stream } "." } ;
index 9a9be7ddd3f884600bca43e0bd4b2b813b2e42e0..b2340a2c52034345e454d7da38e196dff9f27870 100644 (file)
@@ -13,13 +13,19 @@ TUPLE: test-failure < source-file-error continuation ;
 
 SYMBOL: +test-failure+
 
-M: test-failure source-file-error-type drop +test-failure+ ;
+M: test-failure error-type drop +test-failure+ ;
 
 SYMBOL: test-failures
 
 test-failures [ V{ } clone ] initialize
 
-+test-failure+ "vocab:ui/tools/error-list/icons/unit-test-error.tiff" [ test-failures get ] define-error-type
+T{ error-type
+   { type +test-failure+ }
+   { word ":test-failures" }
+   { plural "unit test failures" }
+   { icon "vocab:ui/tools/error-list/icons/unit-test-error.tiff" }
+   { quot [ test-failures get ] }
+} define-error-type
 
 <PRIVATE
 
@@ -130,12 +136,9 @@ M: test-failure error. ( error -- )
     [ traceback-button. ]
     bi ;
 
-: :failures ( -- ) test-failures get errors. ;
+: :test-failures ( -- ) test-failures get errors. ;
 
 : test ( prefix -- )
-    [ child-vocabs [ run-vocab-tests ] each ] with-compiler-errors
-    test-failures get [
-        ":failures - show " write length pprint " failing tests." print
-    ] unless-empty ;
+    child-vocabs [ run-vocab-tests ] each ;
 
 : test-all ( -- ) "" test ;
index 6167a5be233fe5a42884d8d667c9be52563e1e45..66618ee23c5e1abd39a56246f736fa4d23feab1f 100644 (file)
@@ -78,7 +78,7 @@ SYMBOL: failures
             recover\r
         ] each\r
         failures get\r
-    ] with-compiler-errors ;\r
+    ] with-scope ;\r
 \r
 : source-modified? ( path -- ? )\r
     dup source-files get at [\r
index 23db13533f696733abe08bc07d1e41f5769f92e4..019538d31c1f767fb96311f3c9be6c240963d9ec 100644 (file)
@@ -26,7 +26,7 @@ MEMO: error-icon ( type -- image-name )
 
 : <error-toggle> ( -- model gadget )
     #! Linkage errors are not shown by default.
-    error-types [ dup +linkage-error+ eq? not <model> ] { } map>assoc
+    error-types get keys [ dup +linkage-error+ eq? not <model> ] { } map>assoc
     [ [ [ error-icon ] dip ] assoc-map <checkboxes> ]
     [ <mapping> ] bi ;
 
@@ -75,7 +75,7 @@ SINGLETON: error-renderer
 M: error-renderer row-columns
     drop [
         {
-            [ source-file-error-type error-icon ]
+            [ error-type error-icon ]
             [ line#>> number>string ]
             [ asset>> unparse-short ]
             [ error>> summary ]
@@ -142,7 +142,7 @@ error-display "toolbar" f {
     [ <toolbar> ] [ error-toggle>> "Show errors:" label-on-left add-gadget ] bi ;
 
 : <error-model> ( visible-errors model -- model' )
-    [ swap '[ source-file-error-type _ at ] filter ] <smart-arrow> ;
+    [ swap '[ error-type _ at ] filter ] <smart-arrow> ;
 
 :: <error-list-gadget> ( model -- gadget )
     vertical error-list-gadget new-track
@@ -192,4 +192,10 @@ M: updater definitions-changed
 
 : error-list-window ( -- )
     compiler-error-model get-global <error-list-gadget>
-    "Errors" open-status-window ;
\ No newline at end of file
+    "Errors" open-status-window ;
+
+: show-error-list ( -- )
+    [ error-list-gadget? ] find-window
+    [ raise-window ] [ error-list-window ] if* ;
+
+\ show-error-list H{ { +nullary+ t } } define-command
index 7cb3c70cbc2de118de752be69697f5463fd4e78c..97821d61c73bd74d44499ac492c4234ddbc120e5 100644 (file)
@@ -1,10 +1,10 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs calendar combinators locals
-colors.constants combinators.short-circuit compiler.units
-help.tips concurrency.flags concurrency.mailboxes continuations
-destructors documents documents.elements fry hashtables help
-help.markup io io.styles kernel lexer listener math models
+source-files.errors colors.constants combinators.short-circuit
+compiler.units help.tips concurrency.flags concurrency.mailboxes
+continuations destructors documents documents.elements fry hashtables
+help help.markup io io.styles kernel lexer listener math models
 models.delay models.arrow namespaces parser prettyprint quotations
 sequences strings threads tools.vocabs vocabs vocabs.loader
 vocabs.parser words debugger ui ui.commands ui.pens.solid ui.gadgets
@@ -13,7 +13,7 @@ ui.gadgets.labeled ui.gadgets.panes ui.gadgets.scrollers
 ui.gadgets.status-bar ui.gadgets.tracks ui.gadgets.borders ui.gestures
 ui.operations ui.tools.browser ui.tools.common ui.tools.debugger
 ui.tools.listener.completion ui.tools.listener.popups
-ui.tools.listener.history ;
+ui.tools.listener.history ui.tools.error-list ;
 IN: ui.tools.listener
 
 ! If waiting is t, we're waiting for user input, and invoking
@@ -356,10 +356,17 @@ interactor "completion" f {
     { T{ key-down f { C+ } "r" } history-completion-popup }
 } define-command-map
 
+: ui-error-summary ( -- )
+    all-errors empty? [
+        { "Press " { $command tool "common" show-error-list } " to view errors." }
+        print-element nl
+    ] unless ;
+
 : listener-thread ( listener -- )
     dup listener-streams [
         [ com-browse ] help-hook set
         '[ [ _ input>> ] 2dip debugger-popup ] error-hook set
+        [ ui-error-summary ] error-summary-hook set
         tip-of-the-day. nl
         listener
     ] with-streams* ;
index cd4216b7a194533dbf3f0fa2b793810debbdd8f4..c825c60dbb78bab21db794dfab4048a1c5e73698 100644 (file)
@@ -30,4 +30,5 @@ tool "common" f {
     { T{ key-down f { A+ } "w" } close-window }
     { T{ key-down f { A+ } "q" } com-exit }
     { T{ key-down f f "F2" } refresh-all }
+    { T{ key-down f f "F3" } show-error-list }
 } define-command-map
\ No newline at end of file
index 987db582b4edbc8b14b4c8d36bfba179a17a01de..6dbe5193aa31fbdce1c962bc5d2545014fa46ff7 100644 (file)
@@ -2,7 +2,4 @@ IN: compiler.errors
 USING: help.markup help.syntax vocabs.loader words io
 quotations words.symbol ;
 
-HELP: compiler-errors
-{ $var-description "Global variable holding an assoc mapping words to compiler errors. This variable is set by " { $link with-compiler-errors } "." } ;
-
 ABOUT: "compiler-errors"
index 00f9860b3a117c687d016722ce57c7a39f5b9548..7e384d1a71d0866a98120670e4f390defff4cf6b 100644 (file)
@@ -1,13 +1,11 @@
 ! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel namespaces make assocs io sequences
-continuations math math.parser accessors definitions
-source-files.errors ;
+USING: accessors source-files.errors kernel namespaces assocs ;
 IN: compiler.errors
 
 TUPLE: compiler-error < source-file-error ;
 
-M: compiler-error source-file-error-type error>> source-file-error-type ;
+M: compiler-error error-type error>> error-type ;
 
 SYMBOL: compiler-errors
 
@@ -15,34 +13,34 @@ compiler-errors [ H{ } clone ] initialize
 
 SYMBOLS: +compiler-error+ +compiler-warning+ +linkage-error+ ;
 
-+compiler-error+ "vocab:ui/tools/error-list/icons/compiler-error.tiff" [ compiler-errors get values ] define-error-type
-+compiler-warning+ "vocab:ui/tools/error-list/icons/compiler-warning.tiff" [ f ] define-error-type
-+linkage-error+ "vocab:ui/tools/error-list/icons/linkage-error.tiff" [ f ] define-error-type
-
-SYMBOL: with-compiler-errors?
-
 : errors-of-type ( type -- assoc )
     compiler-errors get-global
-    swap [ [ nip source-file-error-type ] dip eq? ] curry
+    swap [ [ nip error-type ] dip eq? ] curry
     assoc-filter ;
 
-: (compiler-report) ( what type word -- )
-    over errors-of-type assoc-empty? [ 3drop ] [
-        [
-            ":" %
-            %
-            " - print " %
-            errors-of-type assoc-size #
-            " " %
-            %
-            "." %
-        ] "" make print
-    ] if ;
-
-: compiler-report ( -- )
-    "compiler errors" +compiler-error+ "errors" (compiler-report)
-    "compiler warnings" +compiler-warning+ "warnings" (compiler-report)
-    "linkage errors" +linkage-error+ "linkage" (compiler-report) ;
+T{ error-type
+   { type +compiler-error+ }
+   { word ":errors" }
+   { plural "compiler errors" }
+   { icon "vocab:ui/tools/error-list/icons/compiler-error.tiff" }
+   { quot [ +compiler-error+ errors-of-type values ] }
+} define-error-type
+
+T{ error-type
+   { type +compiler-warning+ }
+   { word ":warnings" }
+   { plural "compiler warnings" }
+   { icon "vocab:ui/tools/error-list/icons/compiler-warning.tiff" }
+   { quot [ +compiler-warning+ errors-of-type values ] }
+} define-error-type
+
+T{ error-type
+   { type +linkage-error+ }
+   { word ":linkage" }
+   { plural "linkage errors" }
+   { icon "vocab:ui/tools/error-list/icons/linkage-error.tiff" }
+   { quot [ +linkage-error+ errors-of-type values ] }
+} define-error-type
 
 : <compiler-error> ( error word -- compiler-error )
     \ compiler-error <definition-error> ;
@@ -50,11 +48,3 @@ SYMBOL: with-compiler-errors?
 : compiler-error ( error word -- )
     compiler-errors get-global pick
     [ [ [ <compiler-error> ] keep ] dip set-at ] [ delete-at drop ] if ;
-
-: with-compiler-errors ( quot -- )
-    with-compiler-errors? get "quiet" get or [ call ] [
-        [
-            with-compiler-errors? on
-            [ compiler-report ] [ ] cleanup
-        ] with-scope
-    ] if ; inline
index 04fa7fa03f7e04b92ae631f4466956ff23ff89b3..62a8e01c44463503b155038d7f49626fcb2857ea 100644 (file)
@@ -281,11 +281,9 @@ print-use-hook [ [ ] ] initialize
 
 : parse-file ( file -- quot )
     [
-        [
-            [ parsing-file ] keep
-            [ utf8 <file-reader> ] keep
-            parse-stream
-        ] with-compiler-errors
+        [ parsing-file ] keep
+        [ utf8 <file-reader> ] keep
+        parse-stream
     ] [
         over parse-file-restarts rethrow-restarts
         drop parse-file
index faabc6a37a4f139e6f166a370af054174348b20c..385ca7a496938825c65d83084c5b59e518e2708f 100644 (file)
@@ -12,7 +12,9 @@ TUPLE: source-file-error error asset file line# ;
 : group-by-source-file ( errors -- assoc )
     H{ } clone [ [ push-at ] curry [ dup file>> ] prepose each ] keep ;
 
-GENERIC: source-file-error-type ( error -- type )
+TUPLE: error-type type word plural icon quot ;
+
+GENERIC: error-type ( error -- type )
 
 : <definition-error> ( error definition class -- source-file-error )
     new
@@ -26,36 +28,31 @@ GENERIC: source-file-error-type ( error -- type )
 
 : delete-file-errors ( seq file type -- )
     [
-        [ swap file>> = ] [ swap source-file-error-type = ]
+        [ swap file>> = ] [ swap error-type = ]
         bi-curry* bi and not
     ] 2curry filter-here ;
 
-SYMBOL: source-file-error-types
-
-source-file-error-types [ V{ } clone ] initialize
+SYMBOL: error-types
 
-: error-types ( -- seq ) source-file-error-types get keys ;
+error-types [ V{ } clone ] initialize
 
-: define-error-type ( type icon quot -- )
-    2array swap source-file-error-types get set-at ;
+: define-error-type ( error-type -- )
+    dup type>> error-types get set-at ;
 
 : error-icon-path ( type -- icon )
-    source-file-error-types get at first ;
+    error-types get at icon>> ;
 
 : error-summary ( -- )
-    source-file-error-types get [
-        [ name>> "+" ?head drop "+" ?tail drop ]
-        [ second call length ] bi*
-    ] assoc-map
+    error-types get [ nip dup quot>> call( -- seq ) length ] assoc-map
     [ nip 0 > ] assoc-filter
     [
         over
-        [ ":" write write ]
-        [ " - print " write number>string write bl ]
-        [ { { CHAR: - CHAR: \s } } substitute write "s" print ] tri*
+        [ word>> write ]
+        [ " - show " write number>string write bl ]
+        [ plural>> print ] tri*
     ] assoc-each ;
 
 : all-errors ( -- errors )
-    source-file-error-types get
-    [ second second call( -- seq ) ] map
+    error-types get values
+    [ quot>> call( -- seq ) ] map
     concat ;
\ No newline at end of file
index 4f9005e11061fed8915062e79b77c3d838be274f..efe8cb2675e2bba9bbf5372464beeafff553cded 100644 (file)
@@ -80,11 +80,11 @@ SYMBOL: load-help?
 PRIVATE>
 
 : require ( vocab -- )
-    [ load-vocab drop ] with-compiler-errors ;
+    load-vocab drop ;
 
 : reload ( name -- )
     dup vocab
-    [ [ [ load-source ] [ load-docs ] bi ] with-compiler-errors ]
+    [ [ load-source ] [ load-docs ] bi ]
     [ require ]
     ?if ;
 
@@ -125,9 +125,7 @@ PRIVATE>
 [
     dup vocab-name blacklist get at* [ rethrow ] [
         drop dup find-vocab-root
-        [ [ (load-vocab) ] with-compiler-errors ]
-        [ dup vocab [ ] [ no-vocab ] ?if ]
-        if
+        [ (load-vocab) ] [ dup vocab [ ] [ no-vocab ] ?if ] if
     ] if
 ] load-vocab-hook set-global