From 4b485812346ed45da5b7a06530bbbf049e548a0b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 7 Jan 2006 21:03:31 +0000 Subject: [PATCH] error handling documentation --- library/continuations.facts | 8 +++--- library/errors.factor | 26 +++++------------- library/errors.facts | 42 ++++++++++++++++++++++++++++-- library/help/markup.factor | 25 +++--------------- library/help/stylesheet.factor | 2 +- library/syntax/parse-stream.factor | 2 +- library/syntax/parser.factor | 4 +-- 7 files changed, 58 insertions(+), 51 deletions(-) diff --git a/library/continuations.facts b/library/continuations.facts index 86c6cb9e92..cd01fdccb5 100644 --- a/library/continuations.facts +++ b/library/continuations.facts @@ -21,18 +21,18 @@ HELP: >continuation< "( continuation -- data call name catch )" { $description "Takes a continuation apart into its four constituents." } ; HELP: ifcc "( terminator balance -- )" -{ $values { "terminator" "a quotation with stack effect " { $snippet "( continuation -- )" } { "balance" "a quotation" } } -{ $description "Reifies a continuation and passes it to " { $snippet "terminator" } ". When the continuation is restored, execution resumes; " { $snippet "terminator" } " is still on the stack and "{ $snippet "balance" } " is called." } +{ $values { "terminator" "a quotation with stack effect " { $snippet "( continuation -- )" } } { "balance" "a quotation" } } +{ $description "Reifies a continuation from the point immediately after which the caller returns, and passes it to " { $snippet "terminator" } ". When the continuation is restored, execution resumes; " { $snippet "terminator" } " is still on the stack and "{ $snippet "balance" } " is called." } { $see-also callcc0 callcc1 } ; HELP: callcc0 "( quot -- )" { $values { "quot" "a quotation with stack effect " { $snippet "( continuation -- )" } } } -{ $description "Applies the quotation to the current continuation. The " { $link continue } " word resumes the continuation." } +{ $description "Applies the quotation to the current continuation, which is reified from the point immediately after which the caller returns. The " { $link continue } " word resumes the continuation." } { $see-also ifcc callcc1 continue } ; HELP: callcc1 "( quot -- obj )" { $values { "quot" "a quotation with stack effect " { $snippet "( continuation -- )" } } { "obj" "an object provided when resuming the continuation" } } -{ $description "Applies the quotation to the current continuation. The " { $link continue-with } " word resumes the continuation, passing a value back to the original execution context." } +{ $description "Applies the quotation to the current continuation, which is reified from the point immediately after which the caller returns. The " { $link continue-with } " word resumes the continuation, passing a value back to the original execution context." } { $see-also ifcc callcc0 continue-with } ; HELP: continue "( continuation -- )" diff --git a/library/errors.factor b/library/errors.factor index 76f3dd6aec..50fcdbb141 100644 --- a/library/errors.factor +++ b/library/errors.factor @@ -10,32 +10,20 @@ TUPLE: no-method object generic ; : >c ( continuation -- ) catchstack* push ; : c> ( -- continuation ) catchstack* pop ; -: catch ( try -- exception/f | try: -- ) - #! Call the try quotation. If an exception is thrown in the - #! dynamic extent of the quotation, restore the datastack - #! and push the exception. Otherwise, the data stack is - #! not restored, and f is pushed. +: catch ( try -- error | try: -- ) [ >c call f c> drop f ] callcc1 nip ; inline -: rethrow ( error -- ) - #! Use rethrow when passing an error on from a catch block. - catchstack empty? - [ die "Can't happen" throw ] [ c> continue-with ] if ; - : cleanup ( try cleanup -- | try: -- | cleanup: -- ) - #! Call the try quotation. If an exception is thrown in the - #! dynamic extent of the quotation, restore the datastack - #! and run the cleanup quotation. Then throw the error to - #! the next outermost catch handler. [ >c >r call c> drop r> call ] - [ drop (continue-with) >r nip call r> rethrow ] ifcc ; inline + [ drop (continue-with) >r nip call r> rethrow ] ifcc ; + inline : recover ( try recovery -- | try: -- | recovery: error -- ) - #! Call the try quotation. If an exception is thrown in the - #! dynamic extent of the quotation, restore the datastack, - #! push the exception on the datastack, and call the - #! recovery quotation. [ >c drop call c> drop ] [ drop (continue-with) rot drop swap call ] ifcc ; inline +: rethrow ( error -- ) + catchstack* empty? + [ die "Can't happen" throw ] [ c> continue-with ] if ; + GENERIC: error. ( error -- ) diff --git a/library/errors.facts b/library/errors.facts index 09e17459d4..4ca88c008f 100644 --- a/library/errors.facts +++ b/library/errors.facts @@ -1,7 +1,45 @@ -USING: errors help ; +USING: errors help kernel ; + +HELP: no-method "( object generic -- )" +{ $values { "object" "an object" } { "generic" "a generic word" } } +{ $description "Throws an error indicating that " { $snippet "object" } " does not respond to the " { $snippet "generic" } " word." } ; + +HELP: >c "( continuation -- )" +{ $values { "continuation" "a continuation" } } +{ $description "Pushes an exception handler continuation on the catch stack. The continuation must have been reified by " { $link callcc1 } "." } ; HELP: throw "( error -- )" { $values { "error" "an object" } } -{ $description "Throws an error. Execution does not continue at the point after the " { $link throw } " call. Rather, the innermost catch block is invoked, and execution continues at that point." } ; +{ $description "Saves the current continuation in the " { $link error-continuation } " global variable and throws an error. Execution does not continue at the point after the " { $link throw } " call. Rather, the innermost catch block is invoked, and execution continues at that point." } +{ $see-also rethrow } ; +HELP: catch "( try -- error/f )" +{ $values { "try" "a quotation" } { "error/f" "an object" } } +{ $description "Calls the " { $snippet "try" } " quotation. If an error is thrown in the dynamic extent of the quotation, restores the datastack and pushes the error. If the quotation returns successfully, outputs " { $link f } " without restoring the datastack." } +{ $notes "This word cannot differentiate between the case of " { $link f } " being thrown, and no error being thrown. You should never throw " { $link f } ", and you should also use other error handling combinators where possible." } +{ $see-also cleanup recover } ; +HELP: cleanup "( try cleanup -- )" +{ $values { "try" "a quotation" } { "cleanup" "a quotation" } } +{ $description "Calls the " { $snippet "try" } " quotation. If an exception is thrown in the dynamic extent of the " { $snippet "try" } " quotation, restores the datastack, calls the " { $snippet "cleanup" } " quotation, and rethrows the error. If the " { $snippet "try" } " quotation returns successfully, calls the " { $snippet "cleanup" } " quotation without restoring the datastack." } +{ $see-also catch recover } ; + +HELP: recover "( try recovery -- )" +{ $values { "try" "a quotation" } { "recovery" "a quotation with stack effect " { $snippet "( error -- )" } } } +{ $description "Calls the " { $snippet "try" } " quotation. If an exception is thrown in the dynamic extent of the " { $snippet "try" } " quotation, restores the datastack and calls the " { $snippet "recovery" } " quotation to handle the error." } +{ $see-also catch cleanup } ; + +HELP: rethrow "( error -- )" +{ $values { "error" "an object" } } +{ $description "Throws an error without saving the current continuation in the " { $link error-continuation } " global variable. This is done so that inspecting the error stacks sheds light on the original cause of the exception, rather than the point where it was rethrown." } +{ $examples + "This word definition attempts to convert a hexadecimal literal string to an integer, and outputs " { $link f } " if there is an error:" + { $code + ": catch-hex> ( str -- n/f )" + " [ hex> ] [ [ drop f ] when ] catch ;" + } +} ; + +HELP: error. "( error -- )" +{ $values { "error" "an object" } } +{ $contract "Prints an error in human-readable form." } ; diff --git a/library/help/markup.factor b/library/help/markup.factor index c393b9bc89..82941d2ea4 100644 --- a/library/help/markup.factor +++ b/library/help/markup.factor @@ -108,29 +108,10 @@ M: simple-element print-element [ print-element ] each ; : textual-list ( seq quot -- ) [ "," format* bl ] interleave ; inline -: $see-methods - "Methods defined in the generic word:" format* terpri - [ order word-sort ] keep - [ "methods" word-prop hash . ] curry - sequence-outliner ; - -: $see-implementors - "Generic words defined for this class:" format* terpri - [ implementors word-sort ] keep - [ swap "methods" word-prop hash . ] curry - sequence-outliner ; - -: ($see) - terpri* - code-style [ with-nesting* ] with-style - terpri* ; - : $see ( content -- ) - first { - { [ dup class? ] [ $see-implementors ] } - { [ dup generic? ] [ $see-methods ] } - { [ t ] [ [ see ] ($see) ] } - } cond ; + terpri* + code-style [ [ first see ] with-nesting* ] with-style + terpri* ; : $example ( content -- ) first2 swap dup diff --git a/library/help/stylesheet.factor b/library/help/stylesheet.factor index 79d37c763a..df63620d76 100644 --- a/library/help/stylesheet.factor +++ b/library/help/stylesheet.factor @@ -27,7 +27,7 @@ USING: styles ; : code-style H{ { font "Monospaced" } - { page-color { 0.9 0.9 0.9 0.5 } } + { page-color { 0.9 0.9 1 0.5 } } { border-width 5 } { wrap-margin f } } ; diff --git a/library/syntax/parse-stream.factor b/library/syntax/parse-stream.factor index 7beef91ea4..5ff4590073 100644 --- a/library/syntax/parse-stream.factor +++ b/library/syntax/parse-stream.factor @@ -7,7 +7,7 @@ words ; : file-vocabs ( -- ) "scratchpad" set-in { "syntax" "scratchpad" } set-use ; -: with-parser ( quot -- ) [ parse-error ] recover ; +: with-parser ( quot -- ) [ rethrow ] recover ; : parse-lines ( lines -- quot ) [ diff --git a/library/syntax/parser.factor b/library/syntax/parser.factor index 23b2c301b8..544d505b99 100644 --- a/library/syntax/parser.factor +++ b/library/syntax/parser.factor @@ -30,9 +30,9 @@ SYMBOL: column TUPLE: parse-error file line col text ; -: parse-error ( msg -- ) +C: parse-error ( error -- error ) file get line-number get column get line-text get - [ set-delegate ] keep throw ; + [ set-delegate ] keep ; : skip ( i seq quot -- n | quot: elt -- ? ) over >r find* drop dup -1 =