1+ -- | Module RecType defines routines for working with recursive data types.
12module RecType
23 (
34 recursiveMembersToPointers ,
@@ -24,49 +25,54 @@ import Concretize
2425import ToTemplate
2526import Validate
2627
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+
2751--------------------------------------------------------------------------------
2852-- Base indirection recursion
2953
3054-- | Returns true if a candidate type definition is a valid instance of recursivity.
3155-- Types have valid recursion if they refer to themselves through indirection.
3256okRecursive :: TypeCandidate -> Either TypeError ()
3357okRecursive 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})
4965
5066-- | Generates interface constraints for a recursive type.
5167-- The recursive portion of recursive types must be wrapped in a type F that supports indirection.
5268-- We enforce this with two interfaces:
5369-- allocate: Heap allocates a value T and wraps it in type F<T>
5470-- 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+ ]
7076
7177--------------------------------------------------------------------------------
7278-- **Value recursion sugar**
0 commit comments