| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
 | 
module TRS where
import Data.List
import Names ( genCorrectIdentifier )
data Term = Var Int | Func FuncType String [Term]
data FuncType = Def | Cons
 deriving Eq
func = Func Def
cons = Func Cons
varsOf :: Term -> [Int]
varsOf (Var v) = [v]
varsOf (Func _ f args)
  | f == "LAMBDA" = let (largs,lexp) = splitAt (length args - 1) args
                     in varsOf (head lexp) \\ concatMap varsOf largs
  | f == "LET"
   = let (bindings,lexp) = splitAt (length args - 1) args
         bvars = concatMap (\ (Func _ _ [bvar,_]) -> varsOf bvar) bindings
      in varsOf (head lexp) \\ bvars
  | otherwise = foldr union [] (map varsOf args)
fSubterms :: Term -> [(String,[Term])]
fSubterms (Var _) = []
fSubterms (Func ft f args) = let argterms = concatMap fSubterms args in
  if ft==Def then (f,args) : argterms else argterms
funcsInTerm :: Term -> [String]
funcsInTerm (Var _) = []
funcsInTerm (Func ft f args) = let argfuns = concatMap funcsInTerm args in
  if ft==Def then f : argfuns else argfuns
showBasicTerm :: Bool -> Term -> String
showBasicTerm _ (Var i) = 'x' : show i
showBasicTerm _ (Func _ f []) = showOperator f
showBasicTerm withp (Func _ f [x]) =
  encloseInPar withp (showOperator f ++ ' ':showBasicTerm True x)
showBasicTerm withp (Func _ f args@(_:_:_))
  | f == "LET"    = encloseInPar withp ("let\n" ++ showLetExp args)
  | f == "LAMBDA" = encloseInPar withp (showLambdaExp args)
  | take 2 f == "(,"
   = '(' : intercalate "," (map (showBasicTerm False) args) ++ ")"
  | not (isAlpha (head f)) && length args == 2
   = encloseInPar withp
                  (showBasicTerm True (head args) ++ ' ':f ++
                     ' ':showBasicTerm True (args!!1))
  | otherwise
   = encloseInPar withp (showOperator f ++
                         concatMap (\a -> ' ':showBasicTerm True a) args)
showLetExp es = let (bindings,exp) = splitAt (length es - 1) es in
  concatMap showBinding bindings ++
  " in " ++ showBasicTerm False (head exp)
 where
  showBinding (Func _ _ [bvar,bexp]) =
    "  "++ showBasicTerm False bvar ++" = "++ showBasicTerm False bexp ++"\n"
showLambdaExp es = let (args,exp) = splitAt (length es - 1) es in
  "\\" ++ concatMap (\a -> showBasicTerm True a ++" ") args ++
  "-> " ++ showBasicTerm False (head exp)
showOperator f | isDigit (head f)  = f
               | head f == '\''    = f
               | f == "[]"         = f
               | isAlpha (head cf) = cf
               | otherwise         = '(':cf++")"
 where cf = genCorrectIdentifier f
encloseInPar withp s = if withp then '(' : s ++ ")" else s
data Rule = Rule String [Term] Term
showRule :: Rule -> String
showRule (Rule f args rhs) =
  showBasicTerm False (Func Def f args) ++ " = " ++ showBasicTerm False rhs ++
  if null extraVars then ""
  else " where " ++
       intercalate "," (map (\i -> showBasicTerm False (Var i)) extraVars) ++
       " free"
 where
  extraVars = varsOf rhs \\ concatMap varsOf args
showTRS :: [Rule] -> String
showTRS = intercalate "\n" . map showRule . filter isShowRule
 where
   isShowRule (Rule f _ _) = f `notElem` ["?"]
allFunctions :: [Rule] -> [(String,Int)]
allFunctions rules = nub (map funOf rules)
 where funOf (Rule rf args _) = (rf,length args)
funcRules :: String -> [Rule] -> [([Term],Term)]
funcRules _ [] = []
funcRules f (Rule rf args rhs : rules) =
    if f==rf then (args,rhs) : funcRules f rules
             else funcRules f rules
arityOf :: String -> [Rule] -> Int
arityOf f [] = error $ "arity of function "++f++" not found"
arityOf f (Rule rf args _ : rules) =
  if f==rf then length args
           else arityOf f rules
containsChoice :: Rule -> Bool
containsChoice (Rule _ _ rhs) = hasChoice rhs
 where
  hasChoice (Var _) = False
  hasChoice (Func ft f args) = (ft==Def && f=="?") || any hasChoice args
addChoiceRules :: [Rule] -> [Rule]
addChoiceRules rules =
  if ("?",2) `elem` allFunctions rules
  then rules
  else Rule "?" [Var 0, Var 1] (Var 0) :
       Rule "?" [Var 0, Var 1] (Var 1) : rules
containsApply :: Rule -> Bool
containsApply (Rule _ _ rhs) = hasApply rhs
 where
  hasApply (Var _) = False
  hasApply (Func ft f args) = (ft==Def && f=="apply") || any hasApply args
addApplyRules :: [Rule] -> [Rule]
addApplyRules rules = rules ++ concatMap genAllApply funcArities
 where
  funcArities = nub (map (\ (Rule f args _) -> (f,length args)) rules)
  genAllApply (f,n) = map genApplyRule [1..n]
   where
    genApplyRule i =
     let pargs = map Var [1..(i-1)]
      in Rule "apply" [Func Cons f pargs, Var i]
              (Func (if i==n then Def else Cons) f (pargs++[Var i]))
 |