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]))
|