@@ -18,60 +18,79 @@ data TypeVarRestriction
18
18
| AllowOnlyNamesInScope -- Used when checking a type definition, e.g. (deftype (Foo a) [x a]), requires a to be in scope
19
19
deriving (Eq )
20
20
21
+ -- | TypeCandidate represents a type that's possibly valid or invalid.
22
+ data TypeCandidate = TypeCandidate {
23
+ -- the name of the type
24
+ typename :: String ,
25
+ -- a list of all variables in the type head
26
+ variables :: [Ty ],
27
+ -- all members of the type
28
+ typemembers :: [XObj ],
29
+ -- what sort of type variables are permitted.
30
+ restriction :: TypeVarRestriction
31
+ }
32
+
21
33
-- | Make sure that the member declarations in a type definition
22
34
-- | Follow the pattern [<name> <type>, <name> <type>, ...]
23
35
-- | TODO: This function is only called by the deftype parts of the codebase, which is more specific than the following check implies.
24
- validateMemberCases :: TypeEnv -> Env -> [Ty ] -> [XObj ] -> Either TypeError ()
25
- validateMemberCases typeEnv globalEnv typeVariables rest = mapM_ visit rest
36
+ validateMemberCases :: TypeEnv -> Env -> TypeCandidate -> Either TypeError ()
37
+ validateMemberCases typeEnv globalEnv candidate = -- mapM_ visit (members candidate)
38
+ validateMembers typeEnv globalEnv (candidate {restriction = AllowOnlyNamesInScope })
39
+ -- where
40
+ -- visit (XObj (Arr membersXObjs) _ _) =
41
+ -- validateMembers typeEnv globalEnv (candidate {restriction = AllowOnlyNamesInScope})
42
+ -- visit xobj =
43
+ -- Left (InvalidSumtypeCase xobj)
44
+
45
+ validateMembers :: TypeEnv -> Env -> TypeCandidate -> Either TypeError ()
46
+ validateMembers typeEnv globalEnv candidate =
47
+ (checkUnevenMembers candidate) >>
48
+ (checkDuplicateMembers candidate) >>
49
+ (checkMembers typeEnv globalEnv candidate) >>
50
+ (checkKindConsistency candidate)
51
+
52
+ -- | Returns an error if a type has an uneven number of members.
53
+ checkUnevenMembers :: TypeCandidate -> Either TypeError ()
54
+ checkUnevenMembers candidate =
55
+ if even (length (typemembers candidate))
56
+ then Right ()
57
+ else Left (UnevenMembers (typemembers candidate))
58
+
59
+ -- | Returns an error if a type has more than one member with the same name.
60
+ checkDuplicateMembers :: TypeCandidate -> Either TypeError ()
61
+ checkDuplicateMembers candidate =
62
+ if length fields == length uniqueFields
63
+ then Right ()
64
+ else Left (DuplicatedMembers dups)
26
65
where
27
- visit (XObj (Arr membersXObjs) _ _) =
28
- validateMembers AllowOnlyNamesInScope typeEnv globalEnv typeVariables membersXObjs
29
- visit xobj =
30
- Left (InvalidSumtypeCase xobj)
66
+ fields = fst <$> (pairwise (typemembers candidate))
67
+ uniqueFields = nubBy ((==) `on` xobjObj) fields
68
+ dups = fields \\ uniqueFields
31
69
32
- validateMembers :: TypeVarRestriction -> TypeEnv -> Env -> [Ty ] -> [XObj ] -> Either TypeError ()
33
- validateMembers typeVarRestriction typeEnv globalEnv typeVariables membersXObjs =
34
- checkUnevenMembers >> checkDuplicateMembers >> checkMembers >> checkKindConsistency
70
+ -- | Returns an error if the type variables in the body of the type and variables in the head of the type are of incompatible kinds.
71
+ checkKindConsistency :: TypeCandidate -> Either TypeError ()
72
+ checkKindConsistency candidate =
73
+ case areKindsConsistent varsOnly of
74
+ Left var -> Left (InconsistentKinds var (typemembers candidate))
75
+ _ -> pure ()
35
76
where
36
- pairs = pairwise membersXObjs
37
- -- Are the number of members even?
38
- checkUnevenMembers :: Either TypeError ()
39
- checkUnevenMembers =
40
- if even (length membersXObjs)
41
- then Right ()
42
- else Left (UnevenMembers membersXObjs)
43
- -- Are any members duplicated?
44
- checkDuplicateMembers :: Either TypeError ()
45
- checkDuplicateMembers =
46
- if length fields == length uniqueFields
47
- then Right ()
48
- else Left (DuplicatedMembers dups)
49
- where
50
- fields = fst <$> pairs
51
- uniqueFields = nubBy ((==) `on` xobjObj) fields
52
- dups = fields \\ uniqueFields
53
- -- Do all type variables have consistent kinds?
54
- checkKindConsistency :: Either TypeError ()
55
- checkKindConsistency =
56
- case areKindsConsistent varsOnly of
57
- Left var -> Left (InconsistentKinds var membersXObjs)
58
- _ -> pure ()
59
- where
60
- -- fromJust is safe here; invalid types will be caught in the prior check.
61
- -- todo? be safer anyway?
62
- varsOnly = filter isTypeGeneric (map (fromJust . xobjToTy . snd ) pairs)
63
- checkMembers :: Either TypeError ()
64
- checkMembers = mapM_ (okXObjForType typeVarRestriction typeEnv globalEnv typeVariables . snd ) pairs
77
+ -- fromJust is safe here; invalid types will be caught in a prior check.
78
+ -- TODO: be safer.
79
+ varsOnly = filter isTypeGeneric (map (fromJust . xobjToTy . snd ) (pairwise (typemembers candidate)))
80
+
81
+ -- | Returns an error if one of the types members can't be used as a member.
82
+ checkMembers :: TypeEnv -> Env -> TypeCandidate -> Either TypeError ()
83
+ checkMembers typeEnv globalEnv candidate = mapM_ (okXObjForType (typename candidate) (restriction candidate) typeEnv globalEnv (variables candidate) . snd ) (pairwise (typemembers candidate))
65
84
66
- okXObjForType :: TypeVarRestriction -> TypeEnv -> Env -> [Ty ] -> XObj -> Either TypeError ()
67
- okXObjForType typeVarRestriction typeEnv globalEnv typeVariables xobj =
85
+ okXObjForType :: String -> TypeVarRestriction -> TypeEnv -> Env -> [Ty ] -> XObj -> Either TypeError ()
86
+ okXObjForType tyname typeVarRestriction typeEnv globalEnv typeVariables xobj =
68
87
case xobjToTy xobj of
69
- Just t -> canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables t xobj
88
+ Just t -> canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables t xobj
70
89
Nothing -> Left (NotAType xobj)
71
90
72
91
-- | Can this type be used as a member for a deftype?
73
- canBeUsedAsMemberType :: TypeVarRestriction -> TypeEnv -> Env -> [Ty ] -> Ty -> XObj -> Either TypeError ()
74
- canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables ty xobj =
92
+ canBeUsedAsMemberType :: String -> TypeVarRestriction -> TypeEnv -> Env -> [Ty ] -> Ty -> XObj -> Either TypeError ()
93
+ canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables ty xobj =
75
94
case ty of
76
95
UnitTy -> pure ()
77
96
IntTy -> pure ()
@@ -86,7 +105,7 @@ canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables ty xobj
86
105
FuncTy {} -> pure ()
87
106
PointerTy UnitTy -> pure ()
88
107
PointerTy inner ->
89
- canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables inner xobj
108
+ canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables inner xobj
90
109
>> pure ()
91
110
-- Struct variables may appear as complete applications or individual
92
111
-- components in the head of a definition; that is the forms:
@@ -105,23 +124,23 @@ canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables ty xobj
105
124
-- ((Foo (f a) (f b)) ...)
106
125
-- differ.
107
126
-- Attempt the first, more restrictive formulation first.
108
- struct@ (StructTy name tyVars) ->
109
- checkVar struct <> checkStruct name tyVars
127
+ struct@ (StructTy sname tyVars) ->
128
+ checkVar struct <> checkStruct sname tyVars
110
129
v@ (VarTy _) -> checkVar v
111
130
_ -> Left (InvalidMemberType ty xobj)
112
131
where
113
132
checkStruct :: Ty -> [Ty ] -> Either TypeError ()
114
133
checkStruct (ConcreteNameTy (SymPath [] " Array" )) [innerType] =
115
- canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables innerType xobj
134
+ canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables innerType xobj
116
135
>> pure ()
117
- checkStruct (ConcreteNameTy path@ (SymPath _ name )) vars =
118
- case E. getTypeBinder typeEnv name <> E. findTypeBinder globalEnv path of
136
+ checkStruct (ConcreteNameTy path@ (SymPath _ pname )) vars =
137
+ case E. getTypeBinder typeEnv pname <> E. findTypeBinder globalEnv path of
119
138
Right (Binder _ (XObj (Lst (XObj (ExternalType _) _ _ : _)) _ _)) ->
120
139
pure ()
121
140
Right (Binder _ (XObj (Lst (XObj (Deftype t) _ _ : _)) _ _)) ->
122
- checkInhabitants t >> foldM (\ _ typ -> canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
141
+ checkInhabitants t >> foldM (\ _ typ -> canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
123
142
Right (Binder _ (XObj (Lst (XObj (DefSumtype t) _ _ : _)) _ _)) ->
124
- checkInhabitants t >> foldM (\ _ typ -> canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
143
+ checkInhabitants t >> foldM (\ _ typ -> canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
125
144
_ -> Left (NotAmongRegisteredTypes ty xobj)
126
145
where
127
146
checkInhabitants :: Ty -> Either TypeError ()
@@ -131,8 +150,8 @@ canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables ty xobj
131
150
else Left (UninhabitedConstructor ty xobj (length vs) (length vars))
132
151
checkInhabitants _ = Left (InvalidMemberType ty xobj)
133
152
checkStruct v@ (VarTy _) vars =
134
- canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables v xobj
135
- >> foldM (\ _ typ -> canBeUsedAsMemberType typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
153
+ canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables v xobj
154
+ >> foldM (\ _ typ -> canBeUsedAsMemberType tyname typeVarRestriction typeEnv globalEnv typeVariables typ xobj) () vars
136
155
checkStruct _ _ = error " checkstruct"
137
156
checkVar :: Ty -> Either TypeError ()
138
157
checkVar variable =
0 commit comments