diff --git a/collects/htdp/convert.rkt b/collects/htdp/convert.rkt index d787135f01..bc086c1ab6 100644 --- a/collects/htdp/convert.rkt +++ b/collects/htdp/convert.rkt @@ -11,6 +11,9 @@ ;; --------------------------------------------------------------------------------------------------- +(define IN-ERROR + "The input must be a number. Given: ~e\n") + (define OUT-ERROR "The conversion function must produce a number; but it produced ~e") @@ -231,28 +234,6 @@ ;; --------------------------------------------------------------------------------------------------- -;; make-reader-for-f : (number -> number) -> ( -> void) -;; make-reader-for-f creates a function that reads numbers from a file -;; converts them according to f, and prints the results -;; effect: if any of the S-expressions in the file aren't numbers or -;; if any of f's results aren't numbers, -;; the function signals an error -(define (make-reader-for f) - (displayln 'convertfile) - (local ((define (read-until-eof) - (let ([in (read)]) - (cond - [(eof-object? in) (void)] - [(number? in) - (check-and-print (f in)) - (read-until-eof)] - [else (error 'convert "The input must be a number. Given: ~e\n" in)]))) - (define (check-and-print out) - (cond - [(number? out) (printf "~s\n" out)] - [else (error 'convert OUT-ERROR out)]))) - read-until-eof)) - ;; convert-file : str (num -> num) str -> void ;; to read a number from file in, to convert it with f, and to write it to out (define (convert-file in f out) @@ -262,13 +243,46 @@ "first" in) (check-proc 'convert-file f 1 "convert-file" "one argument") (check-arg 'convert-file (string? out) "string" "third" out) - (when (file-exists? out) - (delete-file out)) + ;; [IPort -> Void] -> Void + ;; perform the actual conversion on the file after optionally reading a prelude + (define (convert-file prefix) + (with-output-to-file out #:exists 'replace + (lambda () (with-input-from-file in (make-reader-for f prefix))))) (with-handlers ((exn:fail:read? (lambda (x) (define message (exn-message x)) (define reader-exception? (regexp-match "#reader" message)) - (if reader-exception? - (error 'convert-file CONVERT-FILE-MESSAGE) - (raise x))))) - (with-output-to-file out (lambda () (with-input-from-file in (make-reader-for f)))))) + (cond + [reader-exception? + (with-handlers ((exn:fail:read? + (lambda (x) + (error 'convert-file CONVERT-FILE-MESSAGE)))) + (convert-file + (lambda () + ;; this assumes that DrRacket adds three lines of header + ;; material to files saved in a Menu-selected language + (read-line) + (read-line) + (read-line))))] + [else (raise x)])))) + (convert-file void))) + +;; make-reader-for-f : [Number -> Number] [IPort -> Void] -> [ -> void] +;; make-reader-for-f creates a function that reads numbers from a file +;; converts them according to f, and prints the results +;; effect: if any of the S-expressions in the file aren't numbers or +;; if any of f's results aren't numbers, +;; the function signals an error +(define (make-reader-for f prefix) + (define (read-until-eof) + (prefix) + (let read-until-eof () + (define in (read)) + (cond + [(eof-object? in) (void)] + [(number? in) + (define out (f in)) + (if (number? out) (printf "~s\n" out) (error 'convert OUT-ERROR out)) + (read-until-eof)] + [else (error 'convert IN-ERROR in)]))) + read-until-eof) \ No newline at end of file diff --git a/collects/htdp/tests/convert-drracket-error.rkt b/collects/htdp/tests/convert-drracket-error.rkt index 8d96f6eae1..0ffebb56bd 100644 --- a/collects/htdp/tests/convert-drracket-error.rkt +++ b/collects/htdp/tests/convert-drracket-error.rkt @@ -4,8 +4,10 @@ (define (Fahrenheit->Celsius x) (* (/ 100 180) (- x 32))) +(convert-file "convert-drracket-non-error.txt" Fahrenheit->Celsius "out.dat") + (with-handlers ((exn? (lambda (x) (unless (cons? (regexp-match "DrRacket" (exn-message x))) (error 'test "something went wrong with the test (1)"))))) (convert-file "convert-drracket-error.txt" Fahrenheit->Celsius "out.dat") - (error 'test "something went wrong with the test (2)")) \ No newline at end of file + (raise `(test "something went wrong with the test (2)"))) \ No newline at end of file diff --git a/collects/htdp/tests/convert-drracket-error.txt b/collects/htdp/tests/convert-drracket-error.txt index 46698aaf71..0b736d5a2b 100644 --- a/collects/htdp/tests/convert-drracket-error.txt +++ b/collects/htdp/tests/convert-drracket-error.txt @@ -1,5 +1,6 @@ ;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. +;; MATTHIAS ADDED THIS LINE TO BREAK THE BRITTLE ASSUMPTION IN HTDP/CONVERT. #reader(lib "htdp-beginner-reader.ss" "lang")((modname convert-drracket-error) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) 214 diff --git a/collects/htdp/tests/convert-drracket-non-error.txt b/collects/htdp/tests/convert-drracket-non-error.txt new file mode 100644 index 0000000000..46698aaf71 --- /dev/null +++ b/collects/htdp/tests/convert-drracket-non-error.txt @@ -0,0 +1,5 @@ +;; The first three lines of this file were inserted by DrRacket. They record metadata +;; about the language level of this file in a form that our tools can easily process. +#reader(lib "htdp-beginner-reader.ss" "lang")((modname convert-drracket-error) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ()))) + +214