module Rule where

import Data.List
import Term

type Rule = (Term, Term)

show_rule :: Rule -> String
show_rule (l, r) = show l ++ " -> " ++ show r

size :: Rule -> Int
size (l, r) = Term.size l + Term.size r

subset :: Eq a => [a] -> [a] -> Bool
subset xs ys = all p xs
  where p x = elem x ys

well_formed :: Rule -> Bool
well_formed (l@(F _ _), r) = subset (Term.variables r) (Term.variables l)
well_formed _ = False

-- Var(l -> r) = Var(l) cup Var(r)
variables :: Rule -> [String]
variables (l, r) = union (Term.variables l) (Term.variables r)

-- Fun(l -> r) = Fun(l) cup Fun(r)
functions :: Rule -> [String]
functions (l, r) = union (Term.functions l) (Term.functions r)

signature_of :: Rule -> Signature
signature_of (l, r) = union (Term.signature_of l) (Term.signature_of r) 

substitute :: Rule -> Subst -> Rule
substitute (l, r) sigma =
  (Term.substitute l sigma, Term.substitute r sigma)

rename :: String -> Int -> Rule -> Rule
rename x k (l, r) = (Term.substitute l sigma, Term.substitute r sigma)
  where
    ys = union (Term.variables l) (Term.variables r)
    sigma = [ (y, V (x ++ show i)) | (y, i) <- zip ys [k :: Int ..] ]

subsume :: Rule -> Rule -> Bool
subsume (l1, r1) (l2, r2) = Term.subsume (F "" [l1,r1]) (F "" [l2,r2]) 

variant :: Rule -> Rule -> Bool
variant rule1 rule2 =
  Rule.subsume rule1 rule2 &&
  Rule.subsume rule2 rule1

left_linear :: Rule -> Bool
left_linear (l, _) = Term.linear l

non_left_linear :: Rule -> Bool
non_left_linear rule = not (Rule.left_linear rule)
