diff --git a/pkgs/db-pkgs/db-lib/db/private/mysql/connection.rkt b/pkgs/db-pkgs/db-lib/db/private/mysql/connection.rkt index 0f392489ef..78f15589bf 100644 --- a/pkgs/db-pkgs/db-lib/db/private/mysql/connection.rkt +++ b/pkgs/db-pkgs/db-lib/db/private/mysql/connection.rkt @@ -185,8 +185,8 @@ [(struct handshake-packet (pver sver tid scramble capabilities charset status auth)) (check-required-flags capabilities) (unless (member auth '("mysql_native_password" #f)) - (raise-misc-error 'mysql-connect "back end requested unsupported authentication plugin" - '("plugin" value) auth)) + (error* 'mysql-connect "back end requested unsupported authentication plugin" + '("plugin" value) auth)) (define do-ssl? (and (case ssl ((yes optional) #t) ((no) #f)) (memq 'ssl capabilities))) @@ -217,8 +217,8 @@ [(equal? auth-plugin "mysql_old_password") (send-message (auth (bytes-append (old-scramble-password scramble password) (bytes 0))))] - [else (raise-misc-error 'mysql-connect "back end does not support authentication plugin" - '("plugin" value) auth-plugin)]) + [else (error* 'mysql-connect "back end does not support authentication plugin" + '("plugin" value) auth-plugin)]) (match (recv 'mysql-connect 'auth) [(struct ok-packet (_ _ status warnings message)) (after-connect)] @@ -229,8 +229,8 @@ (define/private (check-required-flags capabilities) (for-each (lambda (rf) (unless (memq rf capabilities) - (raise-misc-error 'mysql-connect "server does not support required capability" - "capability" rf))) + (error* 'mysql-connect "server does not support required capability" + "capability" rf))) REQUIRED-CAPABILITIES)) (define/private (desired-capabilities capabilities ssl? dbname) diff --git a/pkgs/db-pkgs/db-lib/db/private/odbc/connection.rkt b/pkgs/db-pkgs/db-lib/db/private/odbc/connection.rkt index 2aeffd50f1..8a57ca9936 100644 --- a/pkgs/db-pkgs/db-lib/db/private/odbc/connection.rkt +++ b/pkgs/db-pkgs/db-lib/db/private/odbc/connection.rkt @@ -519,8 +519,8 @@ (define/override (start-transaction* fsym isolation option) (when (eq? isolation 'nested) - (raise-misc-error fsym "already in transaction" - #:continued "nested transactions not supported for ODBC connections")) + (error* fsym "already in transaction" + #:continued "nested transactions not supported for ODBC connections")) (when option ;; No options supported (raise-argument-error fsym "#f" option)) @@ -544,8 +544,8 @@ ;; So if 0, use serializable. (if (zero? default-level) SQL_TXN_SERIALIZABLE default-level)))]) (when (zero? (bitwise-and requested-level ok-levels)) - (raise-misc-error fsym "requested isolation level is not available" - '("isolation level" value) isolation)) + (error* fsym "requested isolation level is not available" + '("isolation level" value) isolation)) (let ([status (SQLSetConnectAttr db SQL_ATTR_TXN_ISOLATION requested-level)]) (handle-status fsym status db))) (let ([status (SQLSetConnectAttr db SQL_ATTR_AUTOCOMMIT SQL_AUTOCOMMIT_OFF)]) diff --git a/pkgs/db-pkgs/db-lib/db/private/postgresql/connection.rkt b/pkgs/db-pkgs/db-lib/db/private/postgresql/connection.rkt index fd15851c9b..c6b3f0d330 100644 --- a/pkgs/db-pkgs/db-lib/db/private/postgresql/connection.rkt +++ b/pkgs/db-pkgs/db-lib/db/private/postgresql/connection.rkt @@ -146,8 +146,8 @@ (cond [(equal? name "client_encoding") (unless (equal? value "UTF8") (disconnect* #f) - (raise-misc-error fsym "client character encoding changed, disconnecting" - '("new encoding" value) value))] + (error* fsym "client character encoding changed, disconnecting" + '("new encoding" value) value))] [(equal? name "integer_datetimes") (set! integer-datetimes? (equal? value "on"))] [else (void)])])) diff --git a/pkgs/db-pkgs/db-lib/db/util/postgresql.rkt b/pkgs/db-pkgs/db-lib/db/util/postgresql.rkt index dcd19b80c2..9eabda3957 100644 --- a/pkgs/db-pkgs/db-lib/db/util/postgresql.rkt +++ b/pkgs/db-pkgs/db-lib/db/util/postgresql.rkt @@ -43,13 +43,13 @@ polygon = #points:int4 (x y : float8)* #:transparent #:guard (lambda (ndim counts lbounds vals _n) (unless (= (length counts) ndim) - (raise-misc-error 'pg-array "list for dimension lengths has wrong length" - "expected length" ndim - '("got" value) counts)) + (error* 'pg-array "list for dimension lengths has wrong length" + "expected length" ndim + '("got" value) counts)) (unless (= (length lbounds) ndim) - (raise-misc-error 'pg-array "list for dimension lower bounds has wrong length" - "expected length" ndim - '("got" value) lbounds)) + (error* 'pg-array "list for dimension lower bounds has wrong length" + "expected length" ndim + '("got" value) lbounds)) (let loop ([counts* counts] [vals* vals]) (when (pair? counts*) (unless (and (vector? vals*) @@ -61,19 +61,19 @@ polygon = #points:int4 (x y : float8)* (define (pg-array-ref arr . indexes) (unless (= (pg-array-dimensions arr) (length indexes)) - (raise-misc-error 'pg-array-ref "wrong number of indexes" - "expected number" (pg-array-dimensions arr) - '("got" value) indexes)) + (error* 'pg-array-ref "wrong number of indexes" + "expected number" (pg-array-dimensions arr) + '("got" value) indexes)) (let* ([counts (pg-array-dimension-lengths arr)] [lbounds (pg-array-dimension-lower-bounds arr)] [ubounds (map (lambda (c lb) (+ c lb -1)) counts lbounds)]) (unless (for/and ([index indexes] [lbound lbounds] [ubound ubounds]) (<= lbound index ubound)) - (raise-misc-error 'pg-array-ref "index out of range" - '("index" value) indexes - "valid range" (string-join (for/list ([lbound lbounds] [ubound ubounds]) - (format "[~a,~a]" lbound ubound)) - ", "))) + (error* 'pg-array-ref "index out of range" + '("index" value) indexes + "valid range" (string-join (for/list ([lbound lbounds] [ubound ubounds]) + (format "[~a,~a]" lbound ubound)) + ", "))) (let loop ([indexes (map - indexes lbounds)] [vals (pg-array-contents arr)]) (cond [(pair? indexes) diff --git a/pkgs/unstable-pkgs/unstable-doc/scribblings/error.scrbl b/pkgs/unstable-pkgs/unstable-doc/scribblings/error.scrbl index 06e24c0e19..a737e08e1e 100644 --- a/pkgs/unstable-pkgs/unstable-doc/scribblings/error.scrbl +++ b/pkgs/unstable-pkgs/unstable-doc/scribblings/error.scrbl @@ -10,21 +10,18 @@ @defmodule[unstable/error] -@defproc[(raise-misc-error [name symbol?] - [message string?] - [field (let ([option/c (or/c 'value 'multi 'maybe)]) - (or/c string? (cons/c string? (listof option/c))))] - [value any/c] ... ... - [#:continued continued-message (or/c string? (listof string?)) null] - [#:constructor constructor - (-> string? continuation-mark-set? exn?) - exn:fail]) +@defproc[(error* [name symbol?] + [message string?] + [field (let ([option/c (or/c 'value 'multi 'maybe)]) + (or/c string? (cons/c string? (listof option/c))))] + [value any/c] ... ... + [#:continued continued-message (or/c string? (listof string?)) null]) any]{ Raises an exception with a message composed according to the Racket @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{error -message convention}. The exception is created with -@racket[constructor], which is @racket[exn:fail] by default. +message convention}. The raised exception is an instance of +@racket[exn:fail]. The composed error message includes details consisting of the alternating @racket[field] and @racket[value] arguments. By default, @@ -36,7 +33,7 @@ options affect the formatting of the detail line: @item{@racket['multi] formats each element in the corresponding @racket[value], which must be a list, as a separate line; if @racket['maybe] is also provided, -then the detail line is omittable if the list is empty} +then the detail line is omitted if the list is empty} @item{@racket['value] formats the value using @racket[error-value->string-handler]; the detail line is not omittable @@ -46,22 +43,21 @@ unless @racket['maybe] or @racket['multi] is also provided} @examples[#:eval the-eval -(raise-misc-error 'mcbean "too many stars upon thars" - '("given" value) 'star-bellied-sneetch - '("stars" value) 3) +(error* 'mcbean "too many stars upon thars" + '("given" value) 'star-bellied-sneetch + '("stars" value) 3) -(raise-misc-error 'hal "unable to open pod bay doors" - #:continued - "this mission is too important to let you jeopardize it" - "threat" "David Bowman" - "detection" "lip reading") +(error* 'hal "unable to open pod bay doors" + #:continued "this mission is too important to let you jeopardize it" + "threat" "David Bowman" + "detection" "lip reading") -(raise-misc-error 'car "missing car keys" - '("searched" multi) - (list "dresser" "desk" "kitchen table" "under sofa" - "behind microwave" "in washing machine") - "last seen" - #f) +(error* 'car "missing car keys" + '("searched" multi) + (list "dresser" "desk" "kitchen table" "under sofa" + "behind microwave" "in washing machine") + "last seen" + #f) ] } @@ -95,7 +91,7 @@ and @racket[sub-expr] are mandatory arguments. [#:continued continued-message (or/c string? (listof string?)) null]) string?]{ -Like @racket[raise-misc-error], but produces a string conforming to +Like @racket[error*], but produces a string conforming to the Racket @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{error message convention}. } diff --git a/racket/collects/db/private/generic/functions.rkt b/racket/collects/db/private/generic/functions.rkt index 7e9df49cb2..db98a17f0e 100644 --- a/racket/collects/db/private/generic/functions.rkt +++ b/racket/collects/db/private/generic/functions.rkt @@ -526,9 +526,9 @@ (eq? (hash-ref table key not-given) not-given) ;; FIXME: okay to coalesce values if equal? (equal? value old-value)) - (raise-misc-error who "duplicate value for key" - '("key" value) key - '("values" multi value) (list old-value value))) + (error* who "duplicate value for key" + '("key" value) key + '("values" multi value) (list old-value value))) (if value-list? (hash-set table key (if (ok-value? value) diff --git a/racket/collects/db/private/generic/interfaces.rkt b/racket/collects/db/private/generic/interfaces.rkt index 38f715087b..2ee369a439 100644 --- a/racket/collects/db/private/generic/interfaces.rkt +++ b/racket/collects/db/private/generic/interfaces.rkt @@ -202,20 +202,20 @@ For SQLite, use symbol instead of SQLSTATE string. error/statement-binding-args) (define (error/internal fsym fmt . args) - (raise-misc-error fsym "internal error" - #:continued (apply format fmt args))) + (error* fsym "internal error" + #:continued (apply format fmt args))) (define (error/internal* fsym msg . args) - (apply raise-misc-error fsym "internal error" #:continued msg args)) + (apply error* fsym "internal error" #:continued msg args)) ;; FIXME; clean up (define (error/comm fsym [when-occurred #f]) - (raise-misc-error fsym "communication failure" - "when" when-occurred)) + (error* fsym "communication failure" + "when" when-occurred)) (define (error/no-support fsym feature) - (raise-misc-error fsym "feature not supported" - "feature" feature)) + (error* fsym "feature not supported" + "feature" feature)) (define (error/hopeless fsym) (error fsym "connection is permanently locked due to a terminated thread")) @@ -226,8 +226,8 @@ For SQLite, use symbol instead of SQLSTATE string. ;; ---- (define (error/invalid-nested-isolation fsym isolation) - (raise-misc-error fsym "invalid isolation level for nested transaction" - '("isolation level" value) isolation)) + (error* fsym "invalid isolation level for nested transaction" + '("isolation level" value) isolation)) (define (error/unbalanced-tx fsym mode saved-cwt?) (error fsym "~a-transaction without matching start-transaction~a" @@ -238,24 +238,24 @@ For SQLite, use symbol instead of SQLSTATE string. (if saved-cwt? " (within extent of call-with-transaction)" ""))) (define (error/tx-bad-stmt fsym stmt-type-string tx-state) - (raise-misc-error fsym "statement not allowed in current transaction state" - "statement type" stmt-type-string - "transaction state" tx-state)) + (error* fsym "statement not allowed in current transaction state" + "statement type" stmt-type-string + "transaction state" tx-state)) (define (error/nested-tx-option fsym option) - (raise-misc-error fsym "option not allowed for nested transaction" - '("option" value) option)) + (error* fsym "option not allowed for nested transaction" + '("option" value) option)) (define (error/exn-in-rollback fsym e1 e2) - (raise-misc-error fsym "error during rollback" - #:continued "secondary error occurred during rollback triggered by primary error" - '("primary" value) (exn-message e1) - '("secondary" value) (exn-message e2))) + (error* fsym "error during rollback" + #:continued "secondary error occurred during rollback triggered by primary error" + '("primary" value) (exn-message e1) + '("secondary" value) (exn-message e2))) ;; ---- (define (error/stmt-arity fsym expected given) - (raise-misc-error fsym "wrong number of parameters for query" + (error* fsym "wrong number of parameters for query" ;; FIXME: add stmt, use error/stmt "expected" expected "given" given)) @@ -268,22 +268,22 @@ For SQLite, use symbol instead of SQLSTATE string. ;; ---- (define (error/unsupported-type fsym typeid [type #f]) - (raise-misc-error fsym "unsupported type" - "type" type - "typeid" typeid)) + (error* fsym "unsupported type" + "type" type + "typeid" typeid)) (define (error/no-convert fsym sys type param [note #f] #:contract [ctc #f]) - (raise-misc-error fsym "cannot convert given value to SQL type" - '("given" value) param - "type" type - "expected" (and ctc (format "~.s" ctc)) - "dialect" sys - "note" note)) + (error* fsym "cannot convert given value to SQL type" + '("given" value) param + "type" type + "expected" (and ctc (format "~.s" ctc)) + "dialect" sys + "note" note)) ;; ---- (define (error/stmt fsym stmt message . args) - (apply raise-misc-error fsym message + (apply error* fsym message '("statement" value) (or (let loop ([stmt stmt]) (cond [(string? stmt) stmt] [(statement-binding? stmt) (loop (statement-binding-pst stmt))] @@ -317,7 +317,7 @@ For SQLite, use symbol instead of SQLSTATE string. "got" got-rows)) (define (error/statement-binding-args fsym stmt args) - (raise-misc-error fsym - "cannot execute statement-binding with additional inline arguments" - '("statement" value) stmt - '("arguments" value) args)) + (error* fsym + "cannot execute statement-binding with additional inline arguments" + '("statement" value) stmt + '("arguments" value) args)) diff --git a/racket/collects/db/private/sqlite3/connection.rkt b/racket/collects/db/private/sqlite3/connection.rkt index 69face42e9..2baf4a78a6 100644 --- a/racket/collects/db/private/sqlite3/connection.rkt +++ b/racket/collects/db/private/sqlite3/connection.rkt @@ -194,12 +194,12 @@ (sqlite3_prepare_v2 db sql)]) (when tail? (when stmt (sqlite3_finalize stmt)) - (raise-misc-error fsym "multiple statements given" - '("given" value) sql)) + (error* fsym "multiple statements given" + '("given" value) sql)) (values prep-status stmt)))]) (when DEBUG? (dprintf " << prepared statement #x~x\n" (cast stmt _pointer _uintptr))) - (unless stmt (raise-misc-error fsym "SQL syntax error" '("given" value) sql)) + (unless stmt (error* fsym "SQL syntax error" '("given" value) sql)) (let* ([param-typeids (for/list ([i (in-range (sqlite3_bind_parameter_count stmt))]) 'any)] diff --git a/racket/collects/unstable/error.rkt b/racket/collects/unstable/error.rkt index 159e258135..5e703fcad1 100644 --- a/racket/collects/unstable/error.rkt +++ b/racket/collects/unstable/error.rkt @@ -28,10 +28,9 @@ TODO (or/c '() (cons/c field/c (cons/c any/c details-list/c))))) (provide/contract - [raise-misc-error - (->* (symbol? string?) - (#:continued (or/c string? (listof string)) - #:constructor (-> string? continuation-mark-set? exn?)) + [error* + (->* [symbol? string?] + [#:continued (or/c string? (listof string))] #:rest details-list/c any)] [raise-syntax-error* @@ -40,23 +39,21 @@ TODO #:rest details-list/c any)] [compose-error-message - (->* ((or/c symbol? #f) string?) - (#:continued (or/c string? (listof string))) + (->* [(or/c symbol? #f) string?] + [#:continued (or/c string? (listof string))] #:rest details-list/c string?)]) ;; ---- -(define (raise-misc-error who message - #:details [detail-table null] - #:continued [continued-message null] - #:constructor [constructor exn:fail] - . field+detail-list) +(define (error* who message + #:continued [continued-message null] + . field+detail-list) (raise - (constructor + (exn:fail (compose* who message continued-message - (field+detail-list->table 'raise-misc-error field+detail-list detail-table)) + (field+detail-list->table 'error* field+detail-list null)) (current-continuation-marks)))) (define (raise-syntax-error* message0 stx sub-stx @@ -88,48 +85,20 @@ TODO ;; ---- (define (compose-error-message who message - #:details [detail-table null] #:continued [continued-message null] . field+detail-list) - (let ([details - (field+detail-list->table 'compose-error-message field+detail-list detail-table)]) - (compose* who message continued-message details))) + (define details + (field+detail-list->table 'compose-error-message field+detail-list null)) + (compose* who message continued-message details)) (define (compose* who message continued-message details) - (let* ([parts (let loop ([details details]) - (cond [(null? details) null] - [else - (let* ([field+opts (car (car details))] - [options (if (pair? field+opts) (cdr field+opts) '())] - [value? (memq 'value options)] - [multi? (memq 'multi options)] - [maybe? (memq 'maybe options)] - [convert-value - (cond [value? - (lambda (v) ((error-value->string-handler) v (error-print-width)))] - [else - (lambda (v) (format "~a" v))])] + (let* ([parts (apply append + (for/list ([detail (in-list details)]) + (let* ([field+opts (car detail)] [field (if (pair? field+opts) (car field+opts) field+opts)] - [value (cdr (car details))]) - (cond [(and (or maybe? multi? (not value?)) - (not value)) - (loop (cdr details))] - [(and maybe? multi? - (null? value)) - (loop (cdr details))] - [multi? - (list* "\n " field ": " - (let value-loop ([value value]) - (cond [(pair? value) - (list* "\n " - (convert-value (car value)) - (value-loop (cdr value)))] - [(null? value) - (loop (cdr details))])))] - [else - (list* "\n " field ": " - (convert-value value) - (loop (cdr details)))]))]))] + [options (if (pair? field+opts) (cdr field+opts) '())] + [value (cdr detail)]) + (compose-error-detail field options value))))] [parts (let loop ([continued continued-message]) (cond [(pair? continued) (list* "\n " (car continued) (loop (cdr continued)))] [(string? continued) (loop (list continued))] @@ -140,6 +109,36 @@ TODO parts)]) (apply string-append parts))) +;; compose-error-detail : string (listof option) any -> (listof string) +;; Note: includes a leading newline (unless detail omitted). +(define (compose-error-detail field options value) + (let* ([value? (memq 'value options)] + [multi? (memq 'multi options)] + [maybe? (memq 'maybe options)] + [convert-value + (cond [value? + (lambda (v) ((error-value->string-handler) v (error-print-width)))] + [else + (lambda (v) (format "~a" v))])]) + (cond [(and (or maybe? multi? (not value?)) + (not value)) + null] + [(and maybe? multi? + (null? value)) + null] + [multi? + (list* "\n " field ": " + (let value-loop ([value value]) + (cond [(pair? value) + (list* "\n " + (convert-value (car value)) + (value-loop (cdr value)))] + [(null? value) + null])))] + [else + (list "\n " field ": " + (convert-value value))]))) + ;; ---- (define (field+detail-list->table who lst onto) diff --git a/racket/collects/unstable/socket.rkt b/racket/collects/unstable/socket.rkt index 7ab87098e6..e28e18dc66 100644 --- a/racket/collects/unstable/socket.rkt +++ b/racket/collects/unstable/socket.rkt @@ -100,28 +100,28 @@ macosx (64): (define clean-path (cleanse-path (path->complete-path path0))) (define path-b (path->bytes clean-path)) (unless (< (bytes-length path-b) 100) - (raise-misc-error 'unix-socket-connect - "complete path must be less than 100 bytes" - '("path" value) path0 - '("complete path" value) clean-path)) + (error* 'unix-socket-connect + "complete path must be less than 100 bytes" + '("path" value) path0 + '("complete path" value) clean-path)) (define s (socket AF_UNIX SOCK_STREAM 0)) (unless (positive? s) (let ([errno (saved-errno)]) - (raise-misc-error 'unix-socket-connect - "failed to create socket" - "errno" errno - '("error" maybe) (strerror_r errno)))) + (error* 'unix-socket-connect + "failed to create socket" + "errno" errno + '("error" maybe) (strerror_r errno)))) (define addr (make-sockaddr path-b)) (define addrlen (+ (ctype-sizeof _ushort) (bytes-length path-b))) (define ce (connect s addr addrlen)) (unless (zero? ce) (close s) (let ([errno (saved-errno)]) - (raise-misc-error 'unix-socket-connect - "failed to connect socket" - '("path" value) path0 - "errno" errno - '("error" maybe) (strerror_r errno)))) + (error* 'unix-socket-connect + "failed to connect socket" + '("path" value) path0 + "errno" errno + '("error" maybe) (strerror_r errno)))) (with-handlers ([(lambda (e) #t) (lambda (e) (close s)