11{-# LANGUAGE PatternSynonyms #-}
22
3- module Test.TypeClassCheck (test ) where
3+ module Test.TypeClassCheck {- (test) -} where
44
55import Control.Lens ((.~) )
66import Data.Function ((&) )
@@ -19,6 +19,7 @@ import LambdaBuffers.Compiler.TypeClass.Pat (
1919 RecP ,
2020 RefP ,
2121 SumP ,
22+ TyVarP ,
2223 VarP ,
2324 (:*) ,
2425 (:=)
@@ -31,7 +32,7 @@ import LambdaBuffers.Compiler.TypeClass.Rules (
3132 Rule ((:<=) ),
3233 )
3334import LambdaBuffers.Compiler.TypeClass.Rules qualified as R
34- import LambdaBuffers.Compiler.TypeClass.Solve (solve )
35+ import LambdaBuffers.Compiler.TypeClass.Solve (Overlap ( Overlap ), solve )
3536import LambdaBuffers.Compiler.TypeClassCheck (detectSuperclassCycles' )
3637import Proto.Compiler (ClassDef , Constraint , Kind , Kind'KindRef (Kind'KIND_REF_TYPE ))
3738import Proto.Compiler_Fields (argKind , argName , arguments , classArgs , className , classRef , kindRef , localClassRef , name , supers , tyVar , varName )
@@ -109,60 +110,77 @@ solveTests =
109110 testGroup
110111 " Solver tests"
111112 [ testCase " 1: C [Maybe Int] (completeRules)" $
112- solveTest1 @?= []
113+ solveTest1 @?= solved
113114 , testCase " 2: D [Maybe Int] (partialRules)" $
114- solveTest2 @?= [ dInt]
115+ solveTest2 @?= Right [cListMaybeInt, cMaybeInt, dInt]
115116 , testCase " 3: D [Maybe Int] (complete D, partial C)" $
116- solveTest3 @?= [cInt]
117+ solveTest3 @?= Right [cInt]
117118 , testCase " 4: C [[[Bool]]] (completeRules)" $
118- solveTest4 @?= []
119+ solveTest4 @?= solved
119120 , testCase " 5: C (Either (Either Int Bool) (Either Bool Int)) (completeRules)" $
120- solveTest5 @?= []
121+ solveTest5 @?= solved
121122 , testCase " 6: C (Either l x) (completeRules)" $
122- solveTest6 @?= [cL, cX]
123+ solveTest6 @?= Right [cL, cX]
123124 , testCase " 7: Sum test (completeRules)" $
124- solveTest7 @?= []
125+ solveTest7 @?= solved
125126 , testCase " 8: Sum test (partialRules)" $
126- solveTest8 @?= [cBool, cInt]
127+ solveTest8 @?= Right [cBool, cInt]
127128 , testCase " 9: Rec test (completeRules)" $
128- solveTest9 @?= []
129+ solveTest9 @?= solved
129130 , testCase " 10: Rec test (partialRules)" $
130- solveTest10 @?= [cBool, cInt]
131+ solveTest10 @?= Right [cBool, cInt]
131132 , testCase " 11: Prod test (completeRules)" $
132- solveTest11 @?= []
133+ solveTest11 @?= solved
133134 , testCase " 12: Prod test (partialRules)" $
134- solveTest12 @?= [cBool, cInt]
135+ solveTest12 @?= Right [cBool, cInt]
135136 , testCase " 13: Dec test (completeRules)" $
136- solveTest13 @?= []
137+ solveTest13 @?= solved
137138 , testCase " 14: Dec test (partialRules)" $
138- solveTest14 @?= [cBool, cInt]
139+ solveTest14 @?= Right [cBool, cInt]
140+ , testCase " 15: Overlap test (specialrules)" $
141+ solveTest15 @?= Left overlap
139142 ]
140143 where
144+ solved :: Either Overlap [R. Constraint ]
145+ solved = Right []
146+ cListMaybeInt = C _c (List (Maybe Int ))
147+ cMaybeInt = C _c (Maybe Int )
141148 cInt = C _c Int
142149 cBool = C _c Bool
143- cL = C _c _l
144- cX = C _c _x
150+ cL = C _c vl
151+ cX = C _c vr
145152 dInt = C _d Int
146-
147- -- hardcoded variables, easier to read than (VarP "blah") everywhere
148- _x , _xs , _vars , _name , _l , _body :: Pat
149- _x = VarP " x"
150- _xs = VarP " xs"
151- _vars = VarP " vars"
152- _name = VarP " name"
153- _l = VarP " l"
154- _body = VarP " body"
153+ overlap =
154+ Overlap
155+ cMaybeInt
156+ [ C _c (Maybe _X) :<= [C _c _X]
157+ , C _c (Maybe Int ) :<= []
158+ ]
159+
160+ -- hardcoded PATTERN variables, easier to read than (VarP "blah") everywhere
161+ _X , _XS , _VARS , _NAME , _L , _BODY :: Pat
162+ _X = VarP " x"
163+ _XS = VarP " xs"
164+ _VARS = VarP " vars"
165+ _NAME = VarP " name"
166+ _L = VarP " l"
167+ _BODY = VarP " body"
168+
169+ -- hardcoded TYPE variables
170+ vl , vr :: Pat
171+ vl = TyVarP " l"
172+ vr = TyVarP " r"
155173
156174-- TODO(@gnumonik): Import this from somewhere else when that somewhere else module exists
157175mkStructuralRules :: Class -> [Rule ]
158176mkStructuralRules c =
159177 [ C c Nil :<= []
160- , C c (_x :* _xs ) :<= [C c _x , C c _xs ]
161- , C c (_l := _x ) :<= [C c _x ]
162- , C c (RecP _xs ) :<= [C c _xs ]
163- , C c (ProdP _xs ) :<= [C c _xs ]
164- , C c (SumP _xs ) :<= [C c _xs ]
165- , C c (DecP _name _vars _body ) :<= [C c _body ]
178+ , C c (_X :* _XS ) :<= [C c _X , C c _XS ]
179+ , C c (_L := _X ) :<= [C c _X ]
180+ , C c (RecP _XS ) :<= [C c _XS ]
181+ , C c (ProdP _XS ) :<= [C c _XS ]
182+ , C c (SumP _XS ) :<= [C c _XS ]
183+ , C c (DecP _NAME _VARS _BODY ) :<= [C c _BODY ]
166184 ]
167185
168186pattern (:@) :: Pat -> Pat -> Pat
@@ -196,16 +214,16 @@ userRules1 :: Class -> [Rule]
196214userRules1 c =
197215 [ NoConstraints c Int
198216 , NoConstraints c Bool
199- , C c (Maybe _x ) :<= [C c _x ]
200- , C c (Either _l _x ) :<= [C c _l , C c _x ]
201- , C c (List _x ) :<= [C c _x ]
217+ , C c (Maybe _X ) :<= [C c _X ]
218+ , C c (Either _L _X ) :<= [C c _L , C c _X ]
219+ , C c (List _X ) :<= [C c _X ]
202220 ]
203221
204222userRules2 :: Class -> [Rule ]
205223userRules2 c =
206- [ C c (Maybe _x ) :<= [C c _x ]
207- , C c (Either _l _x ) :<= [C c _l , C c _x ]
208- , C c (List _x ) :<= [C c _x ]
224+ [ C c (Maybe _X ) :<= [C c _X ]
225+ , C c (Either _L _X ) :<= [C c _L , C c _X ]
226+ , C c (List _X ) :<= [C c _X ]
209227 ]
210228
211229completeRules :: Class -> [Rule ]
@@ -223,49 +241,48 @@ _d :: Class
223241_d = Class (FQClassName " D" [] ) [_c]
224242
225243-- C [Maybe Int] w/ complete rules (expected: [])
226- solveTest1 :: [R. Constraint ]
244+ solveTest1 :: Either Overlap [R. Constraint ]
227245solveTest1 = solve (completeRules _c) (C _c $ List (Maybe Int ))
228246
229- -- D [Maybe Int] w/ incomplete rules (expected: [D Int])
230- solveTest2 :: [R. Constraint ]
247+ -- D [Maybe Int] w/ incomplete rules (expected: [C [Maybe Int], C (Maybe Int), D Int])
248+ solveTest2 :: Either Overlap [R. Constraint ]
231249solveTest2 = solve (partialRules _d) (C _d $ List (Maybe Int ))
232250
233251-- D [Maybe Int] w/ complete D rules & incomplete C rules (expected: [C Int])
234- solveTest3 :: [R. Constraint ]
252+ solveTest3 :: Either Overlap [R. Constraint ]
235253solveTest3 = solve rules (C _d $ List (Maybe Int ))
236254 where
237255 rules = completeRules _d <> partialRules _c
238256
239257-- C [[[Bool]]] w/ complete rules (expected: [])
240- solveTest4 :: [R. Constraint ]
258+ solveTest4 :: Either Overlap [R. Constraint ]
241259solveTest4 = solve (completeRules _c) $ C _c $ List (List (List Bool ))
242260
243261-- C (Either (Either Int Bool) (Either Bool Int)) w/ complete rules (expected: [])
244- solveTest5 :: [R. Constraint ]
262+ solveTest5 :: Either Overlap [R. Constraint ]
245263solveTest5 = solve (completeRules _c) $ C _c $ Either (Either Int Bool ) (Either Bool Int )
246264
247265-- NOTE(@bladyjoker): This one shows that we never need to "freshen" variables
248- -- (if you study it you might also see why we never need to bind them)
249266-- C (Either l x) w/ complete rules (expected: [C l, C x])
250- solveTest6 :: [R. Constraint ]
251- solveTest6 = solve (completeRules _c) $ C _c $ Either _l _x
267+ solveTest6 :: Either Overlap [R. Constraint ]
268+ solveTest6 = solve (completeRules _c) $ C _c $ Either vl vr
252269
253270-- tests for structural subcomponents of types. Can't write Haskell equivalents (w/o row-types)
254271
255272-- expected: []
256- solveTest7 :: [R. Constraint ]
273+ solveTest7 :: Either Overlap [R. Constraint ]
257274solveTest7 = solve (completeRules _c) $ C _c sumBody
258275 where
259276 sumBody = SumP $ Labeled " Ctor1" Int :* Labeled " Ctor2" (List Bool ) :* Nil
260277
261278-- expected [C Bool, C Int]
262- solveTest8 :: [R. Constraint ]
279+ solveTest8 :: Either Overlap [R. Constraint ]
263280solveTest8 = solve (partialRules _c) $ C _c sumBody
264281 where
265282 sumBody = SumP $ Labeled " Ctor1" Int :* Labeled " Ctor2" (List Bool ) :* Nil
266283
267284-- expected []
268- solveTest9 :: [R. Constraint ]
285+ solveTest9 :: Either Overlap [R. Constraint ]
269286solveTest9 = solve (completeRules _c) $ C _c recBody
270287 where
271288 recBody =
@@ -275,7 +292,7 @@ solveTest9 = solve (completeRules _c) $ C _c recBody
275292 :* Nil
276293
277294-- expected [C Bool, C Int]
278- solveTest10 :: [R. Constraint ]
295+ solveTest10 :: Either Overlap [R. Constraint ]
279296solveTest10 = solve (partialRules _c) $ C _c recBody
280297 where
281298 recBody =
@@ -285,19 +302,19 @@ solveTest10 = solve (partialRules _c) $ C _c recBody
285302 :* Nil
286303
287304-- expected []
288- solveTest11 :: [R. Constraint ]
305+ solveTest11 :: Either Overlap [R. Constraint ]
289306solveTest11 = solve (completeRules _c) $ C _c prodBody
290307 where
291308 prodBody = ProdP $ List Bool :* Either Int Bool :* Nil
292309
293310-- expected [C Bool, C Int]
294- solveTest12 :: [R. Constraint ]
311+ solveTest12 :: Either Overlap [R. Constraint ]
295312solveTest12 = solve (partialRules _c) $ C _c prodBody
296313 where
297314 prodBody = ProdP $ List Bool :* Either Int Bool :* Nil
298315
299316-- expected []
300- solveTest13 :: [R. Constraint ]
317+ solveTest13 :: Either Overlap [R. Constraint ]
301318solveTest13 = solve (completeRules _c) $ C _c testDec
302319 where
303320 testDec =
@@ -308,7 +325,7 @@ solveTest13 = solve (completeRules _c) $ C _c testDec
308325 :* Nil
309326
310327-- expected [C Int, C Bool]
311- solveTest14 :: [R. Constraint ]
328+ solveTest14 :: Either Overlap [R. Constraint ]
312329solveTest14 = solve (partialRules _c) $ C _c testDec
313330 where
314331 testDec =
@@ -317,3 +334,14 @@ solveTest14 = solve (partialRules _c) $ C _c testDec
317334 Labeled " Ctor1" (ProdP $ Maybe Int :* Nil )
318335 :* Labeled " Ctor2" (RecP $ Labeled " field1" Bool :* Nil )
319336 :* Nil
337+
338+ -- expected overlap
339+ solveTest15 :: Either Overlap [R. Constraint ]
340+ solveTest15 = solve cOverlapRules (C _c $ List (Maybe Int ))
341+ where
342+ cOverlapRules =
343+ [ C _c (Maybe _X) :<= [C _c _X]
344+ , C _c (Maybe Int ) :<= []
345+ , C _c Int :<= []
346+ , C _c (List _X) :<= [C _c _X]
347+ ]
0 commit comments