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
-- Reading rules from an (Flat)Curry file:

module ReadFlatTRS(readRules,readRulesAndData,readFlatCurryRules) where

import qualified TRS
import FlatCurry.Types as FC
import FlatCurry.Files (readFlatCurry)
import OrCaseLifter

----------------------------------------------------------------------------
-- Reading rules from a (Flat)Curry file:
readRules :: String -> IO [TRS.Rule]
readRules prog = do
  putStrLn $ "Reading rules from Curry program " ++ prog ++ "..."
  flatprog <- readFlatCurry prog
  return (fst (curry2rules flatprog))

-- Reading rules and data declarations from a (Flat)Curry file:
readRulesAndData :: String -> IO ([TRS.Rule],[TypeDecl])
readRulesAndData prog = do
  putStrLn $ "Reading rules from Curry program " ++ prog ++ "..."
  flatprog <- readFlatCurry prog
  return (curry2rules flatprog)

-- Read FlatCurry program and return it together with the rules
-- transformed into a TRS:
readFlatCurryRules :: String -> IO (Prog,[TRS.Rule])
readFlatCurryRules prog = do
  putStrLn $ "Reading rules from Curry program " ++ prog ++ "..."
  flatprog <- readFlatCurry prog
  return (flatprog, fst $ curry2rules flatprog)

curry2rules (Prog modname _ tdecls fdecls _) =
  if any TRS.containsApply crules
  then (TRS.addApplyRules crules, tdecls)
  else (crules, tdecls)
 where
  rules  = concatMap fdecl2rules (liftNestedOrCase (modname,"ORCASE_") fdecls)
  crules = if any TRS.containsChoice rules then TRS.addChoiceRules rules
                                           else rules

-- translate function declaration into rules:
fdecl2rules (FC.Func (_,fname) arity _ _ (External _)) =
  [TRS.Rule fname (genArgs arity) (TRS.Func TRS.Def "EXTERNAL" [])]
 where
  genArgs n = map TRS.Var [1..n]

fdecl2rules (FC.Func fname _ _ _ (FC.Rule lhs rhs)) =
  map patternrule2rule patternrules
 where
  patternrules = rule2equations (Comb FuncCall fname (map Var lhs)) rhs

  patternrule2rule (l,r) =
    let (TRS.Func _ f args) = transExp l
     in TRS.Rule f args (transExp r)

  transExp (FC.Var i) = TRS.Var i
  transExp (Lit (Intc i))   = TRS.Func TRS.Cons (show i) []
  transExp (Lit (Floatc f)) = TRS.Func TRS.Cons (show f) []
  transExp (Lit (Charc c))  = TRS.Func TRS.Cons ['\'',c,'\''] []
  transExp (Comb ct (_,f) args) =
    TRS.Func (if ct==FuncCall then TRS.Def else TRS.Cons) f (map transExp args)
  transExp (Free _ exp) = transExp exp
  transExp (Let _ _)    = error "Let not yet supported"
  transExp (FC.Or _ _)  = error "Or not yet supported"
  transExp (Case _ _ _) = error "Case not yet supported"

----------------------------------------------------------------------------

-- transform a rule consisting of a left- and a right-hand side
-- (represented as expressions) into a set of pattern matching rules:
rule2equations :: Expr -> Expr -> [(Expr,Expr)]
rule2equations lhs (FC.Or e1 e2) =
   rule2equations lhs e1 ++ rule2equations lhs e2
rule2equations lhs (Case ctype e bs) =
   if isVarExpr e then let Var i = e  in  caseIntoLhs lhs i bs
                  else [(lhs,Case ctype e bs)]
rule2equations lhs (Var i) = [(lhs,Var i)]
rule2equations lhs (Lit l) = [(lhs,Lit l)]
rule2equations lhs (Comb ct name args) = [(lhs,Comb ct name args)]
rule2equations lhs (Free vs e) = [(lhs,Free vs e)]
rule2equations lhs (Let bs e) = [(lhs,Let bs e)]

caseIntoLhs _ _ [] = []
caseIntoLhs lhs vi (Branch (Pattern c vs) e : bs) =
  rule2equations (substitute [vi] [shallowPattern2Expr c vs] lhs) e
  ++ caseIntoLhs lhs vi bs
caseIntoLhs lhs vi (Branch (LPattern lit) e : bs) =
  rule2equations (substitute [vi] [Lit lit] lhs) e
  ++ caseIntoLhs lhs vi bs

shallowPattern2Expr name vars = Comb ConsCall name (map (\i->Var i) vars)


-- (substitute vars exps expr) = expr[vars/exps]
-- i.e., replace all occurrences of vars by corresponding exps in the
-- expression expr
substitute vars exps expr = substituteAll vars exps 0 expr

-- (substituteAll vars exps base expr):
-- substitute all occurrences of variables by corresonding expressions:
-- * substitute all occurrences of var_i by exp_i in expr
--   (if vars=[var_1,...,var_n] and exps=[exp_1,...,exp_n])
-- * substitute all other variables (Var j) by (Var (base+j))
--
-- here we assume that the new variables in guards and case patterns
-- do not occur in the list "vars" of replaced variables!

substituteAll :: [Int] -> [Expr] -> Int -> Expr -> Expr
substituteAll vars exps b (Var i) = replaceVar vars exps i
  where replaceVar [] [] var = Var (b+var)
        replaceVar (v:vs) (e:es) var = if v==var then e
                                                 else replaceVar vs es var
substituteAll _  _  _ (Lit l) = Lit l
substituteAll vs es b (Comb combtype c exps) =
                 Comb combtype c (map (substituteAll vs es b) exps)
substituteAll vs es b (Let bindings exp) =
                 Let (map (\(x,e)->(x+b,substituteAll vs es b e)) bindings)
                     (substituteAll vs es b exp)
substituteAll vs es b (Free vars e) =
                 Free (map (+b) vars) (substituteAll vs es b e)
substituteAll vs es b (FC.Or e1 e2) =
                 FC.Or (substituteAll vs es b e1) (substituteAll vs es b e2)
substituteAll vs es b (Case ctype e cases) =
   Case ctype (substituteAll vs es b e) (map (substituteAllCase vs es b) cases)

substituteAllCase vs es b (Branch (Pattern l pvs) e) =
                 Branch (Pattern l (map (+b) pvs)) (substituteAll vs es b e)
substituteAllCase vs es b (Branch (LPattern l) e) =
                 Branch (LPattern l) (substituteAll vs es b e)


-- Is the expression a guarded expressions?
isGuardedExpr :: Expr -> Bool
isGuardedExpr e = case e of
  Comb _ f _ -> f == ("Prelude","cond")
  _ -> False

-- Is the expression a variable?
isVarExpr :: Expr -> Bool
isVarExpr e = case e of
  Var _ -> True
  _ -> False


---------------------------------------------------------------------------