never executed always true always false
1 {-# LANGUAGE QuasiQuotes #-}
2
3 module Conjure.Representations.Variant
4 ( variant
5 ) where
6
7 -- conjure
8 import Conjure.Prelude
9 import Conjure.Bug
10 import Conjure.Language
11 import Conjure.Representations.Internal
12 import Conjure.Language.ZeroVal ( EnumerateDomain, zeroVal )
13
14
15 variant :: forall m . (MonadFailDoc m, NameGen m, EnumerateDomain m) => Representation m
16 variant = Representation chck downD structuralCons downC up symmetryOrdering
17
18 where
19
20 chck :: TypeOf_ReprCheck m
21 chck f (DomainVariant ds) = do
22 let names = map fst ds
23 outDoms <- sequence <$> mapM (f . snd) ds
24 return [ DomainVariant (zip names ds') | ds' <- outDoms ]
25 chck _ _ = return []
26
27 mkName name n = mconcat [name, "_", n]
28
29 downD :: TypeOf_DownD m
30 downD (name, DomainVariant ds) = return $ Just
31 $ (mkName name "_tag", defRepr $ mkDomainIntB 1 (fromInt (genericLength ds)))
32 : [ (mkName name n, d)
33 | (n,d) <- ds
34 ]
35 downD _ = na "{downD}"
36
37 structuralCons :: TypeOf_Structural m
38 structuralCons f downX1 (DomainVariant ds) = do
39 let
40 innerStructuralCons which thisIndex thisRef thisDom = do
41 let activeZone b = [essence| &which = &thisIndex -> &b |]
42 -- preparing structural constraints for the inner guys
43 innerStructuralConsGen <- f thisDom
44 outs <- innerStructuralConsGen thisRef
45 return (map activeZone outs)
46
47 dontCares which thisIndex thisRef =
48 [essence| &which != &thisIndex -> dontCare(&thisRef) |]
49
50 return $ \ rec -> do
51 (which:refs) <- downX1 rec
52 concat <$> sequence
53 [ do
54 isc <- innerStructuralCons which (fromInt i) ref dom
55 let dcs = dontCares which (fromInt i) ref
56 return (dcs:isc)
57 | (i, ref, (_, dom)) <- zip3 [1..] refs ds
58 ]
59 structuralCons _ _ _ = na "{structuralCons} variant"
60
61 -- TODO: check if (length ds == length cs)
62 downC :: TypeOf_DownC m
63 downC (name, DomainVariant ds, ConstantAbstract (AbsLitVariant _ n c)) = do
64 let theTag =
65 ( mkName name "_tag"
66 , defRepr $ mkDomainIntB 1 (fromInt (genericLength ds))
67 , case [ fromInt i
68 | (i, (n', _)) <- zip [1..] ds
69 , n == n' ] of
70 [v] -> v
71 _ -> bug "downC variant tag"
72 )
73 outs <- forM ds $ \ (n', d) -> do
74 c' <- if n == n'
75 then return c
76 else zeroVal d
77 return (mkName name n', d, c')
78 return $ Just (theTag : outs)
79 downC (n, d, c) =
80 na $ "{downC} variant" <+> vcat
81 [ "name :" <+> pretty n
82 , "domain:" <+> pretty d
83 , "value :" <+> pretty c
84 ]
85
86 up :: TypeOf_Up m
87 up ctxt (name, DomainVariant ds) = do
88 let dsForgotten = [ (n, defRepr d) | (n,d) <- ds ]
89 case lookup (mkName name "_tag") ctxt of
90 Just (ConstantInt _ i) ->
91 let iTag = at ds (fromInteger (i-1)) |> fst
92 iName = mkName name iTag
93 in case lookup iName ctxt of
94 Just val -> return (name, ConstantAbstract $ AbsLitVariant (Just dsForgotten) iTag val)
95 Nothing -> failDoc $ vcat $
96 [ "(in Variant up 1)"
97 , "No value for:" <+> pretty iName
98 , "When working on:" <+> pretty name
99 , "With domain:" <+> pretty (DomainRecord ds)
100 ] ++
101 ("Bindings in context:" : prettyContext ctxt)
102 Nothing -> failDoc $ vcat $
103 [ "(in Variant up 2)"
104 , "No value for:" <+> pretty (mkName name "_tag")
105 , "When working on:" <+> pretty name
106 , "With domain:" <+> pretty (DomainRecord ds)
107 ] ++
108 ("Bindings in context:" : prettyContext ctxt)
109 Just val -> failDoc $ vcat $
110 [ "Expecting an integer value for:" <+> pretty (mkName name "_tag")
111 , "When working on:" <+> pretty name
112 , "With domain:" <+> pretty (DomainRecord ds)
113 , "But got:" <+> pretty val
114 ] ++
115 ("Bindings in context:" : prettyContext ctxt)
116 up _ _ = na "{up}"
117
118 symmetryOrdering :: TypeOf_SymmetryOrdering m
119 symmetryOrdering innerSO downX1 inp domain = do
120 xs <- downX1 inp
121 Just xsDoms' <- downD ("SO", domain)
122 let xsDoms = map snd xsDoms'
123 soValues <- sequence [ innerSO downX1 x xDom | (x, xDom) <- zip xs xsDoms ]
124 return (fromList soValues)
125