flan/test/programs/two-numbers.flan

56 lines
2.3 KiB
Plaintext

;;;; Two rendered numbers, held at once.
;;;;
;;;; i64->bytes and its two siblings render into a buffer and answer a slice
;;;; over it. That buffer used to be one file-static in the runtime, shared by
;;;; every call in the process, so the program below printed "22 22": the
;;;; second conversion overwrote the first, and the first slice — still a
;;;; perfectly valid pointer into a perfectly live buffer — was read after it.
;;;; No crash, no diagnostic, and nothing for a sanitizer to catch, because
;;;; every byte read was inside an object that was alive. The wrong bytes.
;;;;
;;;; The conversion's bytes are now copied into the temp allocator, so a
;;;; result outlives the frame that made it: the last two cases return one from
;;;; a function and push them into a Vec that outlives the loop that made them.
(defn numstr [n i64] str
(str (i64->bytes n)))
(defn main [] i32
;; Two i64 conversions alive at the same time.
(let [a (str (i64->bytes 11))
b (str (i64->bytes 22))]
(print a) (print " ") (println b)) ; 11 22
;; Three, and read in the order they were made rather than in reverse, so a
;; version that rotated among two buffers would still be caught.
(let [a (str (i64->bytes 1))
b (str (i64->bytes 2))
c (str (i64->bytes 3))]
(print a) (print b) (println c)) ; 123
;; Across the two shims: the f64's text is made first and read last.
(let [x (str (f64->bytes 2.5))
n (str (i64->bytes 7))]
(print x) (print " ") (println n)) ; 2.5 7
;; Inside a loop, one conversion per turn. Printed on one line so the
;; loop's shape is visible in the output.
(dotimes [i 4]
(let [s (str (i64->bytes (i64 (* i 11))))]
(print s) (print " ")))
(println "") ; 0 11 22 33
;; Returned from the function that made it. With the text in that
;; function's frame, the second call wrote over the first.
(let [a (numstr 11)
b (numstr 22)]
(print a) (print " ") (println b)) ; 11 22
;; Pushed, and read after the loop.
(let [v (vec-new [u8])]
(dotimes [i 3]
(push v (f64->bytes (+ (f64 i) 0.5))))
(dotimes [i 3]
(print (str (at v i))) (print " "))
(println "")) ; 0.5 1.5 2.5
0)