48 lines
2.3 KiB
Plaintext
48 lines
2.3 KiB
Plaintext
;;;; M2 queue item 5: typed = and != grow strings. Bytewise, with a
|
|
;;;; length-mismatch fast path and a same-pointer fast path ahead of the byte
|
|
;;;; loop (runtime/flan_rt.c, flan_str_eq). Ordering stays refused on a
|
|
;;;; string -- that half is tested in test_flan.ml, because a program that
|
|
;;;; wrote (< "a" "b") would not compile and so cannot be a row here.
|
|
|
|
(defn main [] i32
|
|
;; Same pointer: one local read twice is the same two words, ptr and len
|
|
;; both, and the fast path answers before a single byte is looked at.
|
|
(let [s "same"]
|
|
(println (= s s)) ; true
|
|
(println (!= s s))) ; false
|
|
|
|
;; Differing lengths: the length check alone settles it, and never reaches
|
|
;; the byte loop -- a common prefix would be no evidence otherwise.
|
|
(println (= "abc" "ab")) ; false
|
|
(println (!= "abc" "ab")) ; true
|
|
|
|
;; Equal contents, distinct pointers. "abc" the literal lives in the
|
|
;; read-only data section; to-lower of "ABC" is a fresh heap allocation,
|
|
;; so this pair shares no address and the same-pointer fast path cannot
|
|
;; fire -- what answers here is the byte loop, or the length check first
|
|
;; ruling nothing out since both are three bytes.
|
|
(let [heap (to-lower (bytes-view "ABC"))]
|
|
(let [h (str (slice heap))]
|
|
(println (= "abc" h)) ; true
|
|
(println (!= "abc" h)))
|
|
(free heap))
|
|
|
|
;; A one-byte difference at the end, so the length check cannot rule it
|
|
;; out and the byte loop has to run to the last byte before it can answer.
|
|
(println (= "abd" "abc")) ; false
|
|
(println (!= "abd" "abc")) ; true
|
|
|
|
;; Empty strings: the length check's zero case, which the runtime helper
|
|
;; also uses to skip a memcmp that would otherwise read through a null
|
|
;; pointer -- two empty string literals, and empty against non-empty.
|
|
(println (= "" "")) ; true
|
|
(println (= "" "a")) ; false
|
|
(println (= "a" "")) ; false
|
|
|
|
;; A slice and the prefix it was cut from: same base pointer, different
|
|
;; lengths -- the one pair the same-pointer fast path would answer wrong on
|
|
;; if it ran before the length check instead of after.
|
|
(let [s "abcd"]
|
|
(println (= s (str (slice (bytes-view s) 0 2))))) ; false
|
|
0)
|