@@ -17,6 +17,7 @@ import Data.ByteString.Char8 (ByteString, pack)
17
17
import Data.Map (Map )
18
18
import Data.Map qualified as Map
19
19
20
+ import Booster.Builtin.BOOL (boolTerm )
20
21
import Booster.Builtin.Base
21
22
import Booster.Builtin.INT
22
23
import Booster.Definition.Attributes.Base (
@@ -29,10 +30,48 @@ builtinsLIST :: Map ByteString BuiltinFunction
29
30
builtinsLIST =
30
31
Map. mapKeys (" LIST." <> ) $
31
32
Map. fromList
32
- [ " get" ~~> listGetHook
33
+ [ " concat" ~~> listConcatHook
34
+ , " element" ~~> listElementHook
35
+ , " get" ~~> listGetHook
36
+ , " in" ~~> listInHook
37
+ , " make" ~~> listMakeHook
38
+ , " range" ~~> listRangeHook
33
39
, " size" ~~> listSizeHook
40
+ , " unit" ~~> listUnitHook
41
+ , " update" ~~> listUpdateHook
34
42
]
35
43
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
+
36
75
listGetHook :: BuiltinFunction
37
76
listGetHook [KList _ heads mbRest, intArg] =
38
77
let headLen = length heads
@@ -67,6 +106,55 @@ listGetHook [_other, _] =
67
106
listGetHook args =
68
107
arityError " LIST.get" 2 args
69
108
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
+
70
158
listSizeHook :: BuiltinFunction
71
159
listSizeHook = \ case
72
160
[KList _ heads Nothing ] ->
@@ -78,6 +166,29 @@ listSizeHook = \case
78
166
moreArgs ->
79
167
arityError " LIST.size" 1 moreArgs
80
168
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
+
81
192
kItemListDef :: KListDefinition
82
193
kItemListDef =
83
194
KListDefinition
0 commit comments