(ns com.tailrecursion.blacktide.source-values-test
"Primitive source reads box at each Object use; mutable locations and saved
Object references retain their identity across normalization and transfers."
(:require [clojure.test :refer [deftest is]]
[com.tailrecursion.blacktide.backend-fixture :as backend]))
(def initializers
'[1000 1.5 (int 1000) (short 1000) (byte 4) (float 1.5) (char 256) (boolean true)
(identity 1000) (identity 1.5) (Integer. 1000) (Double. 1.5)])
(deftest source-reads-preserve-width-and-identity
(doseq [init initializers
body '[(identical? x x)
(let [[a b] [x x]] (identical? a b))
(let [snapshot (identity x)] (identical? snapshot snapshot))
(let [x (identity x)] (identical? x x))]
:let [form (list 'let ['x init] body) reference (backend/compile-program form :default)]
mode [:default :dispatcher]]
(is (= (reference nil) ((backend/compile-program (list 'loophole [] form) mode) nil)) (pr-str [init body mode])))
(doseq [init initializers :let [form (list 'let ['x init] 'x) reference (backend/compile-program form :default)]
mode [:default :dispatcher] :let [compiled (backend/compile-program (list 'loophole [] form) mode)]]
(is (= (reference nil) (compiled nil)) (pr-str [init mode]))
(is (= (class (reference nil)) (class (compiled nil))) (pr-str [init mode]))
(is (= (identical? (reference nil) (reference nil)) (identical? (compiled nil) (compiled nil)))
(pr-str [init mode]))))
(deftest mutable-snapshots-remain-references
(doseq [mode [:default :dispatcher] init initializers
form [(list 'loophole ['x init 'y nil] '(psetq y x x x) '(identical? x y))
(list 'loophole ['x nil 'y nil] (list 'psetq 'y (list 'setq 'x init)) '(identical? x y))
(list 'loophole ['x init]
'(let [saved x] (setq x nil) (identical? saved saved)))]]
(is (true? ((backend/compile-program form mode) nil)) (pr-str [mode form])))
(doseq [mode [:default :dispatcher]]
(is (= [1000 true false]
((backend/compile-program
'(loophole [x 1000 y nil count 0 saved x]
(label again)
(psetq y x x (long 1001))
(setq count (inc count))
(when (< count 2) (setq x saved) (goto again))
[saved (identical? saved y) (identical? saved x)]) mode) nil)))))