1
+ -- | Module RecType defines routines for working with recursive data types.
1
2
module RecType
2
3
(
3
4
recursiveMembersToPointers ,
@@ -24,49 +25,54 @@ import Concretize
24
25
import ToTemplate
25
26
import Validate
26
27
28
+ -- | Returns true if a type candidate is recursive.
29
+ isRecursive :: TypeCandidate -> Bool
30
+ isRecursive candidate =
31
+ let memberTypes = concat $ map snd (typemembers candidate)
32
+ vars = variables candidate
33
+ name = typename candidate
34
+ in any (check name vars) memberTypes
35
+ where check :: String -> [Ty ] -> Ty -> Bool
36
+ check name vars t = isDirectRecursion name vars t || isIndirectRecursion name vars t
37
+
38
+ isDirectRecursion :: String -> [Ty ] -> Ty -> Bool
39
+ isDirectRecursion name vars (StructTy (ConcreteNameTy (SymPath [] n)) rest) =
40
+ (n == name && vars == rest)
41
+ isDirectRecursion name vars (RecTy t) = isDirectRecursion name vars t
42
+ isDirectRecursion _ _ _ = False
43
+
44
+ isIndirectRecursion :: String -> [Ty ] -> Ty -> Bool
45
+ isIndirectRecursion name vars t@ (StructTy _ rest) =
46
+ not (isDirectRecursion name vars t) && any (isDirectRecursion name vars) rest
47
+ isIndirectRecursion name vars (PointerTy t) = isDirectRecursion name vars t
48
+ isIndirectRecursion name vars (RefTy t _) = isDirectRecursion name vars t
49
+ isIndirectRecursion _ _ _ = False
50
+
27
51
--------------------------------------------------------------------------------
28
52
-- Base indirection recursion
29
53
30
54
-- | Returns true if a candidate type definition is a valid instance of recursivity.
31
55
-- Types have valid recursion if they refer to themselves through indirection.
32
56
okRecursive :: TypeCandidate -> Either TypeError ()
33
57
okRecursive candidate =
34
- if any go (typemembers candidate)
35
- then validateInterfaceConstraints (candidate { interfaceConstraints = concat $ map go' (typemembers candidate)})
36
- else Right ()
37
- where go :: XObj -> Bool
38
- go (XObj (Sym (SymPath _ name) _) _ _) = name == typename candidate
39
- go (XObj (Lst xs) _ _) = any go xs
40
- go _ = False
41
- go' x@ (XObj (Lst _) _ _) = if go x
42
- then case xobjToTy x of
43
- Just t@ (PointerTy _) -> recInterfaceConstraints t
44
- Just t@ (RefTy _ _) -> recInterfaceConstraints t
45
- Just t@ (StructTy _ [_]) -> recInterfaceConstraints t
46
- _ -> []
47
- else []
48
- go' _ = []
58
+ let name = typename candidate
59
+ vars = variables candidate
60
+ memberTypes = concat $ map snd (typemembers candidate)
61
+ recursives = (filter (isIndirectRecursion name vars) memberTypes)
62
+ ty = StructTy (ConcreteNameTy (SymPath [] name)) vars
63
+ constraints = map (recInterfaceConstraints ty) recursives
64
+ in validateInterfaceConstraints (candidate {interfaceConstraints = concat constraints})
49
65
50
66
-- | Generates interface constraints for a recursive type.
51
67
-- The recursive portion of recursive types must be wrapped in a type F that supports indirection.
52
68
-- We enforce this with two interfaces:
53
69
-- allocate: Heap allocates a value T and wraps it in type F<T>
54
70
-- indirect: Returns T from a heap allocated F<T>
55
- recInterfaceConstraints :: Ty -> [InterfaceConstraint ]
56
- recInterfaceConstraints t =
57
- let members = tyMembers t
58
- in case members of
59
- [] -> []
60
- _ -> [ InterfaceConstraint " indirect" [(FuncTy [t] (head members) StaticLifetimeTy )],
61
- InterfaceConstraint " alloc" [(FuncTy [(head members)] t StaticLifetimeTy )]
62
- ]
63
-
64
- -- | Returns true if a type member xobj is recursive (either through indirect recursion or "value" recursion)
65
- isRecursive :: Ty -> XObj -> Bool
66
- isRecursive (StructTy (ConcreteNameTy spath) [] ) (XObj (Sym path _) _ _) = spath == path
67
- isRecursive rec (XObj (Lst xs) _ _) = any (isRecursive rec ) xs
68
- isRecursive rec (XObj (Arr xs) _ _) = any (isRecursive rec ) xs
69
- isRecursive _ _ = False
71
+ recInterfaceConstraints :: Ty -> Ty -> [InterfaceConstraint ]
72
+ recInterfaceConstraints recTy t =
73
+ [ InterfaceConstraint " indirect" [(FuncTy [t] recTy StaticLifetimeTy )],
74
+ InterfaceConstraint " alloc" [(FuncTy [recTy] t StaticLifetimeTy )]
75
+ ]
70
76
71
77
--------------------------------------------------------------------------------
72
78
-- **Value recursion sugar**
0 commit comments