diff --git a/drracket-test/tests/drracket/example-tool.rkt b/drracket-test/tests/drracket/example-tool.rkt index a2ba53506..316c2874b 100644 --- a/drracket-test/tests/drracket/example-tool.rkt +++ b/drracket-test/tests/drracket/example-tool.rkt @@ -8,8 +8,7 @@ (define new-collection-root #; (string->path "C:\\tmp") - (make-temporary-file "drracket-test-example-tool~a" - 'directory)) + (make-temporary-directory "drracket-test-example-tool~a")) (define coll (build-path new-collection-root "coll")) (unless (directory-exists? coll) (make-directory coll)) diff --git a/drracket-test/tests/drracket/language-test.rkt b/drracket-test/tests/drracket/language-test.rkt index dcb74eaef..4c2942a09 100644 --- a/drracket-test/tests/drracket/language-test.rkt +++ b/drracket-test/tests/drracket/language-test.rkt @@ -1532,11 +1532,11 @@ the settings above should match r5rs (define (prepare-for-test-expression) - (let ([drs (wait-for-drracket-frame)]) - (clear-definitions drs) - (set-language #t) - (sleep 1) ;; this shouldn't be neccessary.... - (do-execute drs))) + (define drs (wait-for-drracket-frame)) + (clear-definitions drs) + (set-language #t) + (sleep 1) ;; this shouldn't be neccessary.... + (do-execute drs)) ;; test-setting : (-> void) string string string -> void ;; opens the language dialog, runs `set-setting' @@ -1552,34 +1552,37 @@ the settings above should match r5rs (let ([f (test:get-active-top-level-window)]) (fw:test:button-push "OK") (wait-for-new-frame f)) - (let* ([drs (test:get-active-top-level-window)] - [interactions (send drs get-interactions-text)]) - (clear-definitions drs) - (insert-in-definitions drs expression) - (do-execute drs) - (when interactions-expr - (insert-in-interactions drs interactions-expr) - (alt-return-in-interactions drs) - (wait-for-computation drs)) - (let* ([got (fetch-output/should-be-tested drs)]) - (unless (if (regexp? result) - (regexp-match? result got) - (string=? result got)) - (eprintf "FAILED: ~s ~s ~s test\n expected: ~s\n got: ~s\n" - (language) setting-name expression result got))))) + (define drs (test:get-active-top-level-window)) + (send drs get-interactions-text) + (clear-definitions drs) + (insert-in-definitions drs expression) + (do-execute drs) + (when interactions-expr + (insert-in-interactions drs interactions-expr) + (alt-return-in-interactions drs) + (wait-for-computation drs)) + (define got (fetch-output/should-be-tested drs)) + (unless (if (regexp? result) + (regexp-match? result got) + (string=? result got)) + (eprintf "FAILED: ~s ~s ~s test\n expected: ~s\n got: ~s\n" + (language) + setting-name + expression + result + got))) (define (test-hash-bang) - (let* ([expression "#!/bin/sh\n1"] - [result "1"] - [drs (test:get-active-top-level-window)] - [interactions (queue-callback (λ () (send drs get-interactions-text)))]) - (clear-definitions drs) - (insert-in-definitions drs expression) - (do-execute drs) - (let* ([got (fetch-output/should-be-tested drs)]) - (unless (string=? "1" got) - (eprintf "FAILED: ~s ~a test\n expected: ~s\n got: ~s\n" - (language) expression result got))))) + (define expression "#!/bin/sh\n1") + (define result "1") + (define drs (test:get-active-top-level-window)) + (queue-callback (λ () (send drs get-interactions-text))) + (clear-definitions drs) + (insert-in-definitions drs expression) + (do-execute drs) + (define got (fetch-output/should-be-tested drs)) + (unless (string=? "1" got) + (eprintf "FAILED: ~s ~a test\n expected: ~s\n got: ~s\n" (language) expression result got))) (define (fetch-output/should-be-tested . args) (regexp-replace (regexp @@ -1683,13 +1686,13 @@ the settings above should match r5rs (when (and has-sharing? show-sharing) (fw:test:set-check-box! "Show sharing in values" - (if (eq? show-sharing 'on) #t #f))) + (eq? show-sharing 'on))) (fw:test:set-check-box! "Insert newlines in printed values" pretty?) - (let ([f (test:get-active-top-level-window)]) - (fw:test:button-push "OK") - (wait-for-new-frame f))) + (define f (test:get-active-top-level-window)) + (fw:test:button-push "OK") + (wait-for-new-frame f)) (define (shorten str) (if ((string-length str) . <= . 45) str @@ -1774,15 +1777,14 @@ the settings above should match r5rs (unless (member #\newline (string->list got)) (eprintf "long output should have contained newlines, got ~s\n" got))) - (let () - (clear-definitions drr) - (insert-in-definitions drr (defs-prefix)) - (insert-in-definitions drr "(print-value-columns 1000)") - (insert-in-definitions drr "(build-list 100 values)") - (do-execute drr) - (define got (fetch-output/should-be-tested drr)) - (when (member #\newline (string->list got)) - (eprintf "long output should not have contained newlines, got ~s\n" got))))) + (clear-definitions drr) + (insert-in-definitions drr (defs-prefix)) + (insert-in-definitions drr "(print-value-columns 1000)") + (insert-in-definitions drr "(build-list 100 values)") + (do-execute drr) + (define got (fetch-output/should-be-tested drr)) + (when (member #\newline (string->list got)) + (eprintf "long output should not have contained newlines, got ~s\n" got)))) (define (find-output-radio-box label) (define frame (test:get-active-top-level-window)) @@ -1818,26 +1820,24 @@ the settings above should match r5rs "WARNING: Interactions window is out of sync with the definitions window\\.")) (define (test-error-after-definition) - (let* ([drs (wait-for-drracket-frame)] - [interactions-text (queue-callback/res (λ () (send drs get-interactions-text)))]) - (clear-definitions drs) - (insert-in-definitions drs (defs-prefix)) - (insert-in-definitions drs "(define y 0) (define (f x) (/ x y)) (f 2)") - (do-execute drs) - (let ([last-para (queue-callback/res (λ () (send interactions-text last-paragraph)))]) - (type-in-interactions drs "y\n") - (wait-for-computation drs) - (let ([got - (fetch-output/should-be-tested - drs - (queue-callback/res - (λ () (send interactions-text paragraph-start-position (+ last-para 1)))) - (queue-callback/res - (λ () - (send interactions-text paragraph-end-position - (- (send interactions-text last-paragraph) 1)))))]) - (unless (equal? got "0") - (eprintf "FAILED: test-error-after-definition failed, expected 0, got ~s\n" got)))))) + (define drs (wait-for-drracket-frame)) + (define interactions-text (queue-callback/res (λ () (send drs get-interactions-text)))) + (clear-definitions drs) + (insert-in-definitions drs (defs-prefix)) + (insert-in-definitions drs "(define y 0) (define (f x) (/ x y)) (f 2)") + (do-execute drs) + (define last-para (queue-callback/res (λ () (send interactions-text last-paragraph)))) + (type-in-interactions drs "y\n") + (wait-for-computation drs) + (define got + (fetch-output/should-be-tested + drs + (queue-callback/res (λ () (send interactions-text paragraph-start-position (+ last-para 1)))) + (queue-callback/res (λ () + (send interactions-text paragraph-end-position + (- (send interactions-text last-paragraph) 1)))))) + (unless (equal? got "0") + (eprintf "FAILED: test-error-after-definition failed, expected 0, got ~s\n" got))) ;; test-expression : (union string 'xml 'image (listof (union string 'xml 'image))) @@ -1915,26 +1915,20 @@ the settings above should match r5rs (send interactions-text last-position)) (send interactions-text paste)))) - (let ([last-para (queue-callback/res (λ () (send interactions-text last-paragraph)))]) - (alt-return-in-interactions drs) - (wait-for-computation drs) - (let ([got - (fetch-output - drs - (queue-callback/res - (λ () - (send interactions-text paragraph-start-position (+ last-para 1)))) - (queue-callback/res - (λ () - (send interactions-text paragraph-end-position - (- (send interactions-text last-paragraph) 1)))))]) - (when (regexp-match re:out-of-sync got) - (error 'text-expression "got out of sync message")) - (unless (check-expectation repl-expected got) - (eprintf (make-err-msg repl-expected) - 'interactions - (language) - expression repl-expected got)))))) + (define last-para (queue-callback/res (λ () (send interactions-text last-paragraph)))) + (alt-return-in-interactions drs) + (wait-for-computation drs) + (define got + (fetch-output + drs + (queue-callback/res (λ () (send interactions-text paragraph-start-position (+ last-para 1)))) + (queue-callback/res (λ () + (send interactions-text paragraph-end-position + (- (send interactions-text last-paragraph) 1)))))) + (when (regexp-match re:out-of-sync got) + (error 'text-expression "got out of sync message")) + (unless (check-expectation repl-expected got) + (eprintf (make-err-msg repl-expected) 'interactions (language) expression repl-expected got)))) (define (test-undefined-var id #:icon+in? [icon+in? #f]) (test-expression diff --git a/drracket-test/tests/drracket/memory-log.rkt b/drracket-test/tests/drracket/memory-log.rkt index 0e6ebbc02..608280ccf 100644 --- a/drracket-test/tests/drracket/memory-log.rkt +++ b/drracket-test/tests/drracket/memory-log.rkt @@ -20,7 +20,7 @@ (collect-garbage) (define new-cmu (current-memory-use)) (cond - [(or (< n 0) (< (abs (- cmu new-cmu)) (* 0.01 cmu))) new-cmu] + [(or (negative? n) (< (abs (- cmu new-cmu)) (* 0.01 cmu))) new-cmu] [else (loop new-cmu (- n 1))]))) (void (putenv "PLTDRPLACEPRINT" "yes")) diff --git a/drracket-test/tests/drracket/syncheck-test.rkt b/drracket-test/tests/drracket/syncheck-test.rkt index dca5af649..48a44ed41 100644 --- a/drracket-test/tests/drracket/syncheck-test.rkt +++ b/drracket-test/tests/drracket/syncheck-test.rkt @@ -1770,29 +1770,28 @@ (copy-port in-port out-port))))) (fire-up-drracket-and-run-tests (λ () - (let ([drs (wait-for-drracket-frame)]) - ;(set-language-level! (list "Pretty Big")) - (begin - (set-language-level! (list "Pretty Big") #f) - (test:set-radio-box-item! "No debugging or profiling") - (let ([f (test:get-active-top-level-window)]) - (test:button-push "OK") - (wait-for-new-frame f))) - (do-execute drs) - (let* ([defs (queue-callback/res (λ () (send drs get-definitions-text)))] - [filename (make-temporary-file "syncheck-test~a" #f temp-dir)]) - (queue-callback/res (λ () (send defs save-file filename))) - (preferences:set 'framework:coloring-active #f) - (close-the-error-window-test drs) - (for-each (run-one-test temp-dir) tests) - (preferences:set 'framework:coloring-active #t) - (queue-callback/res - (λ () - (send defs save-file) ;; clear out autosave - (send defs set-filename #f))) - (delete-file filename) - - (printf "Ran ~a tests.\n" total-tests-run)))))) + (define drs (wait-for-drracket-frame)) + ;(set-language-level! (list "Pretty Big")) + (begin + (set-language-level! (list "Pretty Big") #f) + (test:set-radio-box-item! "No debugging or profiling") + (let ([f (test:get-active-top-level-window)]) + (test:button-push "OK") + (wait-for-new-frame f))) + (do-execute drs) + (define defs (queue-callback/res (λ () (send drs get-definitions-text)))) + (define filename (make-temporary-file "syncheck-test~a" #f temp-dir)) + (queue-callback/res (λ () (send defs save-file filename))) + (preferences:set 'framework:coloring-active #f) + (close-the-error-window-test drs) + (for-each (run-one-test temp-dir) tests) + (preferences:set 'framework:coloring-active #t) + (queue-callback/res (λ () + (send defs save-file) ;; clear out autosave + (send defs set-filename #f))) + (delete-file filename) + + (printf "Ran ~a tests.\n" total-tests-run)))) (λ () (delete-directory/files temp-dir)))) (define (close-the-error-window-test drs) @@ -1810,177 +1809,161 @@ (define ((run-one-test save-dir) test) (set! total-tests-run (+ total-tests-run 1)) - (let* ([drs (wait-for-drracket-frame)] - [defs (queue-callback/res (λ () (send drs get-definitions-text)))]) - (clear-definitions drs) - (cond - [(test? test) - (let ([pre-input (test-input test)] - [expected (test-expected test)] - [arrows (test-arrows test)] - [tooltips (test-tooltips test)] - [relative "list.rkt"] - [setup (test-setup test)] - [teardown (test-teardown test)] - [extra-files (test-extra-files test)] - [extra-info? (test-extra-info? test)]) - (define extra-file-paths - (for/list ([(name contents) (in-hash extra-files)]) - (define path (build-path save-dir name)) - (display-to-file contents path #:mode 'text) - path)) - - (define setup-result (setup)) - (define input (if (procedure? pre-input) - (pre-input setup-result) - pre-input)) + (define drs (wait-for-drracket-frame)) + (define defs (queue-callback/res (λ () (send drs get-definitions-text)))) + (clear-definitions drs) + (cond + [(test? test) + (define pre-input (test-input test)) + (define expected (test-expected test)) + (define arrows (test-arrows test)) + (define tooltips (test-tooltips test)) + (define relative "list.rkt") + (define setup (test-setup test)) + (define teardown (test-teardown test)) + (define extra-files (test-extra-files test)) + (define extra-info? (test-extra-info? test)) + (define extra-file-paths + (for/list ([(name contents) (in-hash extra-files)]) + (define path (build-path save-dir name)) + (display-to-file contents path #:mode 'text) + path)) + + (define setup-result (setup)) + (define input + (if (procedure? pre-input) + (pre-input setup-result) + pre-input)) + (cond + [(dir-test? test) (insert-in-definitions drs (format input (path->require-string relative)))] + [else (insert-in-definitions drs input)]) + (click-check-syntax-and-check-errors drs test extra-info?) + + ;; need to check for syntax error here + (let ([got (get-annotated-output drs)] + [got-arrows (queue-callback/res (λ () (send defs syncheck:get-bindings-table)))]) + (when extra-info? + (printf "got-arrows\n") + (pretty-print got-arrows) + (newline) + + (printf "'drracket:syncheck:show-arrows? ~s\n" + (preferences:get 'drracket:syncheck:show-arrows?))) + (compare-output (cond + [(dir-test? test) + (for/list ([x (in-list expected)]) + (list (if (eq? (car x) 'relative-path) + (path->require-string relative) + (car x)) + (cadr x)))] + [else expected]) + got + arrows + got-arrows + input + (test-line test))) + (when tooltips + (compare-tooltips (queue-callback/res (λ () (send defs syncheck:get-bindings-table #t))) + tooltips + (test-line test))) + + (teardown setup-result) + (for-each delete-directory/files extra-file-paths)] + [(rename-test? test) + (insert-in-definitions drs (rename-test-input test)) + (click-check-syntax-and-check-errors drs test #f) + (define menu-item + (queue-callback/res + (λ () + (define defs (send drs get-definitions-text)) + (define menu (make-object popup-menu%)) + (send defs syncheck:build-popup-menu menu (rename-test-pos test) defs) + (define item-name (format "Rename ~a" (rename-test-old-name test))) + (define menu-item + (for/or ([x (in-list (send menu get-items))]) + (and (is-a? x labelled-menu-item<%>) (equal? (send x get-label) item-name) x))) + (cond + [menu-item menu-item] + [else + (eprintf "syncheck-test.rkt: rename test ~s didn't find menu item named ~s in ~s\n" + test + item-name + (map (λ (x) (and (is-a? x labelled-menu-item<%>) (send x get-label))) + (send menu get-items))) + #f])))) + (when (and menu-item (rename-test-new-name test) (rename-test-output test)) + (queue-callback (λ () (send menu-item command (make-object control-event% 'menu)))) + (wait-for-new-frame drs) + (for ([x (in-string (rename-test-new-name test))]) + (test:keystroke x)) + (test:button-push "OK") + (define result + (queue-callback/res (λ () + (define defs (send drs get-definitions-text)) + (send defs get-text 0 (send defs last-position))))) + (unless (equal? result (rename-test-output test)) + (eprintf "syncheck-test.rkt FAILED\n test ~s\n got ~s\n" test result)))] + [(prefix-test? test) + (insert-in-definitions drs (prefix-test-input test)) + (click-check-syntax-and-check-errors drs test #f) + (define menu-item + (queue-callback/res + (λ () + (define defs (send drs get-definitions-text)) + (define menu (make-object popup-menu%)) + (send defs syncheck:build-popup-menu menu (prefix-test-pos test) defs) + (define item-name "Add Require Prefix") + (define menu-item + (for/or ([x (in-list (send menu get-items))]) + (and (is-a? x labelled-menu-item<%>) (equal? (send x get-label) item-name) x))) + (cond + [menu-item menu-item] + [else + (eprintf "syncheck-test.rkt: prefix test ~s didn't find menu item named ~s in ~s\n" + test + item-name + (map (λ (x) (and (is-a? x labelled-menu-item<%>) (send x get-label))) + (send menu get-items))) + #f])))) + (when menu-item + (queue-callback (λ () (send menu-item command (make-object control-event% 'menu)))) + (wait-for-new-frame drs) + (for ([x (in-string (prefix-test-prefix test))]) + (test:keystroke x)) + (test:button-push "OK") + (define result + (queue-callback/res (λ () + (define defs (send drs get-definitions-text)) + (send defs get-text 0 (send defs last-position))))) + (unless (equal? result (prefix-test-output test)) + (eprintf "syncheck-test.rkt FAILED\n test ~s\n got ~s\n" test result)))] + [(err-test? test) + (let/ec done + (insert-in-definitions drs (err-test-input test)) + (define err (click-check-syntax-and-check-errors drs test #f #:err-ok? #t)) + (unless err + (eprintf "syncheck-test.rkt FAILED\n test ~s\n didn't get an error\n" test) + (done)) + (define expected (err-test-expected test)) + (define message-good? (cond - [(dir-test? test) - (insert-in-definitions drs (format input (path->require-string relative)))] - [else (insert-in-definitions drs input)]) - (click-check-syntax-and-check-errors drs test extra-info?) - - ;; need to check for syntax error here - (let ([got (get-annotated-output drs)] - [got-arrows (queue-callback/res (λ () (send defs syncheck:get-bindings-table)))]) - (when extra-info? - (printf "got-arrows\n") - (pretty-print got-arrows) - (newline) - - (printf "'drracket:syncheck:show-arrows? ~s\n" - (preferences:get 'drracket:syncheck:show-arrows?))) - (compare-output (cond - [(dir-test? test) - (map (lambda (x) - (list (if (eq? (car x) 'relative-path) - (path->require-string relative) - (car x)) - (cadr x))) - expected)] - [else - expected]) - got - arrows - got-arrows - input - (test-line test))) - (when tooltips - (compare-tooltips (queue-callback/res (λ () (send defs syncheck:get-bindings-table #t))) - tooltips - (test-line test))) - - (teardown setup-result) - (for-each delete-directory/files extra-file-paths))] - [(rename-test? test) - (insert-in-definitions drs (rename-test-input test)) - (click-check-syntax-and-check-errors drs test #f) - (define menu-item - (queue-callback/res - (λ () - (define defs (send drs get-definitions-text)) - (define menu (make-object popup-menu%)) - (send defs syncheck:build-popup-menu menu (rename-test-pos test) defs) - (define item-name (format "Rename ~a" (rename-test-old-name test))) - (define menu-item - (for/or ([x (in-list (send menu get-items))]) - (and (is-a? x labelled-menu-item<%>) - (equal? (send x get-label) item-name) - x))) - (cond - [menu-item - menu-item] - [else - (eprintf "syncheck-test.rkt: rename test ~s didn't find menu item named ~s in ~s\n" - test - item-name - (map (λ (x) (and (is-a? x labelled-menu-item<%>) (send x get-label))) - (send menu get-items))) - #f])))) - (when (and menu-item (rename-test-new-name test) (rename-test-output test)) - (queue-callback (λ () (send menu-item command (make-object control-event% 'menu)))) - (wait-for-new-frame drs) - (for ([x (in-string (rename-test-new-name test))]) - (test:keystroke x)) - (test:button-push "OK") - (define result - (queue-callback/res (λ () - (define defs (send drs get-definitions-text)) - (send defs get-text 0 (send defs last-position))))) - (unless (equal? result (rename-test-output test)) - (eprintf "syncheck-test.rkt FAILED\n test ~s\n got ~s\n" - test - result)))] - [(prefix-test? test) - (insert-in-definitions drs (prefix-test-input test)) - (click-check-syntax-and-check-errors drs test #f) - (define menu-item - (queue-callback/res - (λ () - (define defs (send drs get-definitions-text)) - (define menu (make-object popup-menu%)) - (send defs syncheck:build-popup-menu menu (prefix-test-pos test) defs) - (define item-name "Add Require Prefix") - (define menu-item - (for/or ([x (in-list (send menu get-items))]) - (and (is-a? x labelled-menu-item<%>) - (equal? (send x get-label) item-name) - x))) - (cond - [menu-item - menu-item] - [else - (eprintf "syncheck-test.rkt: prefix test ~s didn't find menu item named ~s in ~s\n" - test - item-name - (map (λ (x) (and (is-a? x labelled-menu-item<%>) (send x get-label))) - (send menu get-items))) - #f])))) - (when menu-item - (queue-callback (λ () (send menu-item command (make-object control-event% 'menu)))) - (wait-for-new-frame drs) - (for ([x (in-string (prefix-test-prefix test))]) - (test:keystroke x)) - (test:button-push "OK") - (define result - (queue-callback/res (λ () - (define defs (send drs get-definitions-text)) - (send defs get-text 0 (send defs last-position))))) - (unless (equal? result (prefix-test-output test)) - (eprintf "syncheck-test.rkt FAILED\n test ~s\n got ~s\n" - test - result)))] - [(err-test? test) - (let/ec done - (insert-in-definitions drs (err-test-input test)) - (define err (click-check-syntax-and-check-errors drs test #f #:err-ok? #t)) - (unless err - (eprintf "syncheck-test.rkt FAILED\n test ~s\n didn't get an error\n" - test) - (done)) - (define expected (err-test-expected test)) - (define message-good? - (cond - [(string? expected) - (equal? expected err)] - [else - (regexp-match? expected err)])) - (unless message-good? - (eprintf "syncheck-test.rkt FAILED error doesn't match\n test ~s\n ~s\n" - test - err) - (done)) - (define srclocs (queue-callback/res (λ () (send (send drs get-interactions-text) get-error-ranges)))) - (define actual - (for/set ([srcloc (in-list srclocs)]) - (list (srcloc-position srcloc) - (srcloc-span srcloc)))) - (unless (equal? actual (err-test-locations test)) - (eprintf "syncheck-test.rkt FAILED srclocs don't match\n test ~s\n actual ~s\n got ~s\n" - test - actual - (err-test-locations test))) - (void))]))) + [(string? expected) (equal? expected err)] + [else (regexp-match? expected err)])) + (unless message-good? + (eprintf "syncheck-test.rkt FAILED error doesn't match\n test ~s\n ~s\n" test err) + (done)) + (define srclocs + (queue-callback/res (λ () (send (send drs get-interactions-text) get-error-ranges)))) + (define actual + (for/set ([srcloc (in-list srclocs)]) + (list (srcloc-position srcloc) (srcloc-span srcloc)))) + (unless (equal? actual (err-test-locations test)) + (eprintf + "syncheck-test.rkt FAILED srclocs don't match\n test ~s\n actual ~s\n got ~s\n" + test + actual + (err-test-locations test))) + (void))])) (define (path->require-string relative) (define (p->string p) @@ -1998,25 +1981,25 @@ (lexically-bound-variable lexically-bound))) (define (collapse-and-rename expected) - (let ([renamed - (map (lambda (ent) - (let* ([str (car ent)] - [id (cadr ent)] - [matches (assoc id remappings)]) - (if matches - (list str (cadr matches)) - ent))) - expected)]) - (let loop ([ids renamed]) - (cond - [(null? ids) null] - [(null? (cdr ids)) ids] - [else (let ([fst (car ids)] - [snd (cadr ids)]) - (if (eq? (cadr fst) (cadr snd)) - (loop (cons (list (string-append (car fst) (car snd)) (cadr fst)) - (cddr ids))) - (cons fst (loop (cdr ids)))))])))) + (define renamed + (map (lambda (ent) + (let* ([str (car ent)] + [id (cadr ent)] + [matches (assoc id remappings)]) + (if matches + (list str (cadr matches)) + ent))) + expected)) + (let loop ([ids renamed]) + (cond + [(null? ids) null] + [(null? (cdr ids)) ids] + [else + (let ([fst (car ids)] + [snd (cadr ids)]) + (if (eq? (cadr fst) (cadr snd)) + (loop (cons (list (string-append (car fst) (car snd)) (cadr fst)) (cddr ids))) + (cons fst (loop (cdr ids)))))]))) ;; compare-arrows : expression ;; (or/c #f (listof (cons (list number-or-proc number-or-proc)