@@ -17,6 +17,7 @@ import Data.ByteString.Char8 (ByteString, pack)
1717import Data.Map (Map )
1818import Data.Map qualified as Map
1919
20+ import Booster.Builtin.BOOL (boolTerm )
2021import Booster.Builtin.Base
2122import Booster.Builtin.INT
2223import Booster.Definition.Attributes.Base (
@@ -29,10 +30,48 @@ builtinsLIST :: Map ByteString BuiltinFunction
2930builtinsLIST =
3031 Map. mapKeys (" LIST." <> ) $
3132 Map. fromList
32- [ " get" ~~> listGetHook
33+ [ " concat" ~~> listConcatHook
34+ , " element" ~~> listElementHook
35+ , " get" ~~> listGetHook
36+ , " in" ~~> listInHook
37+ , " make" ~~> listMakeHook
38+ , " range" ~~> listRangeHook
3339 , " size" ~~> listSizeHook
40+ , " unit" ~~> listUnitHook
41+ , " update" ~~> listUpdateHook
3442 ]
3543
44+ -- | concatenate two lists
45+ listConcatHook :: BuiltinFunction
46+ listConcatHook [KList def1 heads1 rest1, KList def2 heads2 rest2]
47+ -- see Booster.Pattern.Base.internaliseKList
48+ | def1 /= def2 =
49+ pure Nothing -- actually a compiler error
50+ | Nothing <- rest1
51+ , Nothing <- rest2 =
52+ pure $ Just $ KList def1 (heads1 <> heads2) Nothing
53+ | Nothing <- rest1 =
54+ pure $ Just $ KList def2 (heads1 <> heads2) rest2
55+ | Nothing <- rest2
56+ , Just (mid1, tails1) <- rest1 =
57+ pure $ Just $ KList def1 heads1 $ Just (mid1, tails1 <> heads2)
58+ | otherwise -- opaque middle in both lists, unable to simplify
59+ =
60+ pure Nothing
61+ listConcatHook [KList def1 heads Nothing , other] =
62+ pure $ Just $ KList def1 heads (Just (other, [] ))
63+ listConcatHook [other, KList def2 heads Nothing ] =
64+ pure $ Just $ KList def2 [] (Just (other, heads))
65+ listConcatHook other =
66+ arityError " LIST.concat" 2 other
67+
68+ -- | create a singleton list from a given element
69+ listElementHook :: BuiltinFunction
70+ listElementHook [elem'] =
71+ pure $ Just $ KList kItemListDef [elem'] Nothing
72+ listElementHook other =
73+ arityError " LIST.element" 1 other
74+
3675listGetHook :: BuiltinFunction
3776listGetHook [KList _ heads mbRest, intArg] =
3877 let headLen = length heads
@@ -67,6 +106,55 @@ listGetHook [_other, _] =
67106listGetHook args =
68107 arityError " LIST.get" 2 args
69108
109+ listInHook :: BuiltinFunction
110+ listInHook [e, KList _ heads rest] =
111+ case rest of
112+ Nothing -> pure $ Just $ boolTerm (e `elem` heads)
113+ Just (_mid, tails)
114+ | e `elem` tails ->
115+ pure $ Just $ boolTerm True
116+ | otherwise -> -- could be in opaque _mid
117+ pure Nothing
118+ listInHook args =
119+ arityError " LIST.in" 2 args
120+
121+ listMakeHook :: BuiltinFunction
122+ listMakeHook [intArg, value] =
123+ case fromIntegral <$> readIntTerm intArg of
124+ Nothing ->
125+ intArg `shouldHaveSort` " SortInt" >> pure Nothing
126+ Just len ->
127+ pure $ Just $ KList kItemListDef (replicate len value) Nothing
128+ listMakeHook args =
129+ arityError " LIST.make" 2 args
130+
131+ listRangeHook :: BuiltinFunction
132+ listRangeHook [KList def heads rest, fromFront, fromBack] =
133+ case (fromIntegral <$> readIntTerm fromFront, fromIntegral <$> readIntTerm fromBack) of
134+ (Nothing , _) ->
135+ fromFront `shouldHaveSort` " SortInt" >> pure Nothing
136+ (_, Nothing ) ->
137+ fromBack `shouldHaveSort` " SortInt" >> pure Nothing
138+ (Just frontDrop, Just backDrop)
139+ | frontDrop < 0 -> pure Nothing -- bottom
140+ | backDrop < 0 -> pure Nothing -- bottom
141+ | Nothing <- rest -> do
142+ let targetLen = length heads - frontDrop - backDrop
143+ if targetLen < 0
144+ then pure Nothing -- bottom
145+ else do
146+ let part = take targetLen $ drop frontDrop heads
147+ pure $ Just $ KList def part Nothing
148+ | Just (mid, tails) <- rest ->
149+ if length tails < backDrop
150+ then pure Nothing -- opaque middle, cannot drop from back
151+ else do
152+ let heads' = drop frontDrop heads
153+ tails' = reverse $ drop backDrop $ reverse tails
154+ pure $ Just $ KList def heads' $ Just (mid, tails')
155+ listRangeHook args =
156+ arityError " LIST.range" 3 args
157+
70158listSizeHook :: BuiltinFunction
71159listSizeHook = \ case
72160 [KList _ heads Nothing ] ->
@@ -78,6 +166,29 @@ listSizeHook = \case
78166 moreArgs ->
79167 arityError " LIST.size" 1 moreArgs
80168
169+ listUnitHook :: BuiltinFunction
170+ listUnitHook [] = pure $ Just $ KList kItemListDef [] Nothing
171+ listUnitHook args =
172+ arityError " LIST.unit" 0 args
173+
174+ listUpdateHook :: BuiltinFunction
175+ listUpdateHook [KList def heads rest, intArg, value] =
176+ case fromIntegral <$> readIntTerm intArg of
177+ Nothing ->
178+ intArg `shouldHaveSort` " SortInt" >> pure Nothing
179+ Just idx
180+ | idx < 0 ->
181+ pure Nothing -- bottom
182+ | otherwise ->
183+ case splitAt idx heads of
184+ (front, _target : back) ->
185+ pure $ Just $ KList def (front <> (value : back)) rest
186+ (_heads, [] ) ->
187+ -- idx >= length heads, indeterminate
188+ pure Nothing
189+ listUpdateHook args =
190+ arityError " LIST.update" 3 args
191+
81192kItemListDef :: KListDefinition
82193kItemListDef =
83194 KListDefinition
0 commit comments