@@ -4,39 +4,58 @@ module Transformer where
4
4
5
5
import Prelude hiding (lookup )
6
6
import Parser (Term (Variable , Application , Abstraction ))
7
- import Data.Map (Map , member , lookup , insert , size )
7
+ import Data.Map (Map , member , lookup , insert , size , foldrWithKey , findMin , keys , empty )
8
8
import Data.List (elemIndex , union )
9
+ import Data.Char (chr , ord )
9
10
10
11
data NamelessTerm
11
12
= NamelessVariable Int
12
13
| NamelessApplication NamelessTerm NamelessTerm
13
- | NamelessAbstraction Int NamelessTerm
14
+ | NamelessAbstraction NamelessTerm
14
15
deriving (Show )
15
16
16
17
type NamingContext = Map Char Int
17
- type BoundVariable = [Char ]
18
+ type BoundVariables = [Char ]
18
19
19
- toNameless :: Term -> Int -> BoundVariable -> NamingContext -> (NamelessTerm , NamingContext )
20
- toNameless (Variable var) depth bv context = case var `elemIndex` bv of
20
+ toNamelessWithContext :: Term -> Int -> BoundVariables -> NamingContext -> (NamelessTerm , NamingContext )
21
+ toNamelessWithContext (Variable var) depth bv context = case var `elemIndex` bv of
21
22
Nothing -> case lookup var context of
22
23
Nothing -> let index = size context
23
24
in (NamelessVariable (index + depth), insert var index context)
24
25
Just index -> (NamelessVariable (index + depth), context)
25
26
Just index -> (NamelessVariable index, context)
26
27
27
- toNameless (Application lhs rhs) depth bv context =
28
- let namelessLhs = toNameless lhs depth bv context
29
- namelessRhs = toNameless rhs depth bv (snd namelessLhs)
28
+ toNamelessWithContext (Application lhs rhs) depth bv context =
29
+ let namelessLhs = toNamelessWithContext lhs depth bv context
30
+ namelessRhs = toNamelessWithContext rhs depth bv (snd namelessLhs)
30
31
in (NamelessApplication (fst namelessLhs) (fst namelessRhs), snd namelessRhs)
31
32
32
- toNameless (Abstraction argument body) depth bv context =
33
- let namelessBody = toNameless body (depth + 1 ) (insertBoundVariable argument bv) context
34
- in (NamelessAbstraction depth (fst namelessBody), snd namelessBody)
33
+ toNamelessWithContext (Abstraction argument body) depth bv context =
34
+ let namelessBody = toNamelessWithContext body (depth + 1 ) (insertBoundVariable argument bv) context
35
+ in (NamelessAbstraction (fst namelessBody), snd namelessBody)
35
36
where insertBoundVariable var bv = if var `elem` bv then bv else var: bv
36
37
37
- -- a = Abstraction 'y' (Application (Variable 'x') (Application (Variable 'y') (Abstraction 'x' (Variable 'x'))))
38
- -- /x -> xy => Abstraction x (Application (Variable x) (Variable y))
39
- -- /01 => NamelessAbstraction 1 (NamelessApplication (Variable 0) (Variable 1))
40
-
41
- -- /y -> xy/x -> x => /10/0
42
- -- (NamelessAbstraction (NamelessApplication (NamelessVariable 1) (NamelessApplication (NamelessVariable 0) (NamelessAbstraction (NamelessVariable 1))))
38
+ toNameless :: Term -> (NamelessTerm , NamingContext )
39
+ toNameless term = toNamelessWithContext term 0 [] empty
40
+
41
+ toNamedWithContext :: NamelessTerm -> BoundVariables -> NamingContext -> Term
42
+ toNamedWithContext (NamelessVariable var) bv context
43
+ | var >= length bv = Variable $ findKey (var - length bv) context
44
+ | otherwise = Variable (bv !! var)
45
+ toNamedWithContext (NamelessApplication lhs rhs) bv context =
46
+ Application (toNamedWithContext lhs bv context) (toNamedWithContext rhs bv context)
47
+ toNamedWithContext (NamelessAbstraction body) bv context = let updatedBoundVariables = extendBoundVariables bv
48
+ in Abstraction (head updatedBoundVariables) (toNamedWithContext body updatedBoundVariables context)
49
+ where extendBoundVariables :: BoundVariables -> BoundVariables
50
+ extendBoundVariables [] = if ' a' `member` context then [nextVariable ' a' context] else " a"
51
+ extendBoundVariables bv@ (x: _) = nextVariable x context: bv
52
+
53
+ toNamed :: NamelessTerm -> NamingContext -> Term
54
+ toNamed term = toNamedWithContext term []
55
+
56
+ findKey :: Eq v => v -> Map k v -> k
57
+ findKey value map = foldrWithKey (\ k v res -> if v == value then k else res) (fst $ findMin map ) map
58
+
59
+ nextVariable :: Char -> NamingContext -> Char
60
+ nextVariable var context = let next = chr $ ord var + 1
61
+ in if next `member` context then nextVariable next context else next
0 commit comments