Changed the wording of BSL error messages
This commit is contained in:
parent
103474a5f5
commit
2f3da4c4cd
|
@ -1,18 +1,54 @@
|
||||||
#lang racket
|
#lang racket
|
||||||
|
|
||||||
(require unstable/contract)
|
|
||||||
|
|
||||||
|
|
||||||
|
(define-syntax (test stx) #'(begin)) ;; TODO: convert my test into DrRacket's test framework
|
||||||
|
(require #;gmarceau/test
|
||||||
|
parser-tools/lex
|
||||||
|
(prefix-in : parser-tools/lex-sre)
|
||||||
|
(rename-in srfi/26 [cut //])
|
||||||
|
(only-in srfi/1 break)
|
||||||
|
unstable/contract)
|
||||||
|
|
||||||
|
;; An error message has many fragments. The fragments will be concatenated
|
||||||
|
;; before being presented to the user. Some fragment are simply string.
|
||||||
(struct msg-fragment:str (str) #:transparent)
|
(struct msg-fragment:str (str) #:transparent)
|
||||||
|
|
||||||
|
;; Some fragment are arbitrary values. They will be turned into snips if the error message display
|
||||||
|
;; context supports them. Otherwise, they will be turned into a string.
|
||||||
(struct msg-fragment:v (v) #:transparent)
|
(struct msg-fragment:v (v) #:transparent)
|
||||||
|
|
||||||
|
;; colored-msg-fragment represent a fragment of text in the error message that refers (in English)
|
||||||
|
;; to a particular piece of the code. DrRacket will highlight both the fragment text of the error message
|
||||||
|
;; and the piece with the same color.
|
||||||
|
;;
|
||||||
|
;; locs : which srcloc to highlight, one or many
|
||||||
|
;; frags : which fragments of text to highlight. (nested coloring in the error test is not allowed)
|
||||||
|
;; important : when true, the srcloc corresponding to this fragment will be highlighted even in contexts
|
||||||
|
;; that do not support highlighting of the error message text.
|
||||||
|
;; color : if false, DrRacket will assign a color to each fragment, from left to right order of the
|
||||||
|
;; messag text. Otherwise it should be a symbolic color (TBA).
|
||||||
(struct colored-msg-fragment (locs frags important color) #:transparent)
|
(struct colored-msg-fragment (locs frags important color) #:transparent)
|
||||||
|
|
||||||
|
;; msg-fragment? : Returns true if v is a fragment.
|
||||||
(define (msg-fragment? v) (or (msg-fragment:str v) (msg-fragment:v v) (colored-msg-fragment v)))
|
(define (msg-fragment? v) (or (msg-fragment:str v) (msg-fragment:v v) (colored-msg-fragment v)))
|
||||||
|
|
||||||
|
;; srcloc-syntax/c : Contract for specifications of code piece to highlight.
|
||||||
(define srcloc-syntax/c (rename-contract (or/c srcloc? syntax? (listof (or/c srcloc? syntax?))) 'srcloc-syntax/c))
|
(define srcloc-syntax/c (rename-contract (or/c srcloc? syntax? (listof (or/c srcloc? syntax?))) 'srcloc-syntax/c))
|
||||||
|
|
||||||
|
;; additional-highligts can specify their color
|
||||||
|
(define additional-highlights/c (listof (or/c srcloc-syntax/c (list/c srcloc-syntax/c symbol?))))
|
||||||
|
|
||||||
|
;; colored-error-message : Exceptions that support highlighting contain a colored-error-message
|
||||||
|
;; in addition to a string. The string message is automatically generated from
|
||||||
|
;; the colored-error-message for backward compatibility.
|
||||||
|
;; A colored-error-message has a list of fragments (some of which will be highlighted) and a list
|
||||||
|
;; of additional source locations. These additional location will also be highlighted in the code,
|
||||||
|
;; even though they do not correspond to any section of the text of the error message.
|
||||||
(struct colored-error-message (fragments additional-highlights) #:transparent)
|
(struct colored-error-message (fragments additional-highlights) #:transparent)
|
||||||
(provide/contract [struct colored-error-message
|
(provide/contract [struct colored-error-message
|
||||||
([fragments (listof msg-fragment?)]
|
([fragments (listof msg-fragment?)]
|
||||||
[additional-highlights srcloc-syntax/c])]
|
[additional-highlights additional-highlights/c])]
|
||||||
[struct msg-fragment:str ([str string?])]
|
[struct msg-fragment:str ([str string?])]
|
||||||
[struct msg-fragment:v ([v any/c])]
|
[struct msg-fragment:v ([v any/c])]
|
||||||
[struct colored-msg-fragment ([locs srcloc-syntax/c]
|
[struct colored-msg-fragment ([locs srcloc-syntax/c]
|
||||||
|
@ -20,6 +56,8 @@
|
||||||
[important boolean?]
|
[important boolean?]
|
||||||
[color (or/c #f symbol?)])])
|
[color (or/c #f symbol?)])])
|
||||||
|
|
||||||
|
;; prop:exn:colored-message : The property of exceptions that contain colored-message information.
|
||||||
|
;; The property's value is a function that when given an exception, returns the colored-error-message.
|
||||||
(define-values (prop:exn:colored-message
|
(define-values (prop:exn:colored-message
|
||||||
exn:colored-message?
|
exn:colored-message?
|
||||||
exn:colored-message-accessor)
|
exn:colored-message-accessor)
|
||||||
|
@ -29,6 +67,9 @@
|
||||||
(contract (exn? . -> . colored-error-message?) v
|
(contract (exn? . -> . colored-error-message?) v
|
||||||
'struct-definition 'color-error-accessor))))
|
'struct-definition 'color-error-accessor))))
|
||||||
|
|
||||||
|
;; get-error-message/color : When given an exception, if that exception contains coloring information,
|
||||||
|
;; returns it, otherwise, returns a colored-error-message that capture the information provided by
|
||||||
|
;; by field message and the srclocs property (if any) of the exception.
|
||||||
(provide/contract [get-error-messages/color (exn? . -> . colored-error-message?)])
|
(provide/contract [get-error-messages/color (exn? . -> . colored-error-message?)])
|
||||||
(define (get-error-messages/color exn)
|
(define (get-error-messages/color exn)
|
||||||
(cond [(exn:colored-message? exn) ((exn:colored-message-accessor exn) exn)]
|
(cond [(exn:colored-message? exn) ((exn:colored-message-accessor exn) exn)]
|
||||||
|
@ -38,13 +79,6 @@
|
||||||
[else
|
[else
|
||||||
(colored-error-message (list (msg-fragment:str (exn-message exn))) empty)]))
|
(colored-error-message (list (msg-fragment:str (exn-message exn))) empty)]))
|
||||||
|
|
||||||
(require gmarceau/test gmarceau/cut gmarceau/list gmarceau/contract gmarceau/util parser-tools/lex
|
|
||||||
(prefix-in : parser-tools/lex-sre)
|
|
||||||
(only-in srfi/1 break)
|
|
||||||
unstable/function)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define lex (lexer
|
(define lex (lexer
|
||||||
[(eof) empty]
|
[(eof) empty]
|
||||||
|
@ -62,6 +96,11 @@
|
||||||
(test 'lex (check-equal? (lex (open-input-string "~~foo ~| ~~| bar ~v|~ foo ~ "))
|
(test 'lex (check-equal? (lex (open-input-string "~~foo ~| ~~| bar ~v|~ foo ~ "))
|
||||||
'("~~foo " TildaPipe " ~~| bar " TildaV PipeTilda " foo ~ ")))
|
'("~~foo " TildaPipe " ~~| bar " TildaV PipeTilda " foo ~ ")))
|
||||||
|
|
||||||
|
(define-syntax (match? stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ v pattern) (syntax/loc stx
|
||||||
|
(match v [pattern #t] [_ #f]))]))
|
||||||
|
|
||||||
(define (check-tildas-are-paired parsed)
|
(define (check-tildas-are-paired parsed)
|
||||||
(let loop ([tildas (filter (// match? <> (or 'TildaPipe 'PipeTilda)) parsed)] [i 1])
|
(let loop ([tildas (filter (// match? <> (or 'TildaPipe 'PipeTilda)) parsed)] [i 1])
|
||||||
(match tildas
|
(match tildas
|
||||||
|
@ -133,8 +172,25 @@
|
||||||
(define color (and (list? the-arg) (findf symbol? the-arg)))
|
(define color (and (list? the-arg) (findf symbol? the-arg)))
|
||||||
(values (colored-msg-fragment (if (list? the-arg) (first the-arg) the-arg) sub is-important color) rest-args))
|
(values (colored-msg-fragment (if (list? the-arg) (first the-arg) the-arg) sub is-important color) rest-args))
|
||||||
|
|
||||||
(provide/contract [colored-format (([fmt string?]) (#:additional-highlights [additional-highlights srcloc-syntax/c]) #:rest [_ any/c]
|
(provide/contract [colored-format (([fmt string?]) (#:additional-highlights [additional-highlights additional-highlights/c]) #:rest [_ any/c]
|
||||||
. ->i . [_ colored-error-message?])])
|
. ->i . [_ colored-error-message?])])
|
||||||
|
|
||||||
|
;; colored-format : Takes a format string and a number of arguments, and produces a string where each
|
||||||
|
;; format marker has been replaced by their corresponding argument. This function support
|
||||||
|
;; all the formatting option of fprintf, plus:
|
||||||
|
;;
|
||||||
|
;; ~| ... |~ : The text between ~| and |~ will be highlighted with the same color as the corresponding piece
|
||||||
|
;; of code. Arbitrary text and formatting options can occur between ~| and |~, but not another ~| |~
|
||||||
|
;; (there is no nesting of ~| |~).
|
||||||
|
;; The argument is either a srcloc-syntax/c, or a list contain a srcloc-syntax/c in first position and
|
||||||
|
;; then one or two of (in either order): a boolean indicating whether this highlight is important
|
||||||
|
;; a symbol, indication the highlight color
|
||||||
|
;; The argument to ~| |~ should be given first, before the arguments for the formatting options appearing
|
||||||
|
;; between ~| and |~.
|
||||||
|
;;
|
||||||
|
;; ~v : Inserts an arbitrary value in this position. If the value can be converted to a snip, it will be,
|
||||||
|
;; otherwise ~v is equivalent to ~a.
|
||||||
|
;;
|
||||||
(define (colored-format fmt #:additional-highlights [additional-highlights empty] . args)
|
(define (colored-format fmt #:additional-highlights [additional-highlights empty] . args)
|
||||||
(define parsed (lex (open-input-string fmt)))
|
(define parsed (lex (open-input-string fmt)))
|
||||||
|
|
||||||
|
@ -186,13 +242,14 @@
|
||||||
(match f
|
(match f
|
||||||
[(msg-fragment:str str) str]
|
[(msg-fragment:str str) str]
|
||||||
[(msg-fragment:v v) (format "~a" v)]
|
[(msg-fragment:v v) (format "~a" v)]
|
||||||
[(colored-msg-fragment locs frags imp col)
|
[(colored-msg-fragment locs frags imp col) (loop frags)]
|
||||||
(string-append* (map loop frags))])))
|
[(? list?) (string-append* (map loop f))])))
|
||||||
|
|
||||||
(define (important-srclocs msg)
|
(define (important-srclocs msg)
|
||||||
(flatten
|
(append
|
||||||
(filter-map (// match <> [(colored-msg-fragment locs _ #t _) locs] [_ #f])
|
(flatten
|
||||||
(colored-error-message-fragments msg))
|
(filter-map (// match <> [(colored-msg-fragment locs _ #t _) locs] [_ #f])
|
||||||
|
(colored-error-message-fragments msg)))
|
||||||
(colored-error-message-additional-highlights msg)))
|
(colored-error-message-additional-highlights msg)))
|
||||||
|
|
||||||
(struct exn:fail:colored:syntax exn:fail:syntax (colored-message)
|
(struct exn:fail:colored:syntax exn:fail:syntax (colored-message)
|
||||||
|
@ -201,14 +258,30 @@
|
||||||
(define vec (struct->vector v))
|
(define vec (struct->vector v))
|
||||||
(vector-ref vec (sub1 (vector-length vec)))))
|
(vector-ref vec (sub1 (vector-length vec)))))
|
||||||
|
|
||||||
|
;; raise-colored-syntax-error : Formats the message string with colored-format, then raises a exn:fail:colored:syntax error.
|
||||||
|
;; The message and srcloc fields of the exception are populated from the information
|
||||||
|
;; in the fmt. additional-highlights specifies srclocs that should be highlighted, in addition
|
||||||
|
;; to the highlights used to explicate the correspondance between the text and the piece of codes.
|
||||||
(define (raise-colored-syntax-error fmt #:additional-highlights [additional-highlights empty] . args)
|
(define (raise-colored-syntax-error fmt #:additional-highlights [additional-highlights empty] . args)
|
||||||
(define formatted (apply colored-format fmt #:additional-highlights [additional-highlights empty] args))
|
(define formatted (apply colored-format fmt #:additional-highlights empty args))
|
||||||
(raise (exn:fail:colored:syntax (uncolor-message formatted)
|
(raise (exn:fail:colored:syntax (uncolor-message formatted)
|
||||||
(current-continuation-marks)
|
(current-continuation-marks)
|
||||||
(important-srclocs formatted)
|
(important-srclocs formatted)
|
||||||
formatted)))
|
formatted)))
|
||||||
|
|
||||||
|
(test 'raise-colored-syntax-error
|
||||||
|
(check-exn-msg exn:fail:colored:syntax? #rx"only one part"
|
||||||
|
(lambda () (raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~"
|
||||||
|
#'stx #'question)))
|
||||||
|
(check-match (with-handlers ([void (lambda (e) (get-error-messages/color e))])
|
||||||
|
(raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~"
|
||||||
|
#'stx #'question))
|
||||||
|
(colored-error-message (list (colored-msg-fragment
|
||||||
|
(? syntax?)
|
||||||
|
(list (msg-fragment:str "cond")) #f #f)
|
||||||
|
(msg-fragment:str ": expected a clause with a question and answer, but found a clause with only ")
|
||||||
|
(colored-msg-fragment (? syntax?) (list (msg-fragment:str "one part")) #f #f))
|
||||||
|
empty)))
|
||||||
|
|
||||||
|
|
||||||
(test 'get-error-messages/color
|
(test 'get-error-messages/color
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
(define arity-error "expects at least ~a arguments, given ~e")
|
(define arity-error "expects at least ~a arguments, given ~e")
|
||||||
|
|
||||||
;; String [format: String[expected] Any[given]
|
;; String [format: String[expected] Any[given]
|
||||||
(define proc-error "procedure expected as ~s argument, given ~e")
|
(define proc-error "a function was expected as ~s argument, given ~e")
|
||||||
|
|
||||||
;; check-proc :
|
;; check-proc :
|
||||||
;; sym (... *->* ...) num (union sym str) (union sym str) -> void
|
;; sym (... *->* ...) num (union sym str) (union sym str) -> void
|
||||||
|
@ -74,5 +74,5 @@
|
||||||
[else (format "multiple arities (~s)" arity-of-f)])))))
|
[else (format "multiple arities (~s)" arity-of-f)])))))
|
||||||
|
|
||||||
;; String [format: String[expected], String[position] Number[given]
|
;; String [format: String[expected], String[position] Number[given]
|
||||||
(define arity-error2 "procedure of ~a expected as ~s argument, given procedure of ~a ")
|
(define arity-error2 "a function that expects ~a expected as ~s argument, given a function that expects ~a ")
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
|
|
||||||
(module htdp-beginner scheme/base
|
(module htdp-beginner scheme/base
|
||||||
(require mzlib/etc
|
(require mzlib/etc
|
||||||
mzlib/list
|
mzlib/list
|
||||||
syntax/docprovide
|
syntax/docprovide
|
||||||
|
"private/rewrite-error-message.rkt"
|
||||||
|
(for-syntax "private/rewrite-error-message.rkt")
|
||||||
(for-syntax scheme/base))
|
(for-syntax scheme/base))
|
||||||
|
|
||||||
;; Implements the forms:
|
;; Implements the forms:
|
||||||
(require "private/teach.rkt"
|
(require "private/teach.ss"
|
||||||
"private/teach-module-begin.rkt"
|
"private/teach-module-begin.ss"
|
||||||
test-engine/scheme-tests)
|
test-engine/scheme-tests)
|
||||||
|
|
||||||
;; syntax:
|
;; syntax:
|
||||||
|
@ -84,15 +86,14 @@
|
||||||
(lambda (stx)
|
(lambda (stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(id . args)
|
[(id . args)
|
||||||
(syntax/loc stx (beginner-app orig-name . args))]
|
(syntax/loc stx
|
||||||
|
(with-handlers ([exn:fail:contract? (compose raise rewrite-contract-error-message)])
|
||||||
|
(beginner-app orig-name . args)))]
|
||||||
[_else
|
[_else
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(format
|
(format
|
||||||
"this ~a must be ~a; expected an open parenthesis before the ~a name"
|
"found a use that does not follow an open parenthesis")
|
||||||
what
|
|
||||||
something
|
|
||||||
what)
|
|
||||||
stx)]))
|
stx)]))
|
||||||
#'orig-name)))))]))
|
#'orig-name)))))]))
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
(module htdp-intermediate scheme/base
|
(module htdp-intermediate scheme/base
|
||||||
(require "private/teach.rkt"
|
|
||||||
"private/teachprims.rkt"
|
(require "private/teach.ss"
|
||||||
"private/teach-module-begin.rkt"
|
"private/teachprims.ss"
|
||||||
mzlib/etc
|
"private/teach-module-begin.ss"
|
||||||
mzlib/list
|
"private/rewrite-error-message.rkt"
|
||||||
syntax/docprovide
|
mzlib/etc
|
||||||
|
mzlib/list
|
||||||
|
syntax/docprovide
|
||||||
test-engine/scheme-tests)
|
test-engine/scheme-tests)
|
||||||
|
|
||||||
;; syntax:
|
;; syntax:
|
||||||
|
|
|
@ -44,9 +44,7 @@
|
||||||
[_
|
[_
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(string-append
|
"found a use that does not follow an open parenthesis"
|
||||||
"this primitive operator must be applied to arguments; "
|
|
||||||
"expected an open parenthesis before the operator name")
|
|
||||||
stx)])))
|
stx)])))
|
||||||
((syntax-local-certifier #t)
|
((syntax-local-certifier #t)
|
||||||
#'impl))))]))
|
#'impl))))]))
|
||||||
|
@ -59,7 +57,7 @@
|
||||||
(let ([args (syntax->list (syntax (arg ...)))])
|
(let ([args (syntax->list (syntax (arg ...)))])
|
||||||
(for-each (lambda (id)
|
(for-each (lambda (id)
|
||||||
(unless (identifier? id)
|
(unless (identifier? id)
|
||||||
(raise-syntax-error #f "not an identifier" stx id)))
|
(raise-syntax-error #f "expected a variable" stx id)))
|
||||||
(cons (syntax name)
|
(cons (syntax name)
|
||||||
args))
|
args))
|
||||||
(let ([new-args (generate-temporaries args)])
|
(let ([new-args (generate-temporaries args)])
|
||||||
|
@ -72,9 +70,7 @@
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(format
|
(format
|
||||||
"primitive operator ~a expects a defined procedure name (usually `~a') in this position"
|
"expects a function in this position")
|
||||||
'name
|
|
||||||
'#,arg)
|
|
||||||
s
|
s
|
||||||
(#,#'syntax #,new-arg)))))
|
(#,#'syntax #,new-arg)))))
|
||||||
args new-args)]
|
args new-args)]
|
||||||
|
@ -113,18 +109,20 @@
|
||||||
(syntax/loc s (tagged-impl wrapped-arg ...))
|
(syntax/loc s (tagged-impl wrapped-arg ...))
|
||||||
)]
|
)]
|
||||||
[(_ . rest)
|
[(_ . rest)
|
||||||
(raise-syntax-error
|
(let ([num-actuals (length (syntax->list #'rest))])
|
||||||
#f
|
(raise-syntax-error
|
||||||
(format
|
#f
|
||||||
"primitive operator requires ~a arguments"
|
(format
|
||||||
num-arguments)
|
"this function expects ~a argument~a, here it is provided ~a argument~a"
|
||||||
s)]
|
num-arguments
|
||||||
|
(if (= num-arguments 1) "" "s")
|
||||||
|
num-actuals
|
||||||
|
(if (= num-actuals 1) "" "s"))
|
||||||
|
s))]
|
||||||
[_
|
[_
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(string-append
|
"found a use that does not follow an open parenthesis"
|
||||||
"this primitive operator must be applied to arguments; "
|
|
||||||
"expected an open parenthesis before the operator name")
|
|
||||||
s)])))
|
s)])))
|
||||||
((syntax-local-certifier #t)
|
((syntax-local-certifier #t)
|
||||||
#'impl))))))))]))
|
#'impl))))))))]))
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
(define (arity-check t r f a)
|
(define (arity-check t r f a)
|
||||||
(unless (and (procedure? f) (procedure-arity-includes? f a))
|
(unless (and (procedure? f) (procedure-arity-includes? f a))
|
||||||
(if (= a 1)
|
(if (= a 1)
|
||||||
(hocheck t "~a argument must be a <procedure> that accepts one argument, given ~e" r f)
|
(hocheck t "~a argument must be a function that accepts one argument, given ~e" r f)
|
||||||
(hocheck t "~a argument must be a <procedure> that accepts ~a arguments, given ~e" r a f))))
|
(hocheck t "~a argument must be a function that accepts ~a arguments, given ~e" r a f))))
|
||||||
|
|
||||||
|
|
||||||
(define-syntax-rule
|
(define-syntax-rule
|
||||||
(boolean-test-wrapper tag (f z ...))
|
(boolean-test-wrapper tag (f z ...))
|
||||||
|
@ -27,12 +26,12 @@
|
||||||
(define f@x (f z ...))
|
(define f@x (f z ...))
|
||||||
(if (boolean? f@x)
|
(if (boolean? f@x)
|
||||||
f@x
|
f@x
|
||||||
(error tag "the results of ~a must be of type <boolean>, produced ~e" name f@x)))
|
(error tag "expected a boolean from ~a, but received ~e" name f@x)))
|
||||||
g))
|
g))
|
||||||
|
|
||||||
(define (list-check? name msg l)
|
(define (list-check? name msg l)
|
||||||
(unless (beginner-list? l)
|
(unless (beginner-list? l)
|
||||||
(hocheck name "~a argument must be of type <list>, given ~e" msg l)))
|
(hocheck name "expected a list for the ~a argument, given ~e" msg l)))
|
||||||
|
|
||||||
;; --- refined function definitions ---
|
;; --- refined function definitions ---
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@
|
||||||
(arity-check 'name "first" f 1)
|
(arity-check 'name "first" f 1)
|
||||||
(list-check? 'name "second" l)
|
(list-check? 'name "second" l)
|
||||||
(unless (beginner-list? l)
|
(unless (beginner-list? l)
|
||||||
(hocheck 'name "second argument must be of type <list>, given ~e" l))
|
(hocheck 'name "expected a list for the second argument, given ~e" l))
|
||||||
(define g (boolean-test-wrapper 'name (f x)))
|
(define g (boolean-test-wrapper 'name (f x)))
|
||||||
(name g l))))
|
(name g l))))
|
||||||
|
|
||||||
|
|
56
collects/lang/private/rewrite-error-message.rkt
Executable file
56
collects/lang/private/rewrite-error-message.rkt
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
#lang scheme/base
|
||||||
|
|
||||||
|
(require mzlib/etc mzlib/list)
|
||||||
|
(require (for-syntax scheme/base))
|
||||||
|
(require (for-syntax "firstorder.ss"))
|
||||||
|
|
||||||
|
(provide rewrite-contract-error-message
|
||||||
|
rewrite-lookup-error-message/rand
|
||||||
|
rewrite-lookup-error-message/rator
|
||||||
|
wrap-for-contract-error-message
|
||||||
|
wrap-for-lookup-error-message
|
||||||
|
::)
|
||||||
|
|
||||||
|
(define (rewrite-lookup-error-message/rator e)
|
||||||
|
(rewrite-lookup-error-message e "function"))
|
||||||
|
|
||||||
|
(define (rewrite-lookup-error-message/rand e)
|
||||||
|
(rewrite-lookup-error-message e "variable"))
|
||||||
|
|
||||||
|
(define (rewrite-lookup-error-message e var-or-function)
|
||||||
|
(define new-message
|
||||||
|
(regexp-replace* #rx"reference to an identifier before its definition"
|
||||||
|
(exn-message e)
|
||||||
|
(format "this is ~a not defined" var-or-function)))
|
||||||
|
(struct-copy exn e [message new-message]))
|
||||||
|
|
||||||
|
(define-syntax (wrap-for-lookup-error-message stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ . id)
|
||||||
|
(with-syntax ([top (syntax/loc stx #%top)])
|
||||||
|
(syntax/loc stx
|
||||||
|
(with-handlers ([exn:fail:contract:variable?
|
||||||
|
(compose raise rewrite-lookup-error-message)])
|
||||||
|
(top . id))))]))
|
||||||
|
|
||||||
|
(define (rewrite-contract-error-message e)
|
||||||
|
(define replacements
|
||||||
|
(list (list #rx"expects argument of type (<([^>]+)>)"
|
||||||
|
(lambda (all one two) (format "expects a ~a" two)))
|
||||||
|
(list #rx"expects type (<([^>]+)>)"
|
||||||
|
(lambda (all one two) (format "expects a ~a" two)))))
|
||||||
|
(define new-message
|
||||||
|
(for/fold ([msg (exn-message e)]) ([repl. replacements])
|
||||||
|
(regexp-replace* (first repl.) msg (second repl.))))
|
||||||
|
(struct-copy exn e [message new-message]))
|
||||||
|
|
||||||
|
(define-for-syntax (wrap-for-contract-error-message* stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ new old)
|
||||||
|
#'(define (new . args)
|
||||||
|
(with-handlers ([exn:fail:contract? (compose raise rewrite-contract-error-message)])
|
||||||
|
(apply old args)))]))
|
||||||
|
|
||||||
|
(define-syntax wrap-for-contract-error-message wrap-for-contract-error-message*)
|
||||||
|
|
||||||
|
(define-syntax :: wrap-for-contract-error-message*) ;; to circumvent most of the ugliness of provide-and-document/wrap's renaming of the function's infered name
|
|
@ -40,15 +40,16 @@
|
||||||
scheme/match
|
scheme/match
|
||||||
"set-result.rkt"
|
"set-result.rkt"
|
||||||
(only racket/base define-struct)
|
(only racket/base define-struct)
|
||||||
racket/struct-info
|
"rewrite-error-message.rkt"
|
||||||
deinprogramm/signature/signature-english
|
racket/struct-info
|
||||||
(all-except deinprogramm/signature/signature signature-violation)
|
deinprogramm/signature/signature-english
|
||||||
(all-except lang/private/signature-syntax property)
|
(all-except deinprogramm/signature/signature signature-violation)
|
||||||
(rename lang/private/signature-syntax signature:property property)
|
(all-except lang/private/signature-syntax property)
|
||||||
(all-except deinprogramm/quickcheck/quickcheck property)
|
(rename lang/private/signature-syntax signature:property property)
|
||||||
(rename deinprogramm/quickcheck/quickcheck quickcheck:property property)
|
(all-except deinprogramm/quickcheck/quickcheck property)
|
||||||
test-engine/racket-tests
|
(rename deinprogramm/quickcheck/quickcheck quickcheck:property property)
|
||||||
scheme/class
|
test-engine/racket-tests
|
||||||
|
scheme/class
|
||||||
"../posn.rkt"
|
"../posn.rkt"
|
||||||
(only lang/private/teachprims
|
(only lang/private/teachprims
|
||||||
beginner-equal? beginner-equal~? teach-equal?
|
beginner-equal? beginner-equal~? teach-equal?
|
||||||
|
@ -256,8 +257,7 @@
|
||||||
name
|
name
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"found a use of `~a' that does not follow an open parenthesis"
|
"found a use that does not follow an open parenthesis"))
|
||||||
name))
|
|
||||||
|
|
||||||
;; Use for messages "expected ..., found <something else>"
|
;; Use for messages "expected ..., found <something else>"
|
||||||
(define (something-else v)
|
(define (something-else v)
|
||||||
|
@ -265,6 +265,7 @@
|
||||||
(cond
|
(cond
|
||||||
[(number? v) "a number"]
|
[(number? v) "a number"]
|
||||||
[(string? v) "a string"]
|
[(string? v) "a string"]
|
||||||
|
[(list? v) "a part"]
|
||||||
[else "something else"])))
|
[else "something else"])))
|
||||||
|
|
||||||
(define (ordinal n)
|
(define (ordinal n)
|
||||||
|
@ -319,11 +320,9 @@
|
||||||
(when b
|
(when b
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'duplicate
|
'duplicate
|
||||||
name
|
stx
|
||||||
#f
|
#f
|
||||||
(if (binding-in-this-module? b)
|
"~a was defined previously and cannot be re-defined" (syntax-e name)))))
|
||||||
"this name was defined previously and cannot be re-defined"
|
|
||||||
"this name has a built-in meaning and cannot be re-defined")))))
|
|
||||||
names)
|
names)
|
||||||
(if assign
|
(if assign
|
||||||
(with-syntax ([(name ...) (if (eq? assign #t)
|
(with-syntax ([(name ...) (if (eq? assign #t)
|
||||||
|
@ -394,11 +393,10 @@
|
||||||
who
|
who
|
||||||
stx
|
stx
|
||||||
(cadr exprs)
|
(cadr exprs)
|
||||||
"expected only one expression ~a, but found ~a extra part"
|
"expected only one expression ~a, but found ~a extra part~a"
|
||||||
where
|
where
|
||||||
(if (null? (cddr exprs))
|
(sub1 (length exprs))
|
||||||
"one"
|
(if (> (length exprs) 2) "s" ""))))
|
||||||
"at least one"))))
|
|
||||||
|
|
||||||
(define (check-single-result-expr exprs where enclosing-expr will-bind)
|
(define (check-single-result-expr exprs where enclosing-expr will-bind)
|
||||||
(check-single-expression where
|
(check-single-expression where
|
||||||
|
@ -540,7 +538,7 @@
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
names
|
names
|
||||||
"expected a function name for a definition, but the name is missing"))
|
"expected a name for the function, but nothing's there"))
|
||||||
(let loop ([names names][pos 0])
|
(let loop ([names names][pos 0])
|
||||||
(unless (null? names)
|
(unless (null? names)
|
||||||
(unless (identifier/non-kw? (car names))
|
(unless (identifier/non-kw? (car names))
|
||||||
|
@ -548,10 +546,10 @@
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
(car names)
|
(car names)
|
||||||
"expected a name for ~a, but found ~a"
|
"expected ~a, but found ~a"
|
||||||
(cond
|
(cond
|
||||||
[(zero? pos) "a function"]
|
[(zero? pos) "the name of the function"]
|
||||||
[else (format "the function's ~a argument" (ordinal pos))])
|
[else "a variable"])
|
||||||
(something-else/kw (car names))))
|
(something-else/kw (car names))))
|
||||||
(loop (cdr names) (add1 pos))))
|
(loop (cdr names) (add1 pos))))
|
||||||
(when (null? (cdr names))
|
(when (null? (cdr names))
|
||||||
|
@ -559,14 +557,14 @@
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
(syntax name-seq)
|
(syntax name-seq)
|
||||||
"expected at least one argument name after the function name, but found none"))
|
"expected at least one variable after the function name, but found none"))
|
||||||
(let ([dup (check-duplicate-identifier (cdr names))])
|
(let ([dup (check-duplicate-identifier (cdr names))])
|
||||||
(when dup
|
(when dup
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
dup
|
dup
|
||||||
"found an argument name that was used more than once: ~a"
|
"found a variable that was used more than once: ~a"
|
||||||
(syntax-e dup))))
|
(syntax-e dup))))
|
||||||
(check-single-result-expr (syntax->list (syntax (expr ...)))
|
(check-single-result-expr (syntax->list (syntax (expr ...)))
|
||||||
#f
|
#f
|
||||||
|
@ -604,7 +602,7 @@
|
||||||
(identifier/non-kw? (syntax name))
|
(identifier/non-kw? (syntax name))
|
||||||
(let ([exprs (syntax->list (syntax (expr ...)))])
|
(let ([exprs (syntax->list (syntax (expr ...)))])
|
||||||
(check-single-expression 'define
|
(check-single-expression 'define
|
||||||
(format "after the defined name ~a"
|
(format "after the variable name ~a"
|
||||||
(syntax-e (syntax name)))
|
(syntax-e (syntax name)))
|
||||||
stx
|
stx
|
||||||
exprs
|
exprs
|
||||||
|
@ -617,7 +615,7 @@
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
(syntax non-name)
|
(syntax non-name)
|
||||||
"expected a function name, constant name, or function header for `define', but found ~a"
|
"expected a variable name, or a function name and its variables (in parentheses), but found ~a"
|
||||||
(something-else/kw (syntax non-name)))]
|
(something-else/kw (syntax non-name)))]
|
||||||
;; Missing name:
|
;; Missing name:
|
||||||
[(_)
|
[(_)
|
||||||
|
@ -625,8 +623,7 @@
|
||||||
'define
|
'define
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a function name, constant name, or function header after `define', ~
|
"expected a variable name, or a function name and its variables (in parentheses), but nothing's there")]
|
||||||
but nothing's there")]
|
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error 'define stx)]))
|
(bad-use-error 'define stx)]))
|
||||||
|
|
||||||
|
@ -668,7 +665,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"found a `lambda' expression that is not a function definition")]
|
"found a lambda that is not a function definition")]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error 'lambda stx)]))
|
(bad-use-error 'lambda stx)]))
|
||||||
|
|
||||||
|
@ -691,7 +688,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
rhs
|
rhs
|
||||||
arg
|
arg
|
||||||
"expected a name for a function argument, but found ~a"
|
"expected a variable, but found ~a"
|
||||||
(something-else/kw arg))))
|
(something-else/kw arg))))
|
||||||
args)
|
args)
|
||||||
(when (null? args)
|
(when (null? args)
|
||||||
|
@ -699,14 +696,14 @@
|
||||||
'lambda
|
'lambda
|
||||||
rhs
|
rhs
|
||||||
(syntax arg-seq)
|
(syntax arg-seq)
|
||||||
"expected at least one argument name in the sequence after `lambda', but found none"))
|
"expected at least one variable after lambda, but found none"))
|
||||||
(let ([dup (check-duplicate-identifier args)])
|
(let ([dup (check-duplicate-identifier args)])
|
||||||
(when dup
|
(when dup
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'lambda
|
'lambda
|
||||||
rhs
|
rhs
|
||||||
dup
|
dup
|
||||||
"found an argument name that was used more than once: ~a"
|
"found a variable that was used more than once: ~a"
|
||||||
(syntax-e dup))))
|
(syntax-e dup))))
|
||||||
(check-single-result-expr (syntax->list (syntax (lexpr ...)))
|
(check-single-result-expr (syntax->list (syntax (lexpr ...)))
|
||||||
#f
|
#f
|
||||||
|
@ -719,7 +716,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
rhs
|
rhs
|
||||||
(syntax args)
|
(syntax args)
|
||||||
"expected a sequence of function arguments after `lambda', but found ~a"
|
"expected at least one variable (in parentheses) after lambda, but found ~a"
|
||||||
(something-else (syntax args)))]
|
(something-else (syntax args)))]
|
||||||
;; Bad lambda, no args:
|
;; Bad lambda, no args:
|
||||||
[(lam)
|
[(lam)
|
||||||
|
@ -727,7 +724,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
rhs
|
rhs
|
||||||
(syntax args)
|
(syntax args)
|
||||||
"expected a sequence of function arguments after `lambda', but nothing's there")]
|
"expected at least one variable (in parentheses) after lambda, but nothing's there")]
|
||||||
[_else 'ok])]
|
[_else 'ok])]
|
||||||
[_else 'ok]))
|
[_else 'ok]))
|
||||||
|
|
||||||
|
@ -753,7 +750,7 @@
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
(syntax name)
|
(syntax name)
|
||||||
"expected a structure type name after `define-struct', but found ~a"
|
"expected the structure name after define-struct, but found ~a"
|
||||||
(something-else/kw (syntax name)))]
|
(something-else/kw (syntax name)))]
|
||||||
;; Main case (`rest' is for nice error messages):
|
;; Main case (`rest' is for nice error messages):
|
||||||
[(_ name_ (field_ ...) . rest)
|
[(_ name_ (field_ ...) . rest)
|
||||||
|
@ -767,7 +764,7 @@
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
field
|
field
|
||||||
"expected a structure field name, found ~a"
|
"expected a field name, but found ~a"
|
||||||
(something-else field)))
|
(something-else field)))
|
||||||
(let ([sym (syntax-e field)])
|
(let ([sym (syntax-e field)])
|
||||||
(when (hash-table-get ht sym (lambda () #f))
|
(when (hash-table-get ht sym (lambda () #f))
|
||||||
|
@ -785,11 +782,9 @@
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
(car rest)
|
(car rest)
|
||||||
"expected nothing after the field name sequence in `define-struct', ~
|
"expected nothing after the field names, but found ~a extra part~a"
|
||||||
but found ~a extra part"
|
(length rest)
|
||||||
(if (null? (cdr rest))
|
(if (> (length rest) 1) "s" ""))))
|
||||||
"one"
|
|
||||||
"at least one"))))
|
|
||||||
(let-values ([(struct: constructor-name predicate-name getter-names setter-names)
|
(let-values ([(struct: constructor-name predicate-name getter-names setter-names)
|
||||||
(make-struct-names name fields stx)]
|
(make-struct-names name fields stx)]
|
||||||
[(field-count) (length fields)]
|
[(field-count) (length fields)]
|
||||||
|
@ -973,22 +968,20 @@
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
(syntax something)
|
(syntax something)
|
||||||
"expected a sequence of field names after the structure type name in `define-struct', ~
|
"expected at least one field name after the structure name, but found ~a"
|
||||||
but found ~a"
|
|
||||||
(something-else (syntax something)))]
|
(something-else (syntax something)))]
|
||||||
[(_ name_)
|
[(_ name_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
(syntax something)
|
(syntax something)
|
||||||
"expected a sequence of field names after the structure type name in `define-struct', ~
|
"expected at least one field name (in parentheses) after the structure name, but nothing's there")]
|
||||||
but nothing's there")]
|
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'define-struct
|
'define-struct
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a structure type name after `define-struct', but nothing's there")]
|
"expected the structure name after define-struct, but nothing's there")]
|
||||||
[_else (bad-use-error 'define-struct stx)]))
|
[_else (bad-use-error 'define-struct stx)]))
|
||||||
|
|
||||||
(define (beginner-define-struct/proc stx)
|
(define (beginner-define-struct/proc stx)
|
||||||
|
@ -1148,14 +1141,11 @@
|
||||||
'|function call|
|
'|function call|
|
||||||
stx
|
stx
|
||||||
fun
|
fun
|
||||||
"expected a ~a after an open parenthesis, but found ~a"
|
"expected a function after the open parenthesis, but found ~a"
|
||||||
(if lex-ok?
|
|
||||||
"name"
|
|
||||||
"defined function name or a primitive operation name")
|
|
||||||
what))])
|
what))])
|
||||||
(unless (and (identifier? fun) (or lex-ok? undef-check? (not lex?)))
|
(unless (and (identifier? fun) (or lex-ok? undef-check? (not lex?)))
|
||||||
(bad-app (if lex?
|
(bad-app (if lex?
|
||||||
"a function argument name"
|
"a variable"
|
||||||
(something-else fun))))
|
(something-else fun))))
|
||||||
;; The following check disallows calling thunks.
|
;; The following check disallows calling thunks.
|
||||||
;; It's disabled because we need to allow calls to
|
;; It's disabled because we need to allow calls to
|
||||||
|
@ -1165,31 +1155,29 @@
|
||||||
'|function call|
|
'|function call|
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected an argument after the function name for a function call, ~
|
"expected an argument after the function, but nothing's there"))
|
||||||
but nothing's there"))
|
|
||||||
(cond
|
(cond
|
||||||
[(and (not lex-ok?) (binding-in-this-module? binding))
|
[(and (not lex-ok?) (binding-in-this-module? binding))
|
||||||
;; An application of something defined as a constant
|
;; An application of something defined as a constant
|
||||||
(bad-app "something else")]
|
(bad-app "a variable")]
|
||||||
[(or lex-ok? (and binding (not (binding-in-this-module? binding))))
|
[(or lex-ok? (and binding (not (binding-in-this-module? binding))))
|
||||||
(syntax/loc stx (#%app rator rand ...))]
|
(with-syntax ([new-rator (syntax-property #'rator 'was-in-app-position #t)])
|
||||||
|
(syntax/loc stx (#%app new-rator rand ...)))]
|
||||||
[else
|
[else
|
||||||
;; We don't know what rator is, yet, and it might be local:
|
;; We don't know what rator is, yet, and it might be local:
|
||||||
(quasisyntax/loc
|
(with-syntax ([new-rator (syntax-property #'rator 'was-in-app-position #t)])
|
||||||
stx
|
(quasisyntax/loc
|
||||||
(#%app values #,(quasisyntax/loc
|
stx
|
||||||
stx
|
(#%app values #,(quasisyntax/loc
|
||||||
(beginner-app-continue rator rand ...))))]))]
|
stx
|
||||||
|
(beginner-app-continue new-rator rand ...)))))]))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'|function call|
|
'|function call|
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
(format
|
(format
|
||||||
"expected a ~a after an open parenthesis, but nothing's there"
|
"expected a function after the open parenthesis, but nothing's there"))]
|
||||||
(if lex-ok?
|
|
||||||
"name"
|
|
||||||
"defined function name or a primitive operation name")))]
|
|
||||||
[_else (bad-use-error '#%app stx)])))])
|
[_else (bad-use-error '#%app stx)])))])
|
||||||
(values (mk-app #f) (mk-app #t))))
|
(values (mk-app #f) (mk-app #t))))
|
||||||
|
|
||||||
|
@ -1206,9 +1194,11 @@
|
||||||
;; Something for which we probably need to report an error,
|
;; Something for which we probably need to report an error,
|
||||||
;; but let beginner-app take care of it:
|
;; but let beginner-app take care of it:
|
||||||
(syntax/loc stx (beginner-app rator rand ...)))
|
(syntax/loc stx (beginner-app rator rand ...)))
|
||||||
;; Something undefined; let beginner-top take care of it:
|
|
||||||
(syntax/loc stx (#%app rator rand ...))))]))
|
|
||||||
|
|
||||||
|
;; Something undefined; let beginner-top take care of it:
|
||||||
|
(with-syntax ([new-rator (syntax-property #'rator 'was-in-app-position #t)])
|
||||||
|
(syntax/loc stx (#%app new-rator rand ...)))
|
||||||
|
))]))
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; top-level variables (beginner)
|
;; top-level variables (beginner)
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1218,29 +1208,42 @@
|
||||||
(define (beginner-top/proc stx)
|
(define (beginner-top/proc stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ . id)
|
[(_ . id)
|
||||||
;; If we're in a module, we'll need to check that the name
|
;; If we're in a module, we'll need to check that the name
|
||||||
;; is bound....
|
;; is bound....
|
||||||
(if (and (not (identifier-binding #'id))
|
(if (and (not (identifier-binding #'id))
|
||||||
(syntax-source-module #'id))
|
(syntax-source-module #'id))
|
||||||
;; ... but it might be defined later in the module, so
|
;; ... but it might be defined later in the module, so
|
||||||
;; delay the check.
|
;; delay the check.
|
||||||
(stepper-ignore-checker
|
(stepper-ignore-checker
|
||||||
(syntax/loc stx (#%app values (beginner-top-continue id))))
|
(syntax/loc stx (#%app values (beginner-top-continue id))))
|
||||||
(syntax/loc stx (#%top . id)))]))
|
(with-syntax ([rewriter
|
||||||
|
(if (syntax-property #'id 'was-in-app-position)
|
||||||
|
'rewrite-lookup-error-message/rator
|
||||||
|
'rewrite-lookup-error-message/rand)])
|
||||||
|
(syntax/loc stx
|
||||||
|
(with-handlers ([exn:fail:contract:variable?
|
||||||
|
(compose raise rewriter)])
|
||||||
|
(#%top . id)))))]))
|
||||||
|
|
||||||
(define (beginner-top-continue/proc stx)
|
(define (beginner-top-continue/proc stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ id)
|
[(_ id)
|
||||||
;; If there's still no binding, it's an "unknown name" error.
|
;; If there's still no binding, it's an "unknown name" error.
|
||||||
(if (not (identifier-binding #'id))
|
(if (not (identifier-binding #'id))
|
||||||
(teach-syntax-error
|
(if (syntax-property #'id 'was-in-app-position)
|
||||||
'unknown
|
(teach-syntax-error
|
||||||
#'id
|
'unknown
|
||||||
#f
|
#'id
|
||||||
"name is not defined, not a parameter, and not a primitive name")
|
#f
|
||||||
;; Don't use #%top here; id might have become bound to something
|
"this function is not defined")
|
||||||
;; that isn't a value.
|
(teach-syntax-error
|
||||||
#'id)]))
|
'unknown
|
||||||
|
#'id
|
||||||
|
#f
|
||||||
|
"this variable is not defined"))
|
||||||
|
;; Don't use #%top here; id might have become bound to something
|
||||||
|
;; that isn't a value.
|
||||||
|
#'id)]))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; cond
|
;; cond
|
||||||
|
@ -1256,7 +1259,7 @@
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a question--answer clause after `cond', but nothing's there")]
|
"expected a clause after cond, but nothing's there")]
|
||||||
[(_ clause ...)
|
[(_ clause ...)
|
||||||
(let* ([clauses (syntax->list (syntax (clause ...)))]
|
(let* ([clauses (syntax->list (syntax (clause ...)))]
|
||||||
[check-preceding-exprs
|
[check-preceding-exprs
|
||||||
|
@ -1284,8 +1287,8 @@
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"found an `else' clause that isn't the last clause ~
|
"found an else clause that isn't the last clause ~
|
||||||
in its `cond' expression"))
|
in its cond expression"))
|
||||||
(with-syntax ([new-test (stepper-syntax-property (syntax #t) 'stepper-else #t)])
|
(with-syntax ([new-test (stepper-syntax-property (syntax #t) 'stepper-else #t)])
|
||||||
(syntax/loc clause (new-test answer))))]
|
(syntax/loc clause (new-test answer))))]
|
||||||
[(question answer)
|
[(question answer)
|
||||||
|
@ -1297,14 +1300,14 @@
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"expected a question--answer clause, but found an empty clause")]
|
"expected a clause with a question and an answer, but found an empty part")]
|
||||||
[(question?)
|
[(question?)
|
||||||
(check-preceding-exprs clause)
|
(check-preceding-exprs clause)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"expected a clause with a question and answer, but found a clause with only one part")]
|
"expected a clause with a question and an answer, but found a clause with only one part")]
|
||||||
[(question? answer? ...)
|
[(question? answer? ...)
|
||||||
(check-preceding-exprs clause)
|
(check-preceding-exprs clause)
|
||||||
(let ([parts (syntax->list clause)])
|
(let ([parts (syntax->list clause)])
|
||||||
|
@ -1320,14 +1323,14 @@
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
parts
|
parts
|
||||||
"expected a clause with one question and one answer, but found a clause with ~a parts"
|
"expected a clause with a question and an answer, but found a clause with ~a parts"
|
||||||
(length parts)))]
|
(length parts)))]
|
||||||
[_else
|
[_else
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'cond
|
'cond
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"expected a question--answer clause, but found ~a"
|
"expected a clause with a question and an answer, but found ~a"
|
||||||
(something-else clause))]))
|
(something-else clause))]))
|
||||||
clauses)])
|
clauses)])
|
||||||
;; Add `else' clause for error (always):
|
;; Add `else' clause for error (always):
|
||||||
|
@ -1347,7 +1350,7 @@
|
||||||
'else
|
'else
|
||||||
expr
|
expr
|
||||||
#f
|
#f
|
||||||
"not allowed here, because this is not an immediate question in a `cond' clause"))
|
"not allowed here, because this is not a question in a clause"))
|
||||||
(syntax-case stx (set! x)
|
(syntax-case stx (set! x)
|
||||||
[(set! e expr) (bad #'e)]
|
[(set! e expr) (bad #'e)]
|
||||||
[(e . expr) (bad #'e)]
|
[(e . expr) (bad #'e)]
|
||||||
|
@ -1374,7 +1377,7 @@
|
||||||
'if
|
'if
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected one question expression and two answer expressions, but found ~a expression~a"
|
"expected a question and two answers, but found ~a part~a"
|
||||||
(if (zero? n) "no" n)
|
(if (zero? n) "no" n)
|
||||||
(if (= n 1) "" "s")))]
|
(if (= n 1) "" "s")))]
|
||||||
[_else (bad-use-error 'if stx)]))))
|
[_else (bad-use-error 'if stx)]))))
|
||||||
|
@ -1402,7 +1405,7 @@
|
||||||
where
|
where
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected at least two expressions after `~a', but found ~a"
|
"expected at least two expressions after ~a, but found ~a"
|
||||||
where
|
where
|
||||||
(if (zero? n) "no expressions" "only one expression")))
|
(if (zero? n) "no expressions" "only one expression")))
|
||||||
(let loop ([clauses-consumed 0]
|
(let loop ([clauses-consumed 0]
|
||||||
|
@ -1441,7 +1444,7 @@
|
||||||
'quote
|
'quote
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a name after a ', found ~a"
|
"expected the name of the symbol after the quote, found ~a"
|
||||||
(something-else sym)))
|
(something-else sym)))
|
||||||
(syntax/loc stx (quote expr)))]
|
(syntax/loc stx (quote expr)))]
|
||||||
[_else (bad-use-error 'quote stx)]))
|
[_else (bad-use-error 'quote stx)]))
|
||||||
|
@ -1640,7 +1643,7 @@
|
||||||
'local
|
'local
|
||||||
stx
|
stx
|
||||||
orig
|
orig
|
||||||
"expected only definitions within the definition sequence, but found ~a"
|
"expected a definition, but found ~a"
|
||||||
(something-else orig))]))
|
(something-else orig))]))
|
||||||
l origs)))]
|
l origs)))]
|
||||||
[val-defns
|
[val-defns
|
||||||
|
@ -1679,7 +1682,7 @@
|
||||||
'local
|
'local
|
||||||
stx
|
stx
|
||||||
dup
|
dup
|
||||||
"found a name that was defined locally more than once: ~a"
|
"~a was defined locally more than once"
|
||||||
(syntax-e dup)))
|
(syntax-e dup)))
|
||||||
(let ([exprs (syntax->list (syntax exprs))])
|
(let ([exprs (syntax->list (syntax exprs))])
|
||||||
(check-single-expression 'local
|
(check-single-expression 'local
|
||||||
|
@ -1740,14 +1743,14 @@
|
||||||
'local
|
'local
|
||||||
stx
|
stx
|
||||||
(syntax def-non-seq)
|
(syntax def-non-seq)
|
||||||
"expected a parenthesized definition sequence after `local', but found ~a"
|
"expected at least one definition (in square brackets) after local, but found ~a"
|
||||||
(something-else (syntax def-non-seq)))]
|
(something-else (syntax def-non-seq)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'local
|
'local
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a parenthesized definition sequence after `local', but nothing's there")]
|
"expected at least one definition (in square brackets) after local, but nothing's there")]
|
||||||
[_else (bad-use-error 'local stx)]))))
|
[_else (bad-use-error 'local stx)]))))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1885,12 +1888,12 @@
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
name
|
name
|
||||||
"expected a name for a local binding, but found ~a"
|
"expected a variable for the binding, but found ~a"
|
||||||
(something-else/kw name))))]
|
(something-else/kw name))))]
|
||||||
[(name . exprs)
|
[(name . exprs)
|
||||||
(identifier/non-kw? (syntax name))
|
(identifier/non-kw? (syntax name))
|
||||||
(check-single-expression who
|
(check-single-expression who
|
||||||
(format "after the name `~a'"
|
(format "after the name ~a"
|
||||||
(syntax-e (syntax name)))
|
(syntax-e (syntax name)))
|
||||||
binding
|
binding
|
||||||
(syntax->list (syntax exprs))
|
(syntax->list (syntax exprs))
|
||||||
|
@ -1900,16 +1903,14 @@
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
(syntax something)
|
(syntax something)
|
||||||
"expected a name after the parenthesis for a ~a local definition, but found ~a"
|
"expected a variable after the square bracket, but found ~a"
|
||||||
who
|
|
||||||
(something-else/kw (syntax something)))]
|
(something-else/kw (syntax something)))]
|
||||||
[_else
|
[_else
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
binding
|
binding
|
||||||
"expected a parenthesized name and expression for a ~a local definition, but found ~a"
|
"expected a binding with a variable and an expression, but found ~a"
|
||||||
who
|
|
||||||
(something-else binding))]))
|
(something-else binding))]))
|
||||||
bindings)
|
bindings)
|
||||||
(unless (eq? who 'let*)
|
(unless (eq? who 'let*)
|
||||||
|
@ -1922,7 +1923,7 @@
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
dup
|
dup
|
||||||
"found a name that was defined locally more than once: ~a"
|
"~a was defined locally more than once"
|
||||||
(syntax-e dup)))))
|
(syntax-e dup)))))
|
||||||
(let ([exprs (syntax->list (syntax exprs))])
|
(let ([exprs (syntax->list (syntax exprs))])
|
||||||
(check-single-expression who
|
(check-single-expression who
|
||||||
|
@ -1935,7 +1936,7 @@
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
(syntax binding-non-seq)
|
(syntax binding-non-seq)
|
||||||
"expected a parenthesized sequence of local name definitions after `~a', but found ~a"
|
"expected at least one binding (in parentheses) after ~a, but found ~a"
|
||||||
who
|
who
|
||||||
(something-else (syntax binding-non-seq)))]
|
(something-else (syntax binding-non-seq)))]
|
||||||
[(_)
|
[(_)
|
||||||
|
@ -1943,7 +1944,7 @@
|
||||||
who
|
who
|
||||||
orig-stx
|
orig-stx
|
||||||
#f
|
#f
|
||||||
"expected a sequence of local name definitions after `~a', but nothing's there"
|
"expected at least one binding (in parentheses) after ~a, but nothing's there"
|
||||||
who)]
|
who)]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error who stx)]))
|
(bad-use-error who stx)]))
|
||||||
|
@ -1992,8 +1993,7 @@
|
||||||
'recur
|
'recur
|
||||||
stx
|
stx
|
||||||
(syntax empty-seq)
|
(syntax empty-seq)
|
||||||
"expected a non-empty sequence of bindings after the function name, ~
|
"expected at least one binding (in parentheses) after the function name, but found none")]
|
||||||
but found an empty sequence")]
|
|
||||||
[(_form fname . rest)
|
[(_form fname . rest)
|
||||||
(identifier/non-kw? (syntax fname))
|
(identifier/non-kw? (syntax fname))
|
||||||
(bad-let-form 'recur (syntax (_form . rest)) stx)]
|
(bad-let-form 'recur (syntax (_form . rest)) stx)]
|
||||||
|
@ -2002,14 +2002,14 @@
|
||||||
'recur
|
'recur
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a function name after `recur', but found ~a"
|
"expected a function name after recur, but found ~a"
|
||||||
(something-else/kw (syntax fname)))]
|
(something-else/kw (syntax fname)))]
|
||||||
[(_form)
|
[(_form)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'recur
|
'recur
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a function name after `recur', but nothing's there")]
|
"expected a function name after recur, but nothing's there")]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error 'recur stx)])))))])
|
(bad-use-error 'recur stx)])))))])
|
||||||
(values (mk #f) (mk #t))))
|
(values (mk #f) (mk #t))))
|
||||||
|
@ -2032,7 +2032,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
arg
|
arg
|
||||||
"expected a name for a function argument, but found ~a"
|
"expected a variable, but found ~a"
|
||||||
(something-else/kw arg))))
|
(something-else/kw arg))))
|
||||||
args)
|
args)
|
||||||
(when (null? args)
|
(when (null? args)
|
||||||
|
@ -2040,14 +2040,14 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
(syntax arg-seq)
|
(syntax arg-seq)
|
||||||
"expected at least one argument name in the sequence after `lambda', but found none"))
|
"expected at least one variable after lambda, but found none"))
|
||||||
(let ([dup (check-duplicate-identifier args)])
|
(let ([dup (check-duplicate-identifier args)])
|
||||||
(when dup
|
(when dup
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
dup
|
dup
|
||||||
"found an argument name that is used more than once: ~a"
|
"found a variable that is used more than once: ~a"
|
||||||
(syntax-e dup))))
|
(syntax-e dup))))
|
||||||
(check-single-expression 'lambda
|
(check-single-expression 'lambda
|
||||||
"within lambda"
|
"within lambda"
|
||||||
|
@ -2061,14 +2061,14 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
(syntax args)
|
(syntax args)
|
||||||
"expected a sequence of function arguments after `lambda', but found ~a"
|
"expected at least one variable (in parentheses) after lambda, but found ~a"
|
||||||
(something-else (syntax args)))]
|
(something-else (syntax args)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a sequence of argument names after `lambda', but nothing's there")]
|
"expected at least one variable (in parentheses) after lambda, but nothing's there")]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error 'lambda stx)]))))
|
(bad-use-error 'lambda stx)]))))
|
||||||
|
|
||||||
|
@ -2082,7 +2082,7 @@
|
||||||
[(_ expr ...)
|
[(_ expr ...)
|
||||||
(begin
|
(begin
|
||||||
(check-single-expression 'quote
|
(check-single-expression 'quote
|
||||||
"after the `quote' keyword"
|
"after the quote keyword"
|
||||||
stx
|
stx
|
||||||
(syntax->list (syntax (expr ...)))
|
(syntax->list (syntax (expr ...)))
|
||||||
;; Don't expand expr!
|
;; Don't expand expr!
|
||||||
|
@ -2106,7 +2106,7 @@
|
||||||
'quasiquote
|
'quasiquote
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"misuse of `quasiquote'")]
|
"misuse of quasiquote")]
|
||||||
[_else (bad-use-error 'quasiquote stx)])]
|
[_else (bad-use-error 'quasiquote stx)])]
|
||||||
[depth 0])
|
[depth 0])
|
||||||
(syntax-case stx (intermediate-unquote intermediate-unquote-splicing intermediate-quasiquote)
|
(syntax-case stx (intermediate-unquote intermediate-unquote-splicing intermediate-quasiquote)
|
||||||
|
@ -2121,7 +2121,7 @@
|
||||||
'quasiquote
|
'quasiquote
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"misuse of `unquote' within a quasiquoting backquote")]
|
"misuse of unquote within a quasiquoting backquote")]
|
||||||
[((intermediate-unquote-splicing x) . rest)
|
[((intermediate-unquote-splicing x) . rest)
|
||||||
(if (zero? depth)
|
(if (zero? depth)
|
||||||
(with-syntax ([rest (loop (syntax rest) depth)])
|
(with-syntax ([rest (loop (syntax rest) depth)])
|
||||||
|
@ -2137,7 +2137,7 @@
|
||||||
'quasiquote
|
'quasiquote
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"misuse of ,@ or `unquote-splicing' within a quasiquoting backquote")]
|
"misuse of ,@ or unquote-splicing within a quasiquoting backquote")]
|
||||||
[(intermediate-quasiquote x)
|
[(intermediate-quasiquote x)
|
||||||
(with-syntax ([x (loop (syntax x) (add1 depth))]
|
(with-syntax ([x (loop (syntax x) (add1 depth))]
|
||||||
[qq (stx-car stx)])
|
[qq (stx-car stx)])
|
||||||
|
@ -2156,14 +2156,14 @@
|
||||||
'unquote
|
'unquote
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"misuse of a comma or `unquote', not under a quasiquoting backquote"))
|
"misuse of a comma or unquote, not under a quasiquoting backquote"))
|
||||||
|
|
||||||
(define (intermediate-unquote-splicing/proc stx)
|
(define (intermediate-unquote-splicing/proc stx)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'unquote-splicing
|
'unquote-splicing
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"misuse of ,@ or `unquote-splicing', not under a quasiquoting backquote"))
|
"misuse of ,@ or unquote-splicing, not under a quasiquoting backquote"))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; time
|
;; time
|
||||||
|
@ -2176,7 +2176,7 @@
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ . exprs)
|
[(_ . exprs)
|
||||||
(check-single-expression 'time
|
(check-single-expression 'time
|
||||||
"after `time'"
|
"after time"
|
||||||
stx
|
stx
|
||||||
(syntax->list (syntax exprs))
|
(syntax->list (syntax exprs))
|
||||||
null)
|
null)
|
||||||
|
@ -2249,7 +2249,7 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
name
|
name
|
||||||
"expected a name for an argument, but found ~a"
|
"expected a variable, but found ~a"
|
||||||
(something-else/kw name))))
|
(something-else/kw name))))
|
||||||
names)
|
names)
|
||||||
(let ([dup (check-duplicate-identifier names)])
|
(let ([dup (check-duplicate-identifier names)])
|
||||||
|
@ -2258,10 +2258,10 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
dup
|
dup
|
||||||
"found an argument name that is used more than once: ~a"
|
"found a variable that is used more than once: ~a"
|
||||||
(syntax-e dup))))
|
(syntax-e dup))))
|
||||||
(check-single-expression 'lambda
|
(check-single-expression 'lambda
|
||||||
"after the argument-name sequence"
|
"after the variables"
|
||||||
stx
|
stx
|
||||||
(syntax->list (syntax exprs))
|
(syntax->list (syntax exprs))
|
||||||
names)
|
names)
|
||||||
|
@ -2271,14 +2271,14 @@
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
(syntax arg-non-seq)
|
(syntax arg-non-seq)
|
||||||
"expected a parenthesized sequence of argument names after `lambda', but found ~a"
|
"expected at least one variable (in parentheses) after lambda, but found ~a"
|
||||||
(something-else (syntax arg-non-seq)))]
|
(something-else (syntax arg-non-seq)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'lambda
|
'lambda
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a sequence of argument names after `lambda', but nothing's there")]
|
"expected at least one variable (in parentheses) after lambda, but nothing's there")]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error 'lambda stx)]))))
|
(bad-use-error 'lambda stx)]))))
|
||||||
|
|
||||||
|
@ -2292,14 +2292,14 @@
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ rator rand ...)
|
[(_ rator rand ...)
|
||||||
(syntax/loc stx (#%app rator rand ...))]
|
(with-syntax ([new-rator (syntax-property #'rator 'was-in-app-position #t)])
|
||||||
|
(syntax/loc stx (#%app new-rator rand ...)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'|function call|
|
'|function call|
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a defined function name or a primitive operation name after an ~
|
"expected a function after the open parenthesis, but nothing's there")]
|
||||||
open parenthesis, but nothing's there")]
|
|
||||||
[_else (bad-use-error '#%app stx)]))))
|
[_else (bad-use-error '#%app stx)]))))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -2333,14 +2333,14 @@
|
||||||
'set!
|
'set!
|
||||||
stx
|
stx
|
||||||
(syntax id)
|
(syntax id)
|
||||||
"expected a defined name after `set!', but found a keyword"))))))
|
"expected a variable after set!, but found a ~a" (syntax-e #'id)))))))
|
||||||
;; Now try lexical:
|
;; Now try lexical:
|
||||||
(when (eq? 'lexical (identifier-binding (syntax id)))
|
(when (eq? 'lexical (identifier-binding (syntax id)))
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'set!
|
'set!
|
||||||
stx
|
stx
|
||||||
(syntax id)
|
(syntax id)
|
||||||
"expected a defined name after `set!', but found a function argument name")))
|
"expected a mutable variable after set!, but found a variable that cannot be modified")))
|
||||||
;; If we're in a module, we'd like to check here whether
|
;; If we're in a module, we'd like to check here whether
|
||||||
;; the identier is bound, but we need to delay that check
|
;; the identier is bound, but we need to delay that check
|
||||||
;; in case the id is defined later in the module. So only
|
;; in case the id is defined later in the module. So only
|
||||||
|
@ -2354,7 +2354,7 @@
|
||||||
'unknown
|
'unknown
|
||||||
#'id
|
#'id
|
||||||
#f
|
#f
|
||||||
"name is not defined")]
|
"this variable is not defined")]
|
||||||
[(and (list? binding)
|
[(and (list? binding)
|
||||||
(or (not (module-path-index? (car binding)))
|
(or (not (module-path-index? (car binding)))
|
||||||
(let-values ([(path rel) (module-path-index-split (car binding))])
|
(let-values ([(path rel) (module-path-index-split (car binding))])
|
||||||
|
@ -2363,7 +2363,7 @@
|
||||||
'unknown
|
'unknown
|
||||||
#'id
|
#'id
|
||||||
#f
|
#f
|
||||||
"cannot set a primitive name")])))
|
"expected a mutable variable after set!, but found a variable that cannot be modified")])))
|
||||||
;; Check the RHS
|
;; Check the RHS
|
||||||
(check-single-expression 'set!
|
(check-single-expression 'set!
|
||||||
"for the new value"
|
"for the new value"
|
||||||
|
@ -2382,14 +2382,14 @@
|
||||||
'set!
|
'set!
|
||||||
stx
|
stx
|
||||||
(syntax id)
|
(syntax id)
|
||||||
"expected a defined name after `set!', but found ~a"
|
"expected a variable after set!, but found ~a"
|
||||||
(something-else (syntax id)))]
|
(something-else (syntax id)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'set!
|
'set!
|
||||||
stx
|
stx
|
||||||
(syntax id)
|
(syntax id)
|
||||||
"expected a defined name after `set!', but nothing's there")]
|
"expected a variable after set!, but nothing's there")]
|
||||||
[_else (bad-use-error 'set! stx)])))))])
|
[_else (bad-use-error 'set! stx)])))))])
|
||||||
(values (proc #f)
|
(values (proc #f)
|
||||||
(proc #t))))
|
(proc #t))))
|
||||||
|
@ -2409,7 +2409,7 @@
|
||||||
[(_ q expr ...)
|
[(_ q expr ...)
|
||||||
(let ([exprs (syntax->list (syntax (expr ...)))])
|
(let ([exprs (syntax->list (syntax (expr ...)))])
|
||||||
(check-single-expression who
|
(check-single-expression who
|
||||||
(format "for the answer in `~a'"
|
(format "for the answer in ~a"
|
||||||
who)
|
who)
|
||||||
stx
|
stx
|
||||||
exprs
|
exprs
|
||||||
|
@ -2422,7 +2422,7 @@
|
||||||
who
|
who
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a question expression after `~a', but nothing's there"
|
"expected a question after ~a, but nothing's there"
|
||||||
who)]
|
who)]
|
||||||
[_else
|
[_else
|
||||||
(bad-use-error who stx)])))))])
|
(bad-use-error who stx)])))))])
|
||||||
|
@ -2454,7 +2454,7 @@
|
||||||
'let
|
'let
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"bad syntax for named `let'")]
|
"bad syntax for named let")]
|
||||||
[(_ . rest)
|
[(_ . rest)
|
||||||
(syntax/loc stx (intermediate-let . rest))]
|
(syntax/loc stx (intermediate-let . rest))]
|
||||||
[_else
|
[_else
|
||||||
|
@ -2472,7 +2472,7 @@
|
||||||
'begin
|
'begin
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a sequence of expressions after `begin', but nothing's there")]
|
"expected at least one expression after begin, but nothing's there")]
|
||||||
[(_ e ...)
|
[(_ e ...)
|
||||||
(stepper-syntax-property (syntax/loc stx (let () e ...))
|
(stepper-syntax-property (syntax/loc stx (let () e ...))
|
||||||
'stepper-hint
|
'stepper-hint
|
||||||
|
@ -2491,7 +2491,7 @@
|
||||||
'begin
|
'begin
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a sequence of expressions after `begin0', but nothing's there")]
|
"expected at least one expression after begin0, but nothing's there")]
|
||||||
[(_ e ...)
|
[(_ e ...)
|
||||||
(syntax/loc stx (begin0 e ...))]
|
(syntax/loc stx (begin0 e ...))]
|
||||||
[_else
|
[_else
|
||||||
|
@ -2511,13 +2511,13 @@
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected an expression after `case', but nothing's there")]
|
"expected an expression after case, but nothing's there")]
|
||||||
[(_ expr)
|
[(_ expr)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
#f
|
#f
|
||||||
"expected a choices--answer clause after the expression following `case', but nothing's there")]
|
"expected a clause with choices and an answer after the expression, but nothing's there")]
|
||||||
[(_ v-expr clause ...)
|
[(_ v-expr clause ...)
|
||||||
(let ([clauses (syntax->list (syntax (clause ...)))])
|
(let ([clauses (syntax->list (syntax (clause ...)))])
|
||||||
(for-each
|
(for-each
|
||||||
|
@ -2530,8 +2530,8 @@
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"found an `else' clause that isn't the last clause ~
|
"found an else clause that isn't the last clause ~
|
||||||
in its `case' expression"))
|
in its case expression"))
|
||||||
(let ([answers (syntax->list (syntax (answer ...)))])
|
(let ([answers (syntax->list (syntax (answer ...)))])
|
||||||
(check-single-expression 'case
|
(check-single-expression 'case
|
||||||
"for the answer in a case clause"
|
"for the answer in a case clause"
|
||||||
|
@ -2552,23 +2552,23 @@
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
e
|
e
|
||||||
"expected a name (for a symbol) or a number as a choice value, but found ~a"
|
"expected a symbol (without its quote) or a number as a choice, but found ~a"
|
||||||
(something-else e)))))
|
(something-else e)))))
|
||||||
elems))]
|
elems))]
|
||||||
[_else (teach-syntax-error
|
[_else (teach-syntax-error
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
choices
|
choices
|
||||||
"expected a parenthesized sequence of choice values, but found ~a"
|
"expected at least one choice (in parentheses), but found ~a"
|
||||||
(something-else choices))])
|
(something-else choices))])
|
||||||
(when (stx-null? choices)
|
(when (stx-null? choices)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
choices
|
choices
|
||||||
"expected at least once choice in a parenthesized sequence of choice values, but nothing's there"))
|
"expected at least one choice (in parentheses), but nothing's there"))
|
||||||
(check-single-expression 'case
|
(check-single-expression 'case
|
||||||
"for the answer in a `case' clause"
|
"for the answer in a case clause"
|
||||||
clause
|
clause
|
||||||
answers
|
answers
|
||||||
null))]
|
null))]
|
||||||
|
@ -2577,13 +2577,13 @@
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"expected a choices--answer clause, but found an empty clause")]
|
"expected a clause with at least one choice (in parentheses) and an answer, but found an empty part")]
|
||||||
[_else
|
[_else
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'case
|
'case
|
||||||
stx
|
stx
|
||||||
clause
|
clause
|
||||||
"expected a choices--answer clause, but found ~a"
|
"expected a clause with at least one choice (in parentheses) and an answer, but found ~a"
|
||||||
(something-else clause))]))
|
(something-else clause))]))
|
||||||
clauses)
|
clauses)
|
||||||
;; Add `else' clause for error, if necessary:
|
;; Add `else' clause for error, if necessary:
|
||||||
|
@ -2743,7 +2743,7 @@
|
||||||
[(_ expr ...)
|
[(_ expr ...)
|
||||||
(begin
|
(begin
|
||||||
(check-single-expression 'delay
|
(check-single-expression 'delay
|
||||||
"after the `delay' keyword"
|
"after the delay keyword"
|
||||||
stx
|
stx
|
||||||
(syntax->list (syntax (expr ...)))
|
(syntax->list (syntax (expr ...)))
|
||||||
null)
|
null)
|
||||||
|
@ -2793,20 +2793,20 @@
|
||||||
'shared
|
'shared
|
||||||
stx
|
stx
|
||||||
(syntax a)
|
(syntax a)
|
||||||
"expected a name for the binding, but found ~a"
|
"expected a variable for the binding, but found ~a"
|
||||||
(something-else/kw (syntax a)))]
|
(something-else/kw (syntax a)))]
|
||||||
[()
|
[()
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'shared
|
'shared
|
||||||
stx
|
stx
|
||||||
(syntax a)
|
(syntax a)
|
||||||
"expected a name for a binding, but nothing's there")]
|
"expected a variable for a binding, but nothing's there")]
|
||||||
[_else
|
[_else
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'shared
|
'shared
|
||||||
stx
|
stx
|
||||||
binding
|
binding
|
||||||
"expected a name--expression pair for a binding, but found ~a"
|
"expected a binding with a variable and an expression, but found ~a"
|
||||||
(something-else binding))]))
|
(something-else binding))]))
|
||||||
bindings)
|
bindings)
|
||||||
(check-single-expression 'shared
|
(check-single-expression 'shared
|
||||||
|
@ -2819,14 +2819,14 @@
|
||||||
'shared
|
'shared
|
||||||
stx
|
stx
|
||||||
(syntax bad-bind)
|
(syntax bad-bind)
|
||||||
"expected a sequence of bindings after `shared', but found ~a"
|
"expected at least one binding (in parentheses) after shared, but found ~a"
|
||||||
(something-else (syntax bad-bind)))]
|
(something-else (syntax bad-bind)))]
|
||||||
[(_)
|
[(_)
|
||||||
(teach-syntax-error
|
(teach-syntax-error
|
||||||
'shared
|
'shared
|
||||||
stx
|
stx
|
||||||
(syntax bad-bind)
|
(syntax bad-bind)
|
||||||
"expected a sequence of bindings after `shared', but nothing's there")]
|
"expected at least one binding (in parentheses) after shared, but nothing's there")]
|
||||||
[_else (bad-use-error 'shared stx)])
|
[_else (bad-use-error 'shared stx)])
|
||||||
|
|
||||||
;; The main implementation
|
;; The main implementation
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
'stepper-skipto
|
'stepper-skipto
|
||||||
(append skipto/cdr
|
(append skipto/cdr
|
||||||
skipto/third))])))))
|
skipto/third))])))))
|
||||||
|
#;
|
||||||
(define (appropriate-use what)
|
(define (appropriate-use what)
|
||||||
(case what
|
(case what
|
||||||
[(constructor)
|
[(constructor)
|
||||||
|
@ -63,9 +63,7 @@
|
||||||
(identifier? #'id)
|
(identifier? #'id)
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(format "this is a ~a, so it must be ~a (which requires using a parenthesis before the name)"
|
(format "found a use that does not follow an open parenthesis")
|
||||||
what
|
|
||||||
(appropriate-use what))
|
|
||||||
stx
|
stx
|
||||||
#f)]
|
#f)]
|
||||||
[(id . rest)
|
[(id . rest)
|
||||||
|
@ -73,8 +71,7 @@
|
||||||
(unless (= l arity)
|
(unless (= l arity)
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
#f
|
#f
|
||||||
(format "this ~a expects ~a argument~a, here it is provided ~a argument~a"
|
(format "this function expects ~a argument~a, here it is provided ~a argument~a"
|
||||||
what
|
|
||||||
arity (if (= 1 arity) "" "s")
|
arity (if (= 1 arity) "" "s")
|
||||||
l (if (= 1 l) "" "s"))
|
l (if (= 1 l) "" "s"))
|
||||||
stx
|
stx
|
||||||
|
|
|
@ -67,8 +67,8 @@ namespace.
|
||||||
(unless (ok? b)
|
(unless (ok? b)
|
||||||
(raise
|
(raise
|
||||||
(make-exn:fail:contract
|
(make-exn:fail:contract
|
||||||
(format "~a: second argument must be of type <~a>, given ~e and ~e"
|
(format "~a: second argument must be ~a ~a, but received ~e and ~e"
|
||||||
prim-name type
|
prim-name (a-or-an type) type
|
||||||
a b)
|
a b)
|
||||||
(current-continuation-marks))))))
|
(current-continuation-marks))))))
|
||||||
|
|
||||||
|
@ -88,8 +88,8 @@ namespace.
|
||||||
(unless (ok? last)
|
(unless (ok? last)
|
||||||
(raise
|
(raise
|
||||||
(make-exn:fail:contract
|
(make-exn:fail:contract
|
||||||
(format "~a: last argument must be of type <~a>, given ~e; other args:~a"
|
(format "~a: last argument must be ~a ~a, but received ~e; the other arguments were: ~a"
|
||||||
prim-name type
|
prim-name (a-or-an type) type
|
||||||
last
|
last
|
||||||
;; all-but-last:
|
;; all-but-last:
|
||||||
(build-arg-list
|
(build-arg-list
|
||||||
|
@ -111,7 +111,7 @@ namespace.
|
||||||
(lambda (v which type)
|
(lambda (v which type)
|
||||||
(raise
|
(raise
|
||||||
(make-exn:fail:contract
|
(make-exn:fail:contract
|
||||||
(format "~a: ~a argument must be of type <~a>, given ~e, ~e, and ~e"
|
(format "~a: ~a argument must be of a ~a, given ~e, ~e, and ~e"
|
||||||
prim-name which type
|
prim-name which type
|
||||||
a b c)
|
a b c)
|
||||||
(current-continuation-marks))))])
|
(current-continuation-marks))))])
|
||||||
|
@ -154,7 +154,7 @@ namespace.
|
||||||
(unless (number? a)
|
(unless (number? a)
|
||||||
(raise
|
(raise
|
||||||
(make-exn:fail:contract
|
(make-exn:fail:contract
|
||||||
(format "sqr: expected number; given ~e" a)
|
(format "sqr: expected a number; given ~e" a)
|
||||||
(current-continuation-marks))))
|
(current-continuation-marks))))
|
||||||
(sqr a)))
|
(sqr a)))
|
||||||
|
|
||||||
|
@ -335,30 +335,31 @@ namespace.
|
||||||
(define-teach intermediate foldr
|
(define-teach intermediate foldr
|
||||||
(lambda (f e l)
|
(lambda (f e l)
|
||||||
(unless (and (procedure? f) (procedure-arity-includes? f 2))
|
(unless (and (procedure? f) (procedure-arity-includes? f 2))
|
||||||
(hocheck 'foldr "first argument must be a <procedure> that accepts two arguments, given ~e" f))
|
(hocheck 'foldr "first argument must be a function that expects two arguments, given ~e" f))
|
||||||
(unless (beginner-list? l)
|
(unless (beginner-list? l)
|
||||||
(hocheck 'foldr "third argument must be of type <list>, given ~e" l))
|
(hocheck 'foldr "third argument must be a list, given ~e" l))
|
||||||
(foldr f e l)))
|
(foldr f e l)))
|
||||||
|
|
||||||
(define-teach intermediate foldl
|
(define-teach intermediate foldl
|
||||||
(lambda (f e l)
|
(lambda (f e l)
|
||||||
(unless (and (procedure? f) (procedure-arity-includes? f 2))
|
(unless (and (procedure? f) (procedure-arity-includes? f 2))
|
||||||
(hocheck 'foldl "first argument must be a <procedure> that accepts two arguments, given ~e" f))
|
(hocheck 'foldl "first argument must be a function that expects two arguments, given ~e" f))
|
||||||
(unless (beginner-list? l)
|
(unless (beginner-list? l)
|
||||||
(hocheck 'foldl "third argument must be of type <list>, given ~e" l))
|
(hocheck 'foldl "third argument must be a list, given ~e" l))
|
||||||
(foldl f e l)))
|
(foldl f e l)))
|
||||||
|
|
||||||
(define-teach intermediate build-string
|
(define-teach intermediate build-string
|
||||||
(lambda (n f)
|
(lambda (n f)
|
||||||
(unless (and (procedure? f) (procedure-arity-includes? f 1))
|
(unless (and (procedure? f) (procedure-arity-includes? f 1))
|
||||||
(hocheck 'build-string "second argument must be a <procedure> that accepts one argument, given ~e" f))
|
(hocheck 'build-string "second argument must be a function that accepts one argument, given ~e" f))
|
||||||
(unless (and (number? n) (integer? n) (>= n 0))
|
(unless (and (number? n) (integer? n) (>= n 0))
|
||||||
(hocheck 'build-string "first argument must be of type <natural number>, given ~e" n))
|
(hocheck 'build-string "first argument must be a natural number, given ~e" n))
|
||||||
(build-string n (lambda (i)
|
(build-string n (lambda (i)
|
||||||
(define r (f i))
|
(define r (f i))
|
||||||
(unless (char? r)
|
(unless (char? r)
|
||||||
(hocheck 'build-string
|
(hocheck 'build-string
|
||||||
"second argument must be a <procedure> that produces a <char>, given ~e, which produced ~e for ~e" f r i))
|
"the second argument must be a function that produces a character, ~
|
||||||
|
given ~e, which produced ~e for ~e" f r i))
|
||||||
r))))
|
r))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -447,24 +448,24 @@ namespace.
|
||||||
;; auxiliary stuff, ignore
|
;; auxiliary stuff, ignore
|
||||||
|
|
||||||
(define 1-LET "1-letter string")
|
(define 1-LET "1-letter string")
|
||||||
(define 1-LETTER (format "<~a>" 1-LET))
|
(define 1-LETTER (format "~a" 1-LET))
|
||||||
(define 1-LETTER* (format "<list of ~as>" 1-LET))
|
(define 1-LETTER* (format "list of ~as" 1-LET))
|
||||||
(define NAT "<natural number>")
|
(define NAT "natural number")
|
||||||
|
|
||||||
;; Symbol Any -> Boolean
|
;; Symbol Any -> Boolean
|
||||||
;; is this a 1-letter string?
|
;; is this a 1-letter string?
|
||||||
(define (1-letter? tag s)
|
(define (1-letter? tag s)
|
||||||
(unless (string? s) (err tag "~a expected, not a string: ~e" 1-LETTER s))
|
(unless (string? s) (err tag "expected a ~a, but received a string: ~e" 1-LETTER s))
|
||||||
(= (string-length s) 1))
|
(= (string-length s) 1))
|
||||||
|
|
||||||
;; Symbol Any -> Boolean
|
;; Symbol Any -> Boolean
|
||||||
;; is s a list of 1-letter strings
|
;; is s a list of 1-letter strings
|
||||||
;; effect: not a list, not a list of strings
|
;; effect: not a list, not a list of strings
|
||||||
(define (1-letter*? tag s)
|
(define (1-letter*? tag s)
|
||||||
(unless (list? s) (err tag "~a expected, not a <list>: ~e" 1-LETTER* s))
|
(unless (list? s) (err tag "expected a ~a, but received a list: ~e" 1-LETTER* s))
|
||||||
(for-each
|
(for-each
|
||||||
(lambda (c)
|
(lambda (c)
|
||||||
(unless (string? c) (err tag "~a expected, not a <string>: ~e" 1-LETTER* c)))
|
(unless (string? c) (err tag "expected a ~a, but received a string: ~e" 1-LETTER* c)))
|
||||||
s)
|
s)
|
||||||
(andmap (compose (curry = 1) string-length) s))
|
(andmap (compose (curry = 1) string-length) s))
|
||||||
|
|
||||||
|
@ -474,25 +475,29 @@ namespace.
|
||||||
(apply format (string-append (symbol->string tag) ": " msg-format) args)
|
(apply format (string-append (symbol->string tag) ": " msg-format) args)
|
||||||
(current-continuation-marks))))
|
(current-continuation-marks))))
|
||||||
|
|
||||||
|
(define (a-or-an after)
|
||||||
|
(if (member (string-ref (format "~a" after) 0) '(#\a #\e #\i #\o #\u))
|
||||||
|
"an" "a"))
|
||||||
|
|
||||||
(define cerr
|
(define cerr
|
||||||
(case-lambda
|
(case-lambda
|
||||||
[(tag check-result format-msg actual)
|
[(tag check-result format-msg actual)
|
||||||
(unless check-result
|
(unless check-result
|
||||||
(err tag (string-append format-msg " expected, given ~e") actual))]
|
(err tag (string-append "expected " (a-or-an format-msg) " " format-msg ", but received ~e") actual))]
|
||||||
[(tag check-result format-msg actual snd)
|
[(tag check-result format-msg actual snd)
|
||||||
(unless check-result
|
(unless check-result
|
||||||
(err tag (string-append format-msg " for ~a argument expected, given ~e")
|
(err tag (string-append "expected " (a-or-an format-msg) " " format-msg " for the ~a argument, but received ~e")
|
||||||
snd actual))]))
|
snd actual))]))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
(define-teach beginner string-ith
|
(define-teach beginner string-ith
|
||||||
(lambda (s n)
|
(lambda (s n)
|
||||||
(define f "<exact integer in [0, length of the given string (~s))>")
|
(define f "exact integer in [0, length of the given string]")
|
||||||
(cerr 'string-ith (string? s) "<string>" s "first")
|
(cerr 'string-ith (string? s) "string" s "first")
|
||||||
(cerr 'string-ith (and (number? n) (integer? n) (>= n 0)) NAT n "second")
|
(cerr 'string-ith (and (number? n) (integer? n) (>= n 0)) NAT n "second")
|
||||||
(let ([l (string-length s)])
|
(let ([l (string-length s)])
|
||||||
(cerr 'string-ith (< n l) (format f l) n "second"))
|
(cerr 'string-ith (< n l) f n "second"))
|
||||||
(string (string-ref s n))))
|
(string (string-ref s n))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
@ -500,7 +505,7 @@ namespace.
|
||||||
(define-teach beginner replicate
|
(define-teach beginner replicate
|
||||||
(lambda (n s1)
|
(lambda (n s1)
|
||||||
(cerr 'replicate (and (number? n) (exact-integer? n) (>= n 0)) NAT n)
|
(cerr 'replicate (and (number? n) (exact-integer? n) (>= n 0)) NAT n)
|
||||||
(cerr 'replicate (string? s1) "<string>" s1)
|
(cerr 'replicate (string? s1) "string" s1)
|
||||||
(apply string-append (build-list n (lambda (i) s1)))))
|
(apply string-append (build-list n (lambda (i) s1)))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
@ -509,7 +514,7 @@ namespace.
|
||||||
(lambda (i)
|
(lambda (i)
|
||||||
(cerr 'int->string
|
(cerr 'int->string
|
||||||
(and (exact-integer? i) (or (<= 0 i 55295) (<= 57344 i 1114111)))
|
(and (exact-integer? i) (or (<= 0 i 55295) (<= 57344 i 1114111)))
|
||||||
"<exact integer in [0,55295] or [57344 1114111]>"
|
"exact integer in [0,55295] or [57344 1114111]"
|
||||||
i)
|
i)
|
||||||
(string (integer->char i))))
|
(string (integer->char i))))
|
||||||
|
|
||||||
|
@ -524,7 +529,7 @@ namespace.
|
||||||
|
|
||||||
(define-teach beginner explode
|
(define-teach beginner explode
|
||||||
(lambda (s)
|
(lambda (s)
|
||||||
(cerr 'explode (string? s) "<string>" s)
|
(cerr 'explode (string? s) "string" s)
|
||||||
(map string (string->list s))))
|
(map string (string->list s))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
@ -539,7 +544,7 @@ namespace.
|
||||||
(define-teach beginner string-numeric?
|
(define-teach beginner string-numeric?
|
||||||
;; is this: (number? (string->number s)) enough?
|
;; is this: (number? (string->number s)) enough?
|
||||||
(lambda (s1)
|
(lambda (s1)
|
||||||
(cerr 'string-numeric? (string? s1) "<string>" s1)
|
(cerr 'string-numeric? (string? s1) "string" s1)
|
||||||
(andmap char-numeric? (string->list s1))))
|
(andmap char-numeric? (string->list s1))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
@ -548,14 +553,14 @@ namespace.
|
||||||
|
|
||||||
(define-teach beginner string-alphabetic?
|
(define-teach beginner string-alphabetic?
|
||||||
(lambda (s1)
|
(lambda (s1)
|
||||||
(cerr 'string-alphabetic? (string? s1) "<string>" s1)
|
(cerr 'string-alphabetic? (string? s1) "string" s1)
|
||||||
(andmap char-alphabetic? (string->list s1))))
|
(andmap char-alphabetic? (string->list s1))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
(define-teach beginner string-whitespace?
|
(define-teach beginner string-whitespace?
|
||||||
(lambda (s)
|
(lambda (s)
|
||||||
(cerr 'string-whitespace? (string? s) "<string>" s)
|
(cerr 'string-upper-case? (string? s) "string" s)
|
||||||
(andmap char-whitespace? (string->list s))))
|
(andmap char-whitespace? (string->list s))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
@ -563,14 +568,14 @@ namespace.
|
||||||
|
|
||||||
(define-teach beginner string-upper-case?
|
(define-teach beginner string-upper-case?
|
||||||
(lambda (s)
|
(lambda (s)
|
||||||
(cerr 'string-upper-case? (string? s) "<string>" s)
|
(cerr 'string-upper-case? (string? s) "string" s)
|
||||||
(andmap char-upper-case? (string->list s))))
|
(andmap char-upper-case? (string->list s))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
|
||||||
(define-teach beginner string-lower-case?
|
(define-teach beginner string-lower-case?
|
||||||
(lambda (s)
|
(lambda (s)
|
||||||
(cerr 'string-lower-case? (string? s) "<string>" s)
|
(cerr 'string-lower-case? (string? s) "string" s)
|
||||||
(andmap char-lower-case? (string->list s))))
|
(andmap char-lower-case? (string->list s))))
|
||||||
|
|
||||||
(provide
|
(provide
|
||||||
|
|
Loading…
Reference in New Issue
Block a user