Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
lib/maude/strategy.sx — first-class set-valued strategies: idle/fail/all/ rule/seq/alt/star/plus/bang/name combinators, named-strategy env. Same rule set computes different things under different strategies; verified with single-rule vs all vs seq-order vs alt vs star vs bang. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
218 lines
6.3 KiB
Plaintext
218 lines
6.3 KiB
Plaintext
;; lib/maude/strategy.sx — strategy language (Phase 6).
|
|
;;
|
|
;; A strategy controls HOW rules are applied. Strategies are first-class values
|
|
;; (tagged dicts) and SET-VALUED: applying a strategy to a term yields the set
|
|
;; (deduped by canonical form) of result terms. The same rule set under
|
|
;; different strategies computes different things — `;` sequences, `|` unions,
|
|
;; `*`/`+` iterate, `!` normalises.
|
|
;;
|
|
;; Constructors:
|
|
;; (mau/s-idle) identity (the term itself)
|
|
;; (mau/s-fail) empty set
|
|
;; (mau/s-all) apply any rule once, anywhere
|
|
;; (mau/s-rule LABEL) apply a named rule once, anywhere
|
|
;; (mau/s-seq A B) A ; B (apply B to every result of A)
|
|
;; (mau/s-alt A B) A | B (union of results)
|
|
;; (mau/s-star A) A * (reflexive-transitive closure)
|
|
;; (mau/s-plus A) A + (one or more)
|
|
;; (mau/s-bang A) A ! (normal forms: results where A can't apply)
|
|
;; (mau/s-name N) look up named strategy N in the env
|
|
;;
|
|
;; Run with (mau/srun M STRATS STRAT SRC): STRATS is a dict NAME -> strategy.
|
|
|
|
(define mau/s-idle (fn () {:s :idle}))
|
|
(define mau/s-fail (fn () {:s :fail}))
|
|
(define mau/s-all (fn () {:s :all}))
|
|
(define mau/s-rule (fn (label) {:label label :s :rule}))
|
|
(define mau/s-seq (fn (a b) {:a a :b b :s :seq}))
|
|
(define mau/s-alt (fn (a b) {:a a :b b :s :alt}))
|
|
(define mau/s-star (fn (a) {:a a :s :star}))
|
|
(define mau/s-plus (fn (a) {:a a :s :plus}))
|
|
(define mau/s-bang (fn (a) {:a a :s :bang}))
|
|
(define mau/s-name (fn (n) {:n n :s :name}))
|
|
|
|
(define
|
|
mau/rules-with-label
|
|
(fn (rules label) (filter (fn (r) (= (get r :label) label)) rules)))
|
|
|
|
(define
|
|
mau/dedup-loop
|
|
(fn
|
|
(theory ts seen acc)
|
|
(if
|
|
(empty? ts)
|
|
acc
|
|
(let
|
|
((c (mau/canon theory (first ts))))
|
|
(if
|
|
(mau/member? c seen)
|
|
(mau/dedup-loop theory (rest ts) seen acc)
|
|
(mau/dedup-loop
|
|
theory
|
|
(rest ts)
|
|
(cons c seen)
|
|
(mau/append2 acc (list (first ts)))))))))
|
|
|
|
(define
|
|
mau/dedup-canon
|
|
(fn (theory ts) (mau/dedup-loop theory ts (list) (list))))
|
|
|
|
;; ---- strategy interpreter ----
|
|
|
|
(define
|
|
mau/sapply
|
|
(fn
|
|
(ctx strat term)
|
|
(let
|
|
((k (get strat :s)) (theory (get ctx :theory)))
|
|
(cond
|
|
((= k "idle") (list term))
|
|
((= k "fail") (list))
|
|
((= k "all")
|
|
(mau/dedup-canon
|
|
theory
|
|
(mau/all-successors theory (get ctx :eqs) (get ctx :rules) term)))
|
|
((= k "rule")
|
|
(mau/dedup-canon
|
|
theory
|
|
(mau/all-successors
|
|
theory
|
|
(get ctx :eqs)
|
|
(mau/rules-with-label (get ctx :rules) (get strat :label))
|
|
term)))
|
|
((= k "seq")
|
|
(mau/dedup-canon
|
|
theory
|
|
(mau/concat-map
|
|
(fn (t) (mau/sapply ctx (get strat :b) t))
|
|
(mau/sapply ctx (get strat :a) term))))
|
|
((= k "alt")
|
|
(mau/dedup-canon
|
|
theory
|
|
(mau/append2
|
|
(mau/sapply ctx (get strat :a) term)
|
|
(mau/sapply ctx (get strat :b) term))))
|
|
((= k "star") (mau/sstar ctx (get strat :a) term))
|
|
((= k "plus")
|
|
(mau/dedup-canon
|
|
theory
|
|
(mau/concat-map
|
|
(fn (t) (mau/sstar ctx (get strat :a) t))
|
|
(mau/sapply ctx (get strat :a) term))))
|
|
((= k "bang")
|
|
(mau/dedup-canon theory (mau/sbang ctx (get strat :a) term)))
|
|
((= k "name")
|
|
(mau/sapply ctx (get (get ctx :strats) (get strat :n)) term))
|
|
(else (list))))))
|
|
|
|
;; reflexive-transitive closure: term plus everything reachable via A
|
|
(define
|
|
mau/sstar
|
|
(fn
|
|
(ctx a term)
|
|
(mau/sstar-loop
|
|
ctx
|
|
a
|
|
(list term)
|
|
(list (mau/canon (get ctx :theory) term))
|
|
(list term))))
|
|
|
|
(define
|
|
mau/sstar-loop
|
|
(fn
|
|
(ctx a frontier seen acc)
|
|
(if
|
|
(empty? frontier)
|
|
acc
|
|
(let
|
|
((newf (list))
|
|
(newseen seen)
|
|
(newacc acc)
|
|
(theory (get ctx :theory)))
|
|
(for-each
|
|
(fn
|
|
(t)
|
|
(for-each
|
|
(fn
|
|
(succ)
|
|
(let
|
|
((c (mau/canon theory succ)))
|
|
(when
|
|
(not (mau/member? c newseen))
|
|
(do
|
|
(set! newseen (cons c newseen))
|
|
(append! newf succ)
|
|
(append! newacc succ)))))
|
|
(mau/sapply ctx a t)))
|
|
frontier)
|
|
(mau/sstar-loop ctx a newf newseen newacc)))))
|
|
|
|
;; normal forms: terms reachable via A where A yields nothing more
|
|
(define
|
|
mau/sbang
|
|
(fn
|
|
(ctx a term)
|
|
(mau/sbang-loop
|
|
ctx
|
|
a
|
|
(list term)
|
|
(list (mau/canon (get ctx :theory) term))
|
|
(list))))
|
|
|
|
(define
|
|
mau/sbang-loop
|
|
(fn
|
|
(ctx a frontier seen acc)
|
|
(if
|
|
(empty? frontier)
|
|
acc
|
|
(let
|
|
((newf (list))
|
|
(newseen seen)
|
|
(newacc acc)
|
|
(theory (get ctx :theory)))
|
|
(for-each
|
|
(fn
|
|
(t)
|
|
(let
|
|
((succs (mau/sapply ctx a t)))
|
|
(if
|
|
(empty? succs)
|
|
(append! newacc t)
|
|
(for-each
|
|
(fn
|
|
(succ)
|
|
(let
|
|
((c (mau/canon theory succ)))
|
|
(when
|
|
(not (mau/member? c newseen))
|
|
(do
|
|
(set! newseen (cons c newseen))
|
|
(append! newf succ)))))
|
|
succs))))
|
|
frontier)
|
|
(mau/sbang-loop ctx a newf newseen newacc)))))
|
|
|
|
;; ---- public API ----
|
|
|
|
(define mau/make-sctx (fn (m strats) {:eqs (mau/module-eqs m) :theory (mau/build-theory m) :strats strats :rules (mau/module-rules m)}))
|
|
|
|
(define
|
|
mau/srun
|
|
(fn
|
|
(m strats strat src)
|
|
(let
|
|
((ctx (mau/make-sctx m strats)))
|
|
(let
|
|
((t0 (mau/cnormalize (get ctx :theory) (get ctx :eqs) (mau/parse-term-in m src) mau/reduce-fuel)))
|
|
(mau/dedup-canon (get ctx :theory) (mau/sapply ctx strat t0))))))
|
|
|
|
(define
|
|
mau/srun-canon
|
|
(fn
|
|
(m strats strat src)
|
|
(let
|
|
((theory (mau/build-theory m)))
|
|
(mau/sort-strings
|
|
(map (fn (t) (mau/canon theory t)) (mau/srun m strats strat src))))))
|