-
Notifications
You must be signed in to change notification settings - Fork 0
/
TypeChecker.hs
2112 lines (1954 loc) · 129 KB
/
TypeChecker.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}
module TypeChecker where
import qualified Data.Map as Map
import Control.Monad
import Data.List
import Data.Either
import Data.Bifunctor
import Debug.Trace ( trace )
import Control.Monad.State
import Text.Megaparsec as P hiding (State)
import Text.Megaparsec.Pos (mkPos)
import Data.Functor
import qualified Data.Set as Set
import Data.Maybe
import Data.Tuple
import qualified Parser
import Nodes
import Control.Exception.Base (TypeError(TypeError))
insertAnnotation :: Lhs -> Finalizeable Annotation -> AnnotationState (Annotations (Finalizeable Annotation)) Annotation
insertAnnotation k v@(Finalizeable _ a) = do
(a, ((i, Annotations (b, s) o), m)) <- get
put (a, ((i, Annotations (Map.insert k v b, s) o), m))
return a
getAnnotation :: Show a => Lhs -> Annotations a -> Result ErrorType a
getAnnotation k@(LhsIdentifer _ pos) (Annotations anns rest) =
case Map.lookup k $ fst anns of
Just v -> Right v
Nothing ->
case rest of
Just rs -> getAnnotation k rs
Nothing -> Left $ NoDefinitionFound k pos
getAnnotation k a = error $ "Unexpected args " ++ show (k, a)
modifyAnnotation :: UserDefinedTypes -> Lhs -> Annotation -> Annotations (Finalizeable Annotation) -> Result ErrorType (Annotations (Finalizeable Annotation))
modifyAnnotation usts k@(LhsIdentifer _ pos) ann (Annotations (anns, set) rest) =
case Map.lookup k anns of
Just (Finalizeable False v) -> Right $ Annotations (Map.insert k (Finalizeable False ann) anns, set) rest
Just (Finalizeable True v) ->
case sameTypesImpl ann pos usts v ann of
Right _ -> Right $ Annotations (Map.insert k (Finalizeable False ann) anns, set) rest
Left err -> Left $ IrreconcilableAnnotatatedType k v ann pos
Nothing ->
case rest of
Just rs -> case modifyAnnotation usts k ann rs of
Right a -> Right $ Annotations (anns, set) (Just a)
Left err -> Left err
Nothing -> Left $ NoDefinitionFound k pos
modifyAnnotation _ k ann as = error $ "Unexpected args " ++ show (k, ann, as)
modifyAnnotationState :: Lhs -> Annotation -> AnnotationState (Annotations (Finalizeable Annotation)) (Result ErrorType Annotation)
modifyAnnotationState k@(LhsIdentifer _ pos) v = do
(a, ((i, anns), usts)) <- get
case modifyAnnotation usts k v anns of
Right x -> (Right <$> put (a, ((i, x), usts))) $> Right v
Left err -> return $ Left err
modifyAnnotationState k v = error $ "Unexpected args " ++ show (k, v)
finalizeAnnotations :: Ord a => Annotations (Finalizeable a) -> Annotations (Finalizeable a)
finalizeAnnotations (Annotations (anns, set) Nothing) = Annotations (Map.map finalize anns, set) Nothing
finalizeAnnotations (Annotations (anns, set) (Just rest)) = Annotations (Map.map finalize anns, Set.map finalize set) (Just $ finalizeAnnotations rest)
finalizeAnnotationState :: Ord a => AnnotationState (Annotations (Finalizeable a)) ()
finalizeAnnotationState = modify (\(a, ((i, anns), b)) -> (a, ((i, finalizeAnnotations anns), b)))
getAnnotationState :: Show a => Lhs -> AnnotationState (Annotations (Finalizeable a)) (Result ErrorType a)
getAnnotationState k = get >>= \(_, ((_, anns), _)) -> return (fromFinalizeable <$> getAnnotation k anns)
getAnnotationStateFinalizeable :: Show a => Lhs -> AnnotationState (Annotations a) (Result ErrorType a)
getAnnotationStateFinalizeable k = get >>= \(_, ((_, anns), _)) -> return (getAnnotation k anns)
rigidizeTypeConstraints :: UserDefinedTypes -> Constraint -> Constraint
rigidizeTypeConstraints usts (ConstraintHas lhs cs) = ConstraintHas lhs $ rigidizeTypeConstraints usts cs
rigidizeTypeConstraints usts (AnnotationConstraint ann) = AnnotationConstraint $ rigidizeTypeVariables usts ann
rigidizeTypeVariables :: UserDefinedTypes -> Annotation -> Annotation
rigidizeTypeVariables usts fid@(GenericAnnotation id cns) = RigidAnnotation id $ map (rigidizeTypeConstraints usts) cns
rigidizeTypeVariables usts fid@RigidAnnotation{} = fid
rigidizeTypeVariables usts id@AnnotationLiteral{} = id
rigidizeTypeVariables usts fid@(Annotation id) = fromMaybe (error $ noTypeFound id sourcePos) (Map.lookup (LhsIdentifer id sourcePos) usts)
rigidizeTypeVariables usts (NewTypeAnnotation id anns annMap) = NewTypeAnnotation id (map (rigidizeTypeVariables usts) anns) (Map.map (rigidizeTypeVariables usts) annMap)
rigidizeTypeVariables usts (NewTypeInstanceAnnotation id anns) = NewTypeInstanceAnnotation id (map (rigidizeTypeVariables usts) anns)
rigidizeTypeVariables usts (FunctionAnnotation args ret) = FunctionAnnotation (map (rigidizeTypeVariables usts) args) (rigidizeTypeVariables usts ret)
rigidizeTypeVariables usts (StructAnnotation ms) = StructAnnotation $ Map.map (rigidizeTypeVariables usts) ms
rigidizeTypeVariables usts (TypeUnion ts) = TypeUnion $ Set.map (rigidizeTypeVariables usts) ts
rigidizeTypeVariables usts OpenFunctionAnnotation{} = error "Can't use rigidizeVariables with open functions"
unrigidizeTypeConstraints :: UserDefinedTypes -> Constraint -> Constraint
unrigidizeTypeConstraints usts (ConstraintHas lhs cs) = ConstraintHas lhs $ unrigidizeTypeConstraints usts cs
unrigidizeTypeConstraints usts (AnnotationConstraint ann) = AnnotationConstraint $ unrigidizeTypeVariables usts ann
unrigidizeTypeVariables :: UserDefinedTypes -> Annotation -> Annotation
unrigidizeTypeVariables usts fid@(GenericAnnotation id cns) = fid
unrigidizeTypeVariables usts fid@(RigidAnnotation id cns) = GenericAnnotation id $ map (unrigidizeTypeConstraints usts) cns
unrigidizeTypeVariables usts id@AnnotationLiteral{} = id
unrigidizeTypeVariables usts fid@(Annotation id) = fromMaybe (error $ noTypeFound id sourcePos) (Map.lookup (LhsIdentifer id sourcePos) usts)
unrigidizeTypeVariables usts (NewTypeAnnotation id anns annMap) = NewTypeAnnotation id (map (unrigidizeTypeVariables usts) anns) (Map.map (unrigidizeTypeVariables usts) annMap)
unrigidizeTypeVariables usts (NewTypeInstanceAnnotation id anns) = NewTypeInstanceAnnotation id (map (unrigidizeTypeVariables usts) anns)
unrigidizeTypeVariables usts (FunctionAnnotation args ret) = FunctionAnnotation (map (unrigidizeTypeVariables usts) args) (unrigidizeTypeVariables usts ret)
unrigidizeTypeVariables usts (StructAnnotation ms) = StructAnnotation $ Map.map (unrigidizeTypeVariables usts) ms
unrigidizeTypeVariables usts (TypeUnion ts) = TypeUnion $ Set.map (unrigidizeTypeVariables usts) ts
unrigidizeTypeVariables usts OpenFunctionAnnotation{} = error "Can't use rigidizeVariables with open functions"
pushScope :: Show a => AnnotationState (Annotations a) ()
pushScope = (\(a, ((i, mp), b)) -> put (a, ((i, Annotations (Map.empty, Set.empty) $ Just mp), b))) =<< get
popScope :: Show a => AnnotationState (Annotations a) ()
popScope = (\(a, ((i, Annotations _ (Just mp)), b)) -> put (a, ((i, mp), b))) =<< get
mapRight :: Monad m => m (Either a t) -> (t -> m (Either a b)) -> m (Either a b)
mapRight f f1 = do
a <- f
case a of
Right a -> f1 a
Left err -> return $ Left err
makeFunAnnotation args = FunctionAnnotation (map snd args)
isCallable :: Annotation -> Bool
isCallable FunctionAnnotation{} = True
isCallable _ = False
mapLeft s f = case s of
Left x -> f x
Right a -> Right a
toEither def (Just a) = Right a
toEither def Nothing = Left def
getTypeState :: Annotation -> P.SourcePos -> State (Annotation, (b, UserDefinedTypes)) (Either ErrorType Annotation)
getTypeState (Annotation id) pos = do
(_, (_, types)) <- get
case Map.lookup (LhsIdentifer id pos) types of
Just st -> return $ Right st
Nothing -> return . Left $ NoTypeFound id pos
getTypeState a _ = return $ Right a
getTypeStateFrom :: AnnotationState a (Either ErrorType Annotation) -> SourcePos -> AnnotationState a (Either ErrorType Annotation)
getTypeStateFrom f pos = do
res <- f
case res of
Right res -> getTypeState res pos
Left err -> return $ Left err
lookupInTypes ann (Annotations (_, set) (Just rest)) = Set.member ann set || lookupInTypes ann rest
lookupInTypes ann (Annotations (_, set) Nothing) = Set.member ann set
firstInferrableReturn :: P.SourcePos -> [Node] -> AnnotationState (Annotations (Finalizeable Annotation)) (Either ErrorType Node)
firstInferrableReturn pos [] = return . Left $ UnInferrableType Nothing pos
firstInferrableReturn pos (IfStmnt cond ts es _:xs) = do
scope@(_, (_, mp)) <- get
t <- firstInferrableReturn pos ts
case t of
Right a -> return $ Right a
Left _ -> do
put scope
e <- firstInferrableReturn pos es
case e of
Right a -> return $ Right a
Left err -> do
put scope
firstInferrableReturn pos xs
firstInferrableReturn pos (n@(DeclN (Decl _ rhs _ _)):xs) = do
getAssumptionType n
as <- firstInferrableReturn pos [rhs]
bs <- firstInferrableReturn pos xs
return $ mapLeft as (const bs)
firstInferrableReturn pos (n@(DeclN (Assign _ rhs _)):xs) = do
getAssumptionType n
as <- firstInferrableReturn pos [rhs]
bs <- firstInferrableReturn pos xs
return $ mapLeft as (const bs)
firstInferrableReturn _ ((Return a _):_) = return $ Right a
firstInferrableReturn pos (_:xs) = firstInferrableReturn pos xs
isGeneric :: P.SourcePos -> UserDefinedTypes -> Annotation -> Bool
isGeneric pos usts ann = evalState (go pos usts ann) Map.empty where
go :: P.SourcePos -> UserDefinedTypes -> Annotation -> State (Map.Map Annotation Bool) Bool
go pos mp GenericAnnotation{} = return True
go pos mp (RigidAnnotation _ cns) = or <$> mapM goConstraints cns where
goConstraints (ConstraintHas _ cn) = goConstraints cn
goConstraints (AnnotationConstraint ann) = go pos mp ann
go pos mp AnnotationLiteral{} = return False
go pos mp wholeAnn@(Annotation ann) = do
recordedAnns <- get
case Map.lookup wholeAnn recordedAnns of
Just b -> return b
Nothing -> case Map.lookup (LhsIdentifer ann pos) mp of
Just new_ann -> do
put $ Map.insert wholeAnn False recordedAnns
new_res <- go pos mp new_ann
put $ Map.insert wholeAnn new_res recordedAnns
return new_res
Nothing -> return False
go pos mp (FunctionAnnotation args ret) = or <$> mapM (go pos mp) (ret:args)
go pos mp (StructAnnotation ms) = or <$> mapM (go pos mp) ms
go pos mp (NewTypeAnnotation _ _ tmp) = or <$> mapM (go pos mp) tmp
go pos mp (NewTypeInstanceAnnotation _ as) = or <$> mapM (go pos mp) as
go pos mp (TypeUnion ts) = or <$> mapM (go pos mp) (Set.toList ts)
go pos mp OpenFunctionAnnotation{} = return False
firstPreferablyDefinedRelation :: SourcePos
-> Map.Map Lhs Annotation
-> Set.Set Annotation
-> TwoSets Annotation
-> Annotations Annotation
-> Map.Map Annotation a
-> Map.Map Annotation (Set.Set Annotation)
-> Annotation
-> Either ErrorType Annotation
firstPreferablyDefinedRelation pos usts prevs defs scope mp rs k =
case Map.lookup k rs of
Just s ->
if notnull stf then Right . defResIfNull $ inDefs stf
else if notnull deftf then Right . defResIfNull $ inDefs deftf
else if notnull prevs then Right . defResIfNull $ inSecondaryDefs prevs
else if notnull secondaryDeftf then Right . defResIfNull $ inSecondaryDefs secondaryDeftf
else case defRes of
Right x -> Right x
Left _ -> Right . Set.elemAt 0 $ if notnull $ inDefs s then inDefs s else s
where
notnull = not . Set.null
deftf = Set.filter (flip (isPrmaryDefMember usts) defs) s
secondaryDeftf = Set.filter (flip (isSecondaryDefMember usts) defs) s
scopetf = Set.filter (`lookupInTypes` scope) s
stf = Set.filter (\x -> isJust (Map.lookup x mp)) s
defResIfNull s' = if notnull s' then Set.elemAt 0 s' else case defRes of
Right x -> x
Left _ -> Set.elemAt 0 s
Nothing -> defRes
where
inDefs s = Set.filter (flip (isPrmaryDefMember usts) defs) s
inSecondaryDefs s = Set.filter (flip (isSecondaryDefMember usts) defs) s
defRes =
case Map.elems $ Map.filter (\s -> isDefMember usts k s && not (Set.disjoint (primary defs) s)) $ Map.mapWithKey Set.insert rs of
[] -> case Map.elems $ Map.filter (\s -> isDefMember usts k s && not (Set.disjoint (secondary defs) s)) $ Map.mapWithKey Set.insert rs of
[] ->
if isSecondaryDefMember usts k defs then Right k
else Left $ NoEstablishedRelationWith k pos
xs -> Right . Set.elemAt 0 . inSecondaryDefs $ head xs
xs -> Right . Set.elemAt 0 . inDefs $ head xs
isDefMember :: UserDefinedTypes -> Annotation -> Set.Set Annotation -> Bool
isDefMember usts a defs = a `Set.member` defs || rigidizeTypeVariables usts a `Set.member` defs
isPrmaryDefMember :: UserDefinedTypes -> Annotation -> TwoSets Annotation -> Bool
isPrmaryDefMember usts a defs = a `primaryMember` defs || rigidizeTypeVariables usts a `primaryMember` defs
isSecondaryDefMember :: UserDefinedTypes -> Annotation -> TwoSets Annotation -> Bool
isSecondaryDefMember usts a defs = a `secondaryMember` defs || rigidizeTypeVariables usts a `secondaryMember` defs
rigidizeAllConstraintsFromScope :: Annotations Annotation -> Constraint -> Constraint
rigidizeAllConstraintsFromScope scp (ConstraintHas lhs cs) = ConstraintHas lhs $ rigidizeAllConstraintsFromScope scp cs
rigidizeAllConstraintsFromScope scp (AnnotationConstraint ann) = AnnotationConstraint $ rigidizeAllFromScope scp ann
rigidizeAllFromScope :: Annotations Annotation -> Annotation -> Annotation
rigidizeAllFromScope scp fid@(GenericAnnotation id cns) =
(if lookupInTypes fid scp then RigidAnnotation else GenericAnnotation) id $ map (rigidizeAllConstraintsFromScope scp) cns
rigidizeAllFromScope scp fid@(RigidAnnotation id cns) = RigidAnnotation id $ map (rigidizeAllConstraintsFromScope scp) cns
rigidizeAllFromScope scp id@AnnotationLiteral{} = id
rigidizeAllFromScope scp id@Annotation{} = id
rigidizeAllFromScope scp (NewTypeAnnotation id anns annMap) = NewTypeAnnotation id (map (rigidizeAllFromScope scp) anns) (Map.map (rigidizeAllFromScope scp) annMap)
rigidizeAllFromScope scp (NewTypeInstanceAnnotation id anns) = NewTypeInstanceAnnotation id (map (rigidizeAllFromScope scp) anns)
rigidizeAllFromScope scp (FunctionAnnotation args ret) = FunctionAnnotation (map (rigidizeAllFromScope scp) args) (rigidizeAllFromScope scp ret)
rigidizeAllFromScope scp (StructAnnotation ms) = StructAnnotation $ Map.map (rigidizeAllFromScope scp) ms
rigidizeAllFromScope scp (TypeUnion ts) = TypeUnion $ Set.map (rigidizeAllFromScope scp) ts
rigidizeAllFromScope scp OpenFunctionAnnotation{} = error "Can't use rigidizeVariables with open functions"
substituteVariablesOptFilter :: Bool
-> SourcePos
-> TwoSets Annotation
-> Annotations Annotation
-> Map.Map Annotation (Set.Set Annotation)
-> Map.Map Annotation Annotation
-> UserDefinedTypes
-> Annotation
-> Either ErrorType Annotation
substituteVariablesOptFilter pred pos defs anns rels mp usts n = evalState (go pred rels mp n) Set.empty where
goConstraints :: Bool
-> Map.Map Annotation (Set.Set Annotation)
-> Map.Map Annotation Annotation
-> Constraint
-> State (Set.Set Annotation) (Either ErrorType Constraint)
goConstraints pred rels mp (ConstraintHas lhs cs) = goConstraints pred rels mp cs >>= (\a -> return $ ConstraintHas lhs <$> a)
goConstraints pred rels mp (AnnotationConstraint ann) = go pred rels mp ann >>= (\a -> return $ AnnotationConstraint <$> a)
go :: Bool
-> Map.Map Annotation (Set.Set Annotation)
-> Map.Map Annotation Annotation
-> Annotation
-> State (Set.Set Annotation) (Either ErrorType Annotation)
go pred rels mp fid@(GenericAnnotation id cns) =
maybe g (\x -> if sameTypesBool pos usts fid x then g else return $ Right x) (Map.lookup fid mp) >>= \case
Right retGen -> modify (retGen `Set.insert`) >> return (Right retGen)
Left err -> return $ Left err
where
f gs x = case firstPreferablyDefinedRelation pos usts gs defs anns mp rels x of
Right a -> Right a
Left err -> if lookupInTypes x anns then Right x else Left err
g = join <$> (mapM (goConstraints pred rels mp) cns >>= (\case
Left err -> return $ Left err
Right x -> get >>= \gs -> return $ Right $ (f gs . GenericAnnotation id) x) . sequence)
go pred rels mp (RigidAnnotation id cns) =
go pred rels mp (GenericAnnotation id cns) >>= \case
Right (GenericAnnotation id cns) -> return . Right $ RigidAnnotation id cns
Right a -> return $ Right a
Left err -> return $ Left err
go pred rels mp id@AnnotationLiteral{} = return $ Right id
go pred rels mp fid@(Annotation id) = return $ maybe (Left $ NoTypeFound id pos) Right (Map.lookup (LhsIdentifer id pos) usts)
go pred rels mp (NewTypeAnnotation id anns annMap) = do
anns' <- sequence <$> mapM (go pred rels mp) anns
annMap' <- sequence <$> mapM (go pred rels mp) annMap
return (NewTypeAnnotation id <$> anns' <*> annMap')
go pred rels mp (NewTypeInstanceAnnotation id anns) =
(\xanns -> return $ NewTypeInstanceAnnotation id <$> xanns) . sequence =<< mapM (go pred rels mp) anns
go pred rels mp (FunctionAnnotation args ret) = mapM (go pred rels mp) args >>=
(\args'
-> go pred rels mp ret
>>= \ ret' -> return $ FunctionAnnotation <$> args' <*> ret')
. sequence
go pred rels mp (StructAnnotation ms) =
(\ms' -> return $ StructAnnotation <$> ms') . sequence =<< mapM (go pred rels mp) ms
go pred rels mp (TypeUnion ts) = do
let f = if pred then filter (\a -> not (isGeneric pos usts a) || (isGeneric pos usts a && annotationConsistsOf usts defs a)) else id
xs <- mapM (go pred rels mp) (Set.toList ts)
let xs' = map (\(Right a) -> a) $ filter isRight xs
case xs' of
[] -> return $ foldr1 (mergedTypeConcrete pos usts) <$> sequence xs
xs -> return . Right $ foldr1 (mergedTypeConcrete pos usts) xs
go pred rels mp OpenFunctionAnnotation{} = error "Can't use substituteVariables with open functions"
constraintsConsistsOf :: UserDefinedTypes -> TwoSets Annotation -> Constraint -> Bool
constraintsConsistsOf usts defs (ConstraintHas lhs cs) = constraintsConsistsOf usts defs cs
constraintsConsistsOf usts defs (AnnotationConstraint ann) = annotationConsistsOf usts defs ann
annotationConsistsOf :: UserDefinedTypes -> TwoSets Annotation -> Annotation -> Bool
annotationConsistsOf usts defs fid@(GenericAnnotation id cns) = isSecondaryDefMember usts fid defs && all (constraintsConsistsOf usts defs) cns
annotationConsistsOf usts defs fid@(RigidAnnotation id cns) = isSecondaryDefMember usts fid defs && all (constraintsConsistsOf usts defs) cns
annotationConsistsOf usts defs AnnotationLiteral{} = False
annotationConsistsOf usts defs fid@(Annotation ident) = False
annotationConsistsOf usts defs (NewTypeAnnotation id anns annMap) = all (annotationConsistsOf usts defs) anns && and (Map.elems $ Map.map (annotationConsistsOf usts defs) annMap)
annotationConsistsOf usts defs (NewTypeInstanceAnnotation id anns) = all (annotationConsistsOf usts defs) anns
annotationConsistsOf usts defs (FunctionAnnotation args ret) = all (annotationConsistsOf usts defs) (ret:args)
annotationConsistsOf usts defs (StructAnnotation ms) = and . Map.elems $ Map.map (annotationConsistsOf usts defs) ms
annotationConsistsOf usts defs (TypeUnion ts) = all (annotationConsistsOf usts defs) ts
annotationConsistsOf usts defs (OpenFunctionAnnotation args ret ftr _) = all (annotationConsistsOf usts defs) (ftr:ret:args)
substituteVariables = substituteVariablesOptFilter True
collectGenericConstraintsOptionalHOF :: Bool -> Bool -> UserDefinedTypes -> Constraint -> Set.Set Annotation
collectGenericConstraintsOptionalHOF collectHOFs collectRigids usts (ConstraintHas lhs cs) = collectGenericConstraintsOptionalHOF collectHOFs collectRigids usts cs
collectGenericConstraintsOptionalHOF collectHOFs collectRigids usts (AnnotationConstraint ann) = collectGenenricsOptionalHOF collectHOFs collectRigids usts ann
collectGenenricsOptionalHOF :: Bool -> Bool -> UserDefinedTypes -> Annotation -> Set.Set Annotation
collectGenenricsOptionalHOF collectHOFs collectRigids usts fid@(GenericAnnotation id cns) = Set.singleton fid `Set.union` Set.unions (map (collectGenericConstraintsOptionalHOF collectHOFs collectRigids usts) cns)
collectGenenricsOptionalHOF collectHOFs True usts fid@(RigidAnnotation id cns) = Set.singleton fid `Set.union` Set.unions (map (collectGenericConstraintsOptionalHOF collectHOFs True usts) cns)
collectGenenricsOptionalHOF collectHOFs False usts fid@(RigidAnnotation id cns) = Set.unions (map (collectGenericConstraintsOptionalHOF collectHOFs False usts) cns)
collectGenenricsOptionalHOF collectHOFs collectRigids usts AnnotationLiteral{} = Set.empty
collectGenenricsOptionalHOF collectHOFs collectRigids usts fid@(Annotation ident) = maybe (error "Run your passes in order. You should know that this doesn't exists by now") (const Set.empty) (Map.lookup (LhsIdentifer ident (SourcePos "" (mkPos 0) (mkPos 0))) usts)
collectGenenricsOptionalHOF collectHOFs collectRigids usts (NewTypeAnnotation id anns annMap) = Set.unions (Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) (Set.fromList anns)) `Set.union` foldl1 Set.union (map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) (Map.elems annMap))
collectGenenricsOptionalHOF collectHOFs collectRigids usts (NewTypeInstanceAnnotation id anns) = Set.unions $ Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) (Set.fromList anns)
collectGenenricsOptionalHOF collectHOFs collectRigids usts (FunctionAnnotation args ret) = if collectHOFs then Set.unions $ Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) (Set.fromList $ args ++ [ret]) else Set.empty
collectGenenricsOptionalHOF collectHOFs collectRigids usts (StructAnnotation ms) = Set.unions $ Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) (Set.fromList $ Map.elems ms)
collectGenenricsOptionalHOF collectHOFs collectRigids usts (TypeUnion ts) = Set.unions $ Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) ts
collectGenenricsOptionalHOF collectHOFs collectRigids usts (OpenFunctionAnnotation args ret ftr _) = Set.unions $ Set.map (collectGenenricsOptionalHOF collectHOFs collectRigids usts) $ Set.fromList (args++[ret, ftr])
collectGenenrics = collectGenenricsOptionalHOF False True
collectGenenricsHOF = collectGenenricsOptionalHOF True True
getLookupTypeIfAvailable :: Annotation -> SubstituteState Annotation
getLookupTypeIfAvailable k = do
(a, ((rs, mp), usts)) <- get
case Map.lookup k mp of
Just k -> getLookupTypeIfAvailable k
Nothing -> return k
changeType :: P.SourcePos -> TwoSets Annotation -> Annotations Annotation -> Annotation -> Annotation -> SubstituteState (Either ErrorType ())
changeType pos defs anns k v = do
(a, ((rel, mp), usts)) <- get
case substituteVariablesOptFilter False pos defs anns rel mp usts v of
Right sub -> put (a, ((rel, Map.insert k sub mp), usts)) $> Right ()
Left err -> return $ Left err
reshuffleTypes :: P.SourcePos -> TwoSets Annotation -> Annotations Annotation -> SubstituteState ()
reshuffleTypes pos defs anns = (\(_, ((_, mp), _)) -> sequence_ $ Map.mapWithKey (changeType pos defs anns) mp) =<< get
sameTypesNoUnionSpec = sameTypesGeneric (False, True, False, Map.empty)
addTypeVariable :: SourcePos
-> (Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> Maybe (SubstituteState (Either ErrorType ()))
-> Annotation
-> Annotation
-> SubstituteState (Either ErrorType Annotation)
addTypeVariable pos f defs anns stmnt k v = do
(a, ((rs, mp), usts)) <- get
case Map.lookup k mp of
Nothing -> addToMap k v
Just a -> if collectGenenricsNoRigids usts a == Set.empty && collectGenenricsNoRigids usts v == Set.empty then
case f k pos usts a v of
Right v -> addToMap k v
Left err -> case f k pos usts v a of
Left err -> lastResort a rs mp usts (Left err)
Right v -> return $ Right v
else specifyInternal pos stmnt f defs anns a v >>= \case
Right v -> addToMap k v
Left _ -> specifyInternal pos stmnt f defs anns v a >>= \case
Right v -> addToMap k v
Left err -> lastResort a rs mp usts (Left err)
where
collectGenenricsNoRigids = collectGenenricsOptionalHOF False False
collectGenenricsNoRigidsHOF = collectGenenricsOptionalHOF True False
addToMap k v = do
(a, ((rs, mp), usts)) <- get
if k `Set.member` collectGenenricsNoRigidsHOF usts v then
return . Left $ InfiniteTypeError k v pos
else do
put (a, ((rs, Map.insert k v mp), usts))
fromMaybe (updateRelations pos stmnt f defs anns) stmnt >>= \case
Right _ -> reshuffleTypes pos defs anns $> Right v
Left err -> return . Left $ UnificationError k err
lastResort a rs mp usts x = if a == AnnotationLiteral "_" then addToMap k v else
case Map.lookup k rs of
Just st -> if Set.member v st then addToMap k v else return x
Nothing -> return x
-- This is written horribly, rewrite it
updateSingleRelation :: SourcePos
-> p
-> (Annotation
-> SourcePos
-> UserDefinedTypes
-> Annotation
-> Annotation
-> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> Annotation
-> SubstituteState (Either ErrorType ())
updateSingleRelation pos stmnt fa defs anns r = do
(a, ((rs, mp), usts)) <- get
case Map.lookup r rs of
Just rl -> do
(\case
Right _ -> do
put (a, ((Map.insert r (getAllRelationsInvolving r rs) rs, mp), usts))
maybe (return $ Right ()) (fmap ($> ()) . specifyInternal pos (Just . return $ Right ()) fa defs anns r) fnv
Left err -> return $ Left err) . sequence =<< mapM (uncurry f) mls'
where
m = Map.filterWithKey (\k _ -> k `Set.member` rl) mp
mls = Map.toList m
fnv = firstNonUnderscore mls
mls' = case fnv of
Just a -> map (\(k, _) -> (k, a)) mls
Nothing -> []
f = addTypeVariable pos fa defs anns (Just . return $ Right ())
firstNonUnderscore [] = Nothing
firstNonUnderscore ((_, AnnotationLiteral "_"):xs) = firstNonUnderscore xs
firstNonUnderscore ((_, ann):xs) = Just ann
getAllRelationsInvolving r rs = Set.unions $ Map.elems $ Map.filter (Set.member r) $ Map.mapWithKey Set.insert rs
Nothing -> return . Left $ NoEstablishedRelationWith r pos
updateRelations :: P.SourcePos
-> Maybe (SubstituteState (Either ErrorType ()))
-> (Annotation -> P.SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> SubstituteState (Either ErrorType ())
updateRelations pos f stmnt defs anns = do
(a, ((rs, mp), usts)) <- get
x <- mapM (updateSingleRelation pos f stmnt defs anns) $ Map.keys rs
case sequence x of
Right _ -> return $ Right ()
Left err -> return $ Left err
addRelation :: SourcePos
-> Maybe (SubstituteState (Either ErrorType ()))
-> (Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> Annotation
-> Annotation
-> SubstituteState (Either a ())
addRelation pos stmnt f defs anns r nv = do
(a, ((rs, mp), usts)) <- get
case Map.lookup r rs of
Just rl -> do
let nrs = Map.insert r (rl `Set.union` Set.singleton nv) rs
put (a, ((nrs, mp), usts))
Right () <$ updateSingleRelation pos stmnt f defs anns r
Nothing -> do
let nrs = Map.insert r (Set.singleton nv) rs
put (a, ((nrs, mp), usts))
Right () <$ updateSingleRelation pos stmnt f defs anns r
applyConstraintState :: SourcePos
-> Maybe (SubstituteState (Either ErrorType ()))
-> (Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation -> Annotations Annotation -> Annotation ->
Constraint -> SubstituteState (Either ErrorType Annotation)
applyConstraintState pos stmnt f defs anns ann (ConstraintHas lhs cn) =
do
mp <- getTypeMap
case ann of
StructAnnotation mp ->
case lhs `Map.lookup` mp of
Just ann -> applyConstraintState pos stmnt f defs anns ann cn
Nothing -> return . Left $ FieldNotFound lhs ann pos
Annotation id ->
case LhsIdentifer id pos `Map.lookup` mp of
Just ann -> applyConstraintState pos stmnt f defs anns ann cn
Nothing -> return . Left $ NoTypeFound id pos
NewTypeInstanceAnnotation id args ->
accessNewType anns args
(\(NewTypeAnnotation _ _ ps) ->
case Map.lookup lhs ps of
Just ann -> applyConstraintState pos stmnt f defs anns ann cn
Nothing -> return . Left $ FieldNotFound lhs ann pos
)
(LhsIdentifer id pos)
g@(GenericAnnotation id cns) -> case genericHas pos g lhs cns of
Right ann -> applyConstraintState pos stmnt f defs anns ann cn
Left err -> return $ Left err
g@(RigidAnnotation id cns) -> case genericHas pos g lhs cns of
Right ann -> applyConstraintState pos stmnt f defs anns ann cn
Left err -> return $ Left err
t@TypeUnion{} -> typeUnionHas pos stmnt f defs anns t cn >>= \case
Right ann -> applyConstraintState pos stmnt f defs anns ann cn
Left err -> return $ Left err
a -> return . Left $ UnsearchableType lhs a pos
applyConstraintState pos stmnt f defs anns ann2 (AnnotationConstraint ann1) = do
a <- if isGenericAnnotation ann2 && isGenericAnnotation ann1 then addRelation pos stmnt f defs anns ann2 ann1 *> addRelation pos stmnt f defs anns ann1 ann2 $> Right ann1 else addTypeVariable pos f defs anns stmnt ann1 ann2
case a of
Right _ -> specifyInternal pos stmnt f defs anns ann1 ann2
Left err -> return $ Left err
typeUnionHas pos stmnt f defs anns (TypeUnion st) cn = (\case
Left err -> return $ Left err
Right stl -> do
a <- sequence <$> mapM (flip (applyConstraintState pos stmnt f defs anns) cn) stl
case a of
Right (x:_) -> return $ Right x
Left err -> return $ Left err
) . sequence =<< mapM (flip (applyConstraintState pos stmnt f defs anns) cn) stl where stl = Set.toList st
typeUnionHas _ _ _ _ _ t _ = error $ "typeUnionHas can only be called with type union, not " ++ show t
isValidNewTypeInstance = undefined
isGeneralizedInstance pos anns ann@(NewTypeInstanceAnnotation id1 anns1) = do
a <- fullAnotationFromInstance pos anns ann
case a of
Right (NewTypeAnnotation id2 anns2 _) -> return $ id1 == id2 && length anns1 < length anns2
Right _ -> return False
Left err -> return False
isGeneralizedInstance _ a b = error $ "Unexpected argments for isGeneralizedInstance [" ++ show a ++ ", " ++ show b ++ "]"
isGeneralizedInstanceFree :: SourcePos -> Annotations Annotation -> Annotation -> Map.Map Lhs Annotation -> Bool
isGeneralizedInstanceFree pos anns ann@(NewTypeInstanceAnnotation id1 anns1) mp =
case fullAnotationFromInstanceFree pos anns mp ann of
Right (NewTypeAnnotation id2 anns2 _) -> id1 == id2 && length anns1 < length anns2
Right _ -> False
Left err -> False
isGeneralizedInstanceFree _ a b c = error $ "Unexpected argments for isGeneralizedInstance [" ++ show a ++ ", " ++ show b ++ ", " ++ show c ++ "]"
specifyInternal :: SourcePos
-> Maybe (SubstituteState (Either ErrorType ()))
-> (Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> Annotation
-> Annotation
-> SubstituteState (Either ErrorType Annotation)
specifyInternal pos stmnt f defs anns a@AnnotationLiteral{} b@AnnotationLiteral{} = (\mp -> return $ sameTypes pos mp a b *> Right a) =<< gets (snd . snd)
specifyInternal pos stmnt f defs anns a@(RigidAnnotation id1 cns1) b@(RigidAnnotation id2 cns2)
| id1 == id2 = (b <$) <$> (sequence <$> mapM (applyConstraintState pos stmnt f defs anns b) cns1)
| otherwise = return . Left $ UnmatchedType a b pos
specifyInternal pos stmnt f defs anns a@(GenericAnnotation id cns) b@(AnnotationLiteral ann) = do
mp <- getTypeMap
ann <- addTypeVariable pos f defs anns stmnt a b
case ann of
Right ann ->
(\case
Right _ -> return $ Right b
Left err -> return $ Left err) . sequence =<< mapM (applyConstraintState pos stmnt f defs anns ann) cns
Left err -> return $ Left err
specifyInternal pos stmnt f defs anns a@(GenericAnnotation id cns) b@(Annotation ann) = do
anno <- getTypeState b pos
case anno of
Right ann -> specifyInternal pos stmnt f defs anns a ann
Left err -> return $ Left err
specifyInternal pos stmnt f defs anns a@(Annotation id1) b@(Annotation id2)
| id1 == id2 = return $ Right b
| otherwise = (\mp -> case Map.lookup (LhsIdentifer id1 pos) mp of
Just a' -> case Map.lookup (LhsIdentifer id2 pos) mp of
Just b' -> specifyInternal pos stmnt f defs anns a' b'
Nothing -> return . Left $ NoTypeFound id2 pos
Nothing -> return . Left $ NoTypeFound id1 pos) =<< getTypeMap
specifyInternal pos stmnt f defs anns a@(Annotation id) b = (\mp -> case Map.lookup (LhsIdentifer id pos) mp of
Just a' -> specifyInternal pos stmnt f defs anns a' b
Nothing -> return . Left $ NoTypeFound id pos) =<< getTypeMap
specifyInternal pos stmnt f defs anns a b@(Annotation id) = (\mp -> case Map.lookup (LhsIdentifer id pos) mp of
Just b' -> specifyInternal pos stmnt f defs anns a b'
Nothing -> return . Left $ NoTypeFound id pos) =<< getTypeMap
specifyInternal pos stmnt f defs anns a@(GenericAnnotation id1 cns1) b@(GenericAnnotation id2 cns2) = do
(\case
Right _ -> addRelation pos stmnt f defs anns b a *> addRelation pos stmnt f defs anns a b $> Right b
Left err -> return $ Left err
) . sequence =<< mapM (applyConstraintState pos stmnt f defs anns b) cns1
specifyInternal pos stmnt f defs anns a@(GenericAnnotation id cns) b@(TypeUnion st) = (\case
Right _ -> do
a <- addTypeVariable pos f defs anns stmnt a b
case a of
Right _ -> return $ Right b
Left err -> return $ Left err
Left err -> return $ Left err) . sequence =<< mapM (applyConstraintState pos stmnt f defs anns b) cns
specifyInternal pos stmnt f defs anns a@(StructAnnotation ms1) b@(StructAnnotation ms2)
| Map.size ms1 /= Map.size ms2 = return . Left $ UnmatchedType a b pos
| Map.null ms1 && Map.null ms2 = return $ Right b
| Set.fromList (Map.keys ms1) == Set.fromList (Map.keys ms2) = (\case
Right _ -> return $ Right b
Left err -> return $ Left err) . sequence =<< zipWithM (specifyInternal pos stmnt f defs anns) (Map.elems ms1) (Map.elems ms2)
specifyInternal pos stmnt f defs anns a@(OpenFunctionAnnotation oargs oret _ _) b@(FunctionAnnotation args ret)
| length args /= length oargs = return . Left $ CallError oargs args pos
| otherwise = (\case
Right _ -> return $ Right b
Left err -> return $ Left err
) . sequence =<< zipWithM (specifyInternal pos stmnt f defs anns) (oargs ++ [oret]) (args ++ [ret])
specifyInternal pos stmnt f defs anns a@(FunctionAnnotation oargs oret) b@(FunctionAnnotation args ret)
| length args /= length oargs = return . Left $ CallError oargs args pos
| otherwise = (\case
Right _ -> return $ Right b
Left err -> return $ Left err
) . sequence =<< zipWithM (specifyInternal pos stmnt f defs anns) (oargs ++ [oret]) (args ++ [ret])
specifyInternal pos stmnt f defs anns a@(NewTypeAnnotation id1 anns1 _) b@(NewTypeInstanceAnnotation id2 anns2)
| id1 /= id2 = return . Left $ UnmatchedType a b pos
| otherwise = do
(_, ((_, mp), usts)) <- get
specifyInternal pos stmnt (const mergedTypeConcreteEither) defs anns (NewTypeInstanceAnnotation id1 anns1) b
where
fx rels = do
mapM_ sequence_ <$> sequence (Map.map sequence <$> Map.mapWithKey (\k v -> map (\a ->
addRelation pos stmnt f defs anns k a >>= \case
Right _ -> addRelation pos stmnt f defs anns a k
Left err -> return $ Left err) v) $ Map.map Set.toList rels)
specifyInternal pos stmnt f defs anns a@(NewTypeInstanceAnnotation id1 anns1) b@(NewTypeInstanceAnnotation id2 anns2)
| id1 /= id2 = (\mp -> return $ sameTypes pos mp a b) =<< getTypeMap
| otherwise = do
pred <- isGeneralizedInstance pos anns a
if pred then do
x <- fullAnotationFromInstance pos anns a
case x of
Right ntp@(NewTypeAnnotation id _ mp) -> specifyInternal pos stmnt f defs anns ntp b
Right _ -> return . Left $ NoTypeFound id1 pos
Left err -> return $ Left err
else (\case
Right _ -> return $ Right b
Left err -> return $ Left err
) . sequence =<< zipWithM (specifyInternal pos stmnt f defs anns) anns1 anns2
specifyInternal pos stmnt fa defs anns a@(TypeUnion _as) b@(TypeUnion _bs) = do
mp <- getTypeMap
case (foldr1 (mergedTypeConcrete pos mp) _as, foldr1 (mergedTypeConcrete pos mp) _bs) of
(TypeUnion as, TypeUnion bs) -> do
xs <- sequence <$> mapM (f mp $ Set.toList _as) (Set.toList _bs)
case xs of
Right _ -> return $ Right b
Left _ -> do
xs <- sequence <$> mapM (f mp $ Set.toList as) (Set.toList bs)
case xs of
Right _ -> return $ Right b
Left err -> if Set.size as == Set.size bs && Set.null (collectGenenrics mp a) then return $ Left err
else distinctUnion mp err (Set.toList $ collectGenenrics mp a)
(a, b) -> specifyInternal pos stmnt fa defs anns a b
where
f mp ps2 v1 = getFirst a b pos $ map (\x -> specifyInternal pos stmnt (const sameTypes) defs anns x v1) ps2
typeUnionList (TypeUnion xs) action = action $ Set.toList xs
typeUnionList a action = specifyInternal pos stmnt (const sameTypes) defs anns a b
g mp ps2 v1 = map (\x -> (specifyInternal pos stmnt (const sameTypes) defs x v1, x)) ps2
isRightLifted s = isRight <$> s
distinctUnion _ err [] = return $ Left err
distinctUnion mp _ xs = do
let as' = match ++ left where (match, left) = partition (isGeneric pos mp) (Set.toList _as)
let bs' = match ++ left where (match, left) = partition (isGeneric pos mp) (Set.toList _bs)
usts <- getTypeMap
c1 <- specifyInternal pos stmnt (const sameTypes) defs anns (head xs) (foldr1 (mergedTypeConcrete pos usts) $ take (length xs) as')
c2 <- sequence <$> zipWithM (flip (specifyInternal pos stmnt (const sameTypes) defs anns)) (tail xs) (drop (length xs) as')
case (c1, c2) of
(Right _, Right _) -> return $ Right $ mergedTypeConcrete pos usts b b
(Left err, _) -> return $ Left err
(_, Left err) -> return $ Left err
specifyInternal pos stmnt f defs anns a b@(TypeUnion st) = do
x <- sequence <$> mapM (flip (specifyInternal pos stmnt f defs anns) a) stl
case x of
Right a -> return . Right $ head a
Left err -> return $ Left err
where stl = Set.toList st
specifyInternal pos stmnt f defs anns a@(TypeUnion st) b = getFirst a b pos $ map (flip (specifyInternal pos stmnt f defs anns) b) $ Set.toList st
specifyInternal pos stmnt f defs anns a@(GenericAnnotation id cns) b =
(\case
Right _ -> do
a <- addTypeVariable pos f defs anns stmnt a b
case a of
Right _ -> return $ Right b
Left err -> return $ Left err
Left err -> return $ Left err) . sequence =<< mapM (applyConstraintState pos stmnt f defs anns b) cns
specifyInternal pos _ _ _ _ a b = (\mp -> return $ sameTypes pos mp a b) =<< getTypeMap
getFirst a b pos [] = return . Left $ UnmatchedType a b pos
getFirst a b pos (x:xs) = x >>= \case
Right a -> return $ Right a
Left _ -> getFirst a b pos xs
basicSpecifyFunction :: Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation
basicSpecifyFunction _ pos usts a b = sameTypesGeneric (False, True, True, Map.empty) pos usts a b $> b
-- specify :: SourcePos -> Set.Set Annotation -> Map.Map Annotation Annotation -> UserDefinedTypes -> Annotation -> Annotation -> Either String (Annotation, TypeRelations)
specifyGeneralized pos f defs anns base mp a b = (,rel) <$> ann where (ann, (ann1, ((rel, nmp), usts))) = runState (specifyInternal pos Nothing f defs anns a b) (a, ((Map.empty, base), mp))
specify :: SourcePos -> TwoSets Annotation -> Annotations Annotation -> Map.Map Annotation Annotation -> Map.Map Lhs Annotation -> Annotation -> Annotation -> Either ErrorType (Annotation, TypeRelations)
specify pos = specifyGeneralized pos basicSpecifyFunction
getPartialSpecificationRules :: SourcePos -> TwoSets Annotation -> Annotations Annotation -> Map.Map Annotation Annotation -> UserDefinedTypes -> Annotation -> Annotation -> (Map.Map Annotation Annotation, TypeRelations)
getPartialSpecificationRules pos defs anns base mp a b = (nmp, rel) where (ann, (ann1, ((rel, nmp), usts))) = runState (specifyInternal pos Nothing basicSpecifyFunction defs anns a b) (a, ((Map.empty, base), mp))
getPartialNoUnderScoreSpecificationRules :: SourcePos -> TwoSets Annotation -> Annotations Annotation -> Map.Map Annotation Annotation -> UserDefinedTypes -> Annotation -> Annotation -> (Map.Map Annotation Annotation, TypeRelations)
getPartialNoUnderScoreSpecificationRules pos defs anns base mp a b =
(Map.mapWithKey (\k a -> if a == AnnotationLiteral "_" then k else a) nmp, rel) where (nmp, rel) = getPartialSpecificationRules pos defs anns base mp a b
getSpecificationRulesGeneralized :: SourcePos
-> (Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation)
-> TwoSets Annotation
-> Annotations Annotation
-> Map.Map Annotation Annotation
-> Map.Map Lhs Annotation
-> Annotation
-> Annotation
-> Either ErrorType (Annotation, Map.Map Annotation Annotation, TypeRelations)
getSpecificationRulesGeneralized pos f defs anns base mp a b = case fst st of
Right r -> Right (r, nmp, rel)
Left err -> Left err
where st@(ann, (ann1, ((rel, nmp), usts))) = runState (specifyInternal pos Nothing f defs anns a b) (a, ((Map.empty, base), mp))
getSpecificationRules :: SourcePos -> TwoSets Annotation -> Annotations Annotation -> Map.Map Annotation Annotation -> Map.Map Lhs Annotation -> Annotation-> Annotation -> Either ErrorType (Annotation, Map.Map Annotation Annotation, TypeRelations)
getSpecificationRules pos = getSpecificationRulesGeneralized pos basicSpecifyFunction
sameTypesGenericBool gs crt pos mp a b = case sameTypesGeneric gs pos mp a b of
Right _ -> True
Left _ -> False
sameTypesBool pos mp a b = case sameTypes pos mp a b of
Right _ -> True
Left _ -> False
specifyTypesBool pos defs anns base usts a b = case specify pos defs anns base usts a b of
Right _ -> True
Left _ -> False
isGenericAnnotation a = case a of
a@GenericAnnotation{} -> True
_ -> False
expectedUnion pos lhs ann = ExpectedSomething "union" (AnnotationLiteral $ show lhs) pos
fNode f x = head $ f [x]
earlyReturnToElse :: [Node] -> [Node]
earlyReturnToElse [] = []
earlyReturnToElse (IfStmnt c ts [] pos:xs) =
if isReturn $ last ts then [IfStmnt c (earlyReturnToElse ts) (earlyReturnToElse xs) pos]
else IfStmnt c (earlyReturnToElse ts) [] pos : earlyReturnToElse xs
where
isReturn a@Return{} = True
isReturn _ = False
earlyReturnToElse (IfStmnt c ts es pos:xs) = IfStmnt c (earlyReturnToElse ts) (earlyReturnToElse es) pos : earlyReturnToElse xs
earlyReturnToElse (FunctionDef args ret ns pos:xs) = FunctionDef args ret (earlyReturnToElse ns) pos : earlyReturnToElse xs
earlyReturnToElse (DeclN (Decl lhs n ann pos):xs) = DeclN (Decl lhs (fNode earlyReturnToElse n) ann pos) : earlyReturnToElse xs
earlyReturnToElse (DeclN (Assign lhs n pos):xs) = DeclN (Assign lhs (fNode earlyReturnToElse n) pos) : earlyReturnToElse xs
earlyReturnToElse (x:xs) = x : earlyReturnToElse xs
freshDecl :: P.SourcePos -> Node -> TraversableNodeState Decl
freshDecl pos node = do
(i, xs) <- get
let id = LhsIdentifer ("__new_lifted_lambda_" ++ show i) pos
put (i+1, xs ++ [Decl id node Nothing pos])
return $ Decl id node Nothing pos
getDecls :: TraversableNodeState [Decl]
getDecls = get >>= \(_, xs) -> return xs
putDecls :: TraversableNodeState a -> TraversableNodeState a
putDecls action = do
modify $ \(a, _) -> (a, [])
action
inNewScope :: TraversableNodeState a -> TraversableNodeState a
inNewScope action = do
(a, xs) <- get
put (a+1, [])
res <- action
put (a, xs)
return res
lastRegisteredId :: TraversableNodeState String
lastRegisteredId = do
(i, _) <- get
return ("__new_lifted_lambda_" ++ show (i-1))
registerNode :: Node -> TraversableNodeState Node
registerNode n@(FunctionDef args ret body pos) = do
mbody <- inNewScope $ liftLambda body
decl <- freshDecl pos $ FunctionDef args ret mbody pos
id <- lastRegisteredId
return $ Identifier id pos
registerNode (IfStmnt c ts es pos) = putDecls $ do
cx <- registerNode c
tsx <- inNewScope $ liftLambda ts
esx <- inNewScope $ liftLambda es
return $ IfStmnt cx tsx esx pos
registerNode (Call e args pos) = Call <$> registerNode e <*> mapM registerNode args <*> return pos
registerNode (Return n pos) = flip Return pos <$> registerNode n
registerNode (StructN (Struct mp pos)) = StructN . flip Struct pos <$> mapM registerNode mp
registerNode (IfExpr c t e pos) = IfExpr <$> registerNode c <*> registerNode t <*> registerNode e <*> return pos
registerNode (Access n lhs pos) = flip Access lhs <$> registerNode n <*> return pos
registerNode (CreateNewType lhs args pos) = CreateNewType lhs <$> mapM registerNode args <*> return pos
registerNode a = return a
getRegister :: Node -> TraversableNodeState (Node, [Decl])
getRegister n = (,) <$> registerNode n <*> getDecls
liftLambda :: [Node] -> TraversableNodeState [Node]
liftLambda [] = return []
liftLambda (DeclN (ImplOpenFunction lhs args ret body ftr pos):xs) = putDecls $ do
rest <- liftLambda xs
(\mbody -> DeclN (ImplOpenFunction lhs args ret mbody ftr pos) : rest) <$> liftLambda body
liftLambda (DeclN opf@OpenFunctionDecl{}:xs) = (DeclN opf : ) <$> liftLambda xs
liftLambda (DeclN (Decl lhs (FunctionDef args ret body fpos) ann pos):xs) = putDecls $ do
mbody <- inNewScope $ liftLambda body
rest <- liftLambda xs
return $ DeclN (Decl lhs (FunctionDef args ret mbody fpos) ann pos) : rest
liftLambda (DeclN (Decl lhs n ann pos):xs) = putDecls $ do
getRegister n >>= \(x, ds) -> (map DeclN ds ++) . (DeclN (Decl lhs x ann pos) :) <$> liftLambda xs
liftLambda (DeclN (Assign lhs (FunctionDef args ret body fpos) pos):xs) = putDecls $ do
mbody <- inNewScope $ liftLambda body
rest <- liftLambda xs
return $ DeclN (Assign lhs (FunctionDef args ret mbody fpos) pos) : rest
liftLambda (DeclN (Assign lhs n pos):xs) =
putDecls $ getRegister n >>= \(x, ds) -> (map DeclN ds ++) . (DeclN (Assign lhs x pos) :) <$> liftLambda xs
liftLambda (DeclN (Expr n):xs) =
putDecls $ getRegister n >>= \(x, ds) -> (map DeclN ds ++) . (DeclN (Expr x) :) <$> liftLambda xs
liftLambda (n:ns) = putDecls $ getRegister n >>= \(x, ds) -> (map DeclN ds ++) . (x :) <$> liftLambda ns
definitivelyReturns :: [Node] -> Bool
definitivelyReturns [] = False
definitivelyReturns (IfStmnt _ ts es _:ns) =
(definitivelyReturns ts && definitivelyReturns es) || definitivelyReturns ns
definitivelyReturns (Return{}:_) = True
definitivelyReturns (_:ns) = definitivelyReturns ns
initIdentLhs :: Lhs -> Lhs
initIdentLhs (LhsAccess acc p pos) = LhsIdentifer id pos where (Identifier id pos) = initIdent $ Access acc p pos
initIdentLhs n = error $ "Only call initIdent with " ++ show n
initIdent (Access id@Identifier{} _ _) = id
initIdent (Access x _ _) = initIdent x
initIdent n = error $ "Only call initIdent with " ++ show n
trimAccess (Access (Access id p pos) _ _) = Access id p pos
trimAccess n = error $ "Only call initIdent with " ++ show n
makeUnionIfNotSame pos a clhs lhs = do
case a of
Right a -> join $ (\b m ->
case b of
Left err -> return $ Left err
Right (AnnotationLiteral "_") -> modifyAnnotationState lhs a
Right b ->
do
x <- getTypeState a pos
case x of
Right a ->
case sameTypesImpl a pos m b a of
Left _ -> f a m (Right b)
Right _ -> return $ Right a
Left err -> return $ Left err
) <$> clhs <*> getTypeMap
Left err -> return $ Left err
where
f a m = \case
Right b -> modifyAnnotationState lhs $ mergedTypeConcrete pos m a b
Left err -> return $ Left err
modifyWhole :: [Lhs] -> Annotation -> Annotation -> AnnotationState a Annotation
modifyWhole (p:xs) whole@(StructAnnotation ps) given = case Map.lookup p ps of
Just a -> modifyWhole xs a given >>= \x -> return . StructAnnotation $ Map.insert p x ps
Nothing -> error $ "You should already know that " ++ show p ++ " is in " ++ show ps ++ " before comming here"
modifyWhole [] _ given = return given
listAccess n = reverse $ go n where
go (Access n lhs _) = lhs : listAccess n
go Identifier{} = []
makeImpl a b TypeUnion{} = a
makeImpl a b (NewTypeInstanceAnnotation _ xs) =
if isJust $ find isTypeUnion xs then a else b where
isTypeUnion TypeUnion{} = True
isTypeUnion _ = False
makeImpl a b _ = b
sameTypesImpl :: Annotation -> SourcePos -> UserDefinedTypes -> Annotation -> Annotation -> Either ErrorType Annotation
sameTypesImpl = makeImpl sameTypesNoUnionSpec sameTypes
matchingUserDefinedType :: P.SourcePos -> TwoSets Annotation -> Annotations Annotation -> UserDefinedTypes -> Annotation -> Maybe Annotation
matchingUserDefinedType pos defs anns usts t = (\(LhsIdentifer id _, _) -> Just $ Annotation id) =<< find (isRight . snd) (Map.mapWithKey (,) $ Map.map (flip (specify pos defs anns Map.empty usts) t) usts)
evaluateTExpr :: P.SourcePos -> UserDefinedTypes -> TypeDeductionExpr -> State Annotation (Either ErrorType Annotation)
evaluateTExpr pos usts (IsType _ ann) = do
typ <- get
case intersectionTypes True pos usts ann typ of
Right typ' -> put typ' $> Right typ'
Left err -> return $ Left err
evaluateTExpr pos usts (NotIsType _ ann) = do
typ <- get
case differenceTypes pos usts ann typ of
Right typ' -> put typ' $> Right typ'
Left err -> return $ Left err
evaluateTExpr pos usts (NegateTypeDeduction tExpr) = do
typ <- get
evaluateTExpr pos usts $ negatePredicateExpr tExpr
evaluateTExprTotal :: P.SourcePos -> UserDefinedTypes -> TypeDeductionExpr -> Annotation -> Either ErrorType Annotation
evaluateTExprTotal pos usts tExpr typLhs = res $> st
where
(res, st) = runState (evaluateTExpr pos usts tExpr') typLhs
tExpr' = simplify pos usts <$> tExpr
getAnnotationsState :: AnnotationState (Annotations (Finalizeable Annotation)) (Annotations Annotation)
getAnnotationsState = do
(_, ((_, anns), _)) <- get
return $ removeFinalization anns
getAssumptionType :: Node -> AnnotationState (Annotations (Finalizeable Annotation)) (Result ErrorType Annotation)
getAssumptionType (DeclN (Decl lhs n a _)) = case a of
Just a -> Right <$> insertAnnotation lhs (Finalizeable True a)
Nothing -> mapRight (getAssumptionType n) (fmap Right . insertAnnotation lhs . Finalizeable False)
getAssumptionType (DeclN (Assign lhs@(LhsAccess access p accPos) expr pos)) =
do
expcd <- getAssumptionType (Access access p accPos)
rhs <- getTypeStateFrom (getAssumptionType expr) pos
full <- getTypeStateFrom (getAnnotationState $ initIdentLhs lhs) pos
mp <- getTypeMap
case (full, expcd, rhs) of
(Right whole, Right expcd, Right rhs) ->
case sameTypesImpl rhs pos mp expcd rhs of
Right a -> return $ Right a
Left _ -> do
x <- modifyAccess mp pos (Access access p accPos) whole expcd rhs p access accPos getAssumptionType
case x of
Right x -> modifyAnnotationState (initIdentLhs lhs) x
Left err -> return $ Left err
(Left err, _, _) -> return $ Left err
(_, Left err, _) -> return $ Left err
(_, _, Left err) -> return $ Left err
getAssumptionType (DeclN (Assign lhs n pos)) = getAssumptionType n >>= \x -> makeUnionIfNotSame pos x (getAnnotationState lhs) lhs
getAssumptionType (DeclN (FunctionDecl lhs ann _)) = Right <$> insertAnnotation lhs (Finalizeable False ann)
getAssumptionType (CreateNewType lhs args pos) = do
mp <- getTypeMap
annotations <- getAnnotationsState
argsn <- sequence <$> mapM getAssumptionType args
case argsn of
Right as -> case Map.lookup lhs mp of
Just ntp@(NewTypeAnnotation id anns _) ->
if length anns == length args then
case join $ specify pos <$> Right (fromUnionLists (map (collectGenenrics mp) as, map (collectGenenricsHOF mp) as)) <*> Right annotations <*> Right Map.empty <*> Right mp <*> Right ntp <*> (NewTypeInstanceAnnotation id <$> argsn) of
Right as -> return $ NewTypeInstanceAnnotation id <$> argsn
Left err -> return $ Left err
else return . Left $ CallError anns as pos
Just a -> return . Left $ UninstantiableType a pos
Nothing -> return . Left $ NoTypeFound (show lhs) pos
Left err -> return $ Left err
getAssumptionType (DeclN (OpenFunctionDecl lhs ann _)) = Right <$> insertAnnotation lhs (Finalizeable False ann)
getAssumptionType (DeclN impl@(ImplOpenFunction lhs args (Just ret) ns implft pos)) = do
a <- getAnnotationState lhs
annotations <- getAnnotationsState
mp <- getTypeMap
case a of
Left err -> return $ Left err
Right a@(OpenFunctionAnnotation anns ret' ft impls) -> do
let b = makeFunAnnotation args ret
case getSpecificationRules pos (TwoSets (collectGenenrics mp implft) (collectGenenricsHOF mp implft)) annotations Map.empty mp ft implft of
Right (_, base, _) ->
case getSpecificationRules pos (fromUnionLists (map (collectGenenrics mp) (ret:map snd args), map (collectGenenricsHOF mp) (ret:map snd args))) annotations base mp a b of
Left err -> return $ Left err