;; lib/mod/tests/disjunction.sx — Ext 15: disjunctive (:any) conditions. (define mod-or-count 0) (define mod-or-pass 0) (define mod-or-fail 0) (define mod-or-failures (list)) (define mod-or-test! (fn (name got expected) (begin (set! mod-or-count (+ mod-or-count 1)) (if (= got expected) (set! mod-or-pass (+ mod-or-pass 1)) (begin (set! mod-or-fail (+ mod-or-fail 1)) (append! mod-or-failures (str name "\n expected: " expected "\n got: " got))))))) ;; one rule, OR of two classifications → one action covers both (define mod-or-rules (list (mod/mk-rule "spam-or-abuse-hide" :hide (list (list :any (list (list :classification "spam") (list :classification "abuse"))))) (mod/mk-rule "default-keep" :keep (list)))) (define mod-or-spam (mod/mk-report "r1" "a" "b" "this is spam")) (define mod-or-abuse (mod/mk-report "r2" "a" "b" "harassment here")) (define mod-or-clean (mod/mk-report "r3" "a" "b" "a fine post")) (mod-or-test! "OR: spam branch → hide" (get (mod/decide-report mod-or-spam (list mod-or-spam) mod-or-rules) :action) "hide") (mod-or-test! "OR: abuse branch → hide" (get (mod/decide-report mod-or-abuse (list mod-or-abuse) mod-or-rules) :action) "hide") (mod-or-test! "OR: neither branch → keep" (get (mod/decide-report mod-or-clean (list mod-or-clean) mod-or-rules) :action) "keep") ;; ── goal text + proof ── (mod-or-test! "cond->goal :any joins with ;" (mod/cond->goal (list :any (list (list :classification "spam") (list :classification "abuse"))) "Id") "(classification(Id, spam) ; classification(Id, abuse))") (define mod-or-dec (mod/decide-report mod-or-spam (list mod-or-spam) mod-or-rules)) (mod-or-test! "OR proof goal solved" (get (first (get (get mod-or-dec :proof) :goals)) :solved) true) (mod-or-test! "OR proof goal text" (get (first (get (get mod-or-dec :proof) :goals)) :goal) "(classification(r1, spam) ; classification(r1, abuse))") ;; ── :any composes with :not (NOR-ish) and :attr ── (define mod-or-mixed-rules (list (mod/mk-rule "spam-or-flagged-hide" :hide (list (list :any (list (list :classification "spam") (list :attr "flagged"))))) (mod/mk-rule "default-keep" :keep (list)))) (define mod-or-flagged (mod/attach-attr (mod/mk-report "r4" "a" "b" "a fine post") "flagged")) (mod-or-test! "OR over classification|attr: flagged clean post → hide" (get (mod/decide-report mod-or-flagged (list mod-or-flagged) mod-or-mixed-rules) :action) "hide") (mod-or-test! "cond->goal :any with :not branch" (mod/cond->goal (list :any (list (list :classification "spam") (list :not (list :attr "verified")))) "Id") "(classification(Id, spam) ; not(attr(Id, verified)))") ;; AND still works alongside OR in the same :when list (define mod-or-and-rules (list (mod/mk-rule "spam-and-not-verified" :hide (list (list :any (list (list :classification "spam") (list :classification "abuse"))) (list :not (list :attr "verified")))) (mod/mk-rule "default-keep" :keep (list)))) (define mod-or-spam-verified (mod/attach-attr (mod/mk-report "r5" "a" "b" "this is spam") "verified")) (mod-or-test! "AND of OR + NOT: verified spam → keep" (get (mod/decide-report mod-or-spam-verified (list mod-or-spam-verified) mod-or-and-rules) :action) "keep") (mod-or-test! "AND of OR + NOT: unverified abuse → hide" (get (mod/decide-report mod-or-abuse (list mod-or-abuse) mod-or-and-rules) :action) "hide") (define mod-disjunction-tests-run! (fn () {:failures mod-or-failures :total mod-or-count :passed mod-or-pass :failed mod-or-fail}))