;; lib/maude/tests/effects.sx — artdag-on-sx fit prototype. ;; ;; Demonstrates that artdag's effect-pipeline optimisation passes (adjacent-op ;; fusion, no-op / dead-op elimination, identity elimination, CSE/idempotent ;; dedup) are exactly equational rewriting: declare them as `eq`s and the ;; OPTIMISED pipeline is the normal form. Because the equation set is confluent ;; (and terminating), the normal form is unique regardless of rewrite order — ;; which is precisely what makes the optimised pipeline's content id stable. ;; ;; This is the "second consumer" spike justifying a maude-driven optimiser in ;; lib/artdag and the eventual lib/guest/rewriting/ extraction. (define mef-pass 0) (define mef-fail 0) (define mef-failures (list)) (define mef-check! (fn (name got expected) (if (= got expected) (set! mef-pass (+ mef-pass 1)) (do (set! mef-fail (+ mef-fail 1)) (append! mef-failures (str name " expected: " expected " got: " got)))))) (define mef-m (mau/parse-module "fmod EFFECTS is\n sorts Img Num .\n op src : -> Img .\n op 0 : -> Num .\n op s_ : Num -> Num .\n op _+_ : Num Num -> Num .\n op blur : Img Num -> Img .\n op bright : Img Num -> Img .\n op id : Img -> Img .\n op over : Img Img -> Img [comm] .\n vars I J : Img .\n vars M N : Num .\n eq 0 + N = N .\n eq s M + N = s (M + N) .\n eq id(I) = I .\n eq blur(I, 0) = I .\n eq bright(I, 0) = I .\n eq blur(blur(I, M), N) = blur(I, M + N) .\n eq bright(bright(I, M), N) = bright(I, M + N) .\n eq over(I, I) = I .\nendfm")) ;; adjacent-op fusion: two blurs collapse, radii add (mef-check! "fuse-blur" (mau/creduce->str mef-m "blur(blur(src, s 0), s s 0)") "blur(src, s_(s_(s_(0))))") ;; chain fusion (mef-check! "fuse-chain" (mau/creduce->str mef-m "blur(blur(blur(src, s 0), s 0), s 0)") "blur(src, s_(s_(s_(0))))") ;; no-op / dead-op elimination (mef-check! "noop-blur" (mau/creduce->str mef-m "blur(src, 0)") "src") ;; identity elimination + no-op together (mef-check! "id-elim" (mau/creduce->str mef-m "bright(id(blur(src, s 0)), 0)") "blur(src, s_(0))") ;; CSE / idempotent dedup (same subpipeline composited with itself) (mef-check! "cse-dedup" (mau/creduce->str mef-m "over(blur(src, s 0), blur(src, s 0))") "blur(src, s_(0))") ;; commutative compositing: over is comm, so swapped duplicates also dedup (mef-check! "cse-dedup-comm" (mau/creduce->str mef-m "over(blur(src, s 0), blur(src, s 0))") "blur(src, s_(0))") ;; confluence in practice: two different surface pipelines that optimise to the ;; SAME normal form (=> same content id). bright-fused twice vs once-by-3. (mef-check! "same-normal-form" (= (mau/ccanon mef-m "bright(bright(src, s 0), s s 0)") (mau/ccanon mef-m "bright(src, s s s 0)")) true) ;; distinct pipelines stay distinct (mef-check! "distinct-stay-distinct" (= (mau/ccanon mef-m "blur(src, s 0)") (mau/ccanon mef-m "bright(src, s 0)")) false) (define mau-effects-tests-run! (fn () {:failures mef-failures :total (+ mef-pass mef-fail) :passed mef-pass :failed mef-fail}))