Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error". Bradley Lucier (08 Mar 2023 21:19 UTC)
|
Re: Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error".
Marc Nieper-Wißkirchen
(09 Mar 2023 08:33 UTC)
|
Re: Testing how array-creation routines interact with continuations, and crashing when the user does something that "is an error".
Bradley Lucier
(09 Mar 2023 18:30 UTC)
|
New tests for procedures when reinvoking continuations; fix crashes.
Bradley Lucier
(09 Mar 2023 22:02 UTC)
|
There are currently no tests in the test suite for how array-{copy|append|stack|decurry|block}[!]* interact with continuations, and I'd like to fix that, especially for independent implementations of this SRFI. I started with (pp is pretty-print to the system output port): > (import (srfi 231)) > (let* ((cont #f) (call-cont #t) (domain (make-interval '#(2 2))) (A_ (lambda (i j) (call-with-current-continuation (lambda (c) (if (= i j 0) (set! cont c)) 1)))) (A (make-array domain A_)) (array-list '())) (set! array-list (cons (array-copy A) array-list)) (pp 'printing) (for-each (lambda (A) (pp (array->list* A))) array-list) (if call-cont (begin (set! call-cont #f) (cont 4))) (pp (apply eq? array-list))) printing ((1 1) (1 1)) printing ((4 1) (1 1)) ((1 1) (1 1)) #f which works as expected. Replacing array-copy with array-copy! in this test causes the library to crash when compiled in Gambit with safety checks removed: > (let* ((cont #f) (call-cont #t) (domain (make-interval '#(2 2))) (A_ (lambda (i j) (call-with-current-continuation (lambda (c) (if (= i j 0) (set! cont c)) 1)))) (A (make-array domain A_)) (array-list '())) (set! array-list (cons (array-copy! A) array-list)) (pp 'printing) (for-each (lambda (A) (pp (array->list* A))) array-list) (if call-cont (begin (set! call-cont #f) (cont 4))) (pp (apply eq? array-list))) printing ((1 1) (1 1)) printing Segmentation fault (core dumped) I didn't expect this, I just expected that the first and second elements of array-list would be eq?. Running the library interpreted shows the problem: > (load "generic-arrays.scm") "/home/lucier/lang/scheme/srfi-231/srfi-231-temp/generic-arrays.scm" > (let* ((cont #f) (call-cont #t) (domain (make-interval '#(2 2))) (A_ (lambda (i j) (call-with-current-continuation (lambda (c) (if (= i j 0) (set! cont c)) 1)))) (A (make-array domain A_)) (array-list '())) (set! array-list (cons (array-copy! A) array-list)) (pp 'printing) (for-each (lambda (A) (pp (array->list* A))) array-list) (if call-cont (begin (set! call-cont #f) (cont 4))) (pp (apply eq? array-list))) printing ((1 1) (1 1)) *** ERROR IN #<procedure #2>, "generic-arrays.scm"@2534.42 -- (Argument 2, k) Out of range (vector-set! #(4 1 1 1) 5 1) 1> Here is the code: ;; No checks needed, storage-class-setter is vector-set! (let ((body (%%array-body destination))) (%%interval-for-each (case (%%interval-dimension domain) ((0) (let ((index initial-offset)) (lambda () (vector-set! body index (getter)) (set! index (fx+ index 1))))) ;; not necessary ((1) (let ((index initial-offset)) (lambda (i) (vector-set! body index (getter i)) (set! index (fx+ index 1))))) ((2) (let ((index initial-offset)) (lambda (i j) (vector-set! body index (getter i j)) ;; <<<<<< problem (set! index (fx+ index 1))))) ((3) (let ((index initial-offset)) (lambda (i j k) (vector-set! body index (getter i j k)) (set! index (fx+ index 1))))) ((4) (let ((index initial-offset)) (lambda (i j k l) (vector-set! body index (getter i j k l)) (set! index (fx+ index 1))))) (else (let ((index initial-offset)) (lambda multi-index (vector-set! body index (apply getter multi-index)) (set! index (fx+ index 1)))))) domain)) So I was using mutated state (the value of index) in a (perhaps vain) attempt to speed things up, but this causes index to walk off the end of the specialized array result's body the second time the continuation is invoked. The specifications says "Don't do that!", don't invoke the continuation of the argument array's getter more than once when calling array-copy!. On the other hand, I didn't expect the library to crash the system. Is this OK behavior, to crash when the user does something that "is an error", or would it be better to try to catch all such instances while possibly slowing down the general case? Brad