Traverse.hs 46.2 KB
Newer Older
1 2 3 4 5 6 7 8 9
{- sv2v
 - Author: Zachary Snow <zach@zachjs.com>
 -
 - Utilities for traversing AST transformations.
 -}

module Convert.Traverse
( MapperM
, Mapper
10
, CollectorM
11
, unmonad
12
, collectify
13
, mapBothM
14
, breakGenerate
15 16
, traverseDescriptionsM
, traverseDescriptions
17
, collectDescriptionsM
18 19
, traverseModuleItemsM
, traverseModuleItems
20
, collectModuleItemsM
21 22
, traverseStmtsM
, traverseStmts
23 24 25 26
, collectStmtsM
, traverseStmtLHSsM
, traverseStmtLHSs
, collectStmtLHSsM
27 28 29
, traverseExprsM
, traverseExprs
, collectExprsM
30
, traverseNodesM
31
, traverseNodes
32 33 34
, traverseStmtExprsM
, traverseStmtExprs
, collectStmtExprsM
35 36 37
, traverseLHSsM
, traverseLHSs
, collectLHSsM
38 39 40
, traverseDeclsM
, traverseDecls
, collectDeclsM
41 42 43
, traverseStmtDeclsM
, traverseStmtDecls
, collectStmtDeclsM
44 45 46
, traverseSinglyNestedTypesM
, traverseSinglyNestedTypes
, collectSinglyNestedTypesM
47 48 49
, traverseNestedTypesM
, traverseNestedTypes
, collectNestedTypesM
50 51 52
, traverseExprTypesM
, traverseExprTypes
, collectExprTypesM
53 54 55
, traverseTypeExprsM
, traverseTypeExprs
, collectTypeExprsM
56 57 58
, traverseGenItemExprsM
, traverseGenItemExprs
, collectGenItemExprsM
59 60
, traverseDeclNodesM
, traverseDeclNodes
61 62 63
, traverseDeclExprsM
, traverseDeclExprs
, collectDeclExprsM
64 65 66
, traverseDeclTypesM
, traverseDeclTypes
, collectDeclTypesM
67 68 69
, traverseTypesM
, traverseTypes
, collectTypesM
70 71 72
, traverseGenItemsM
, traverseGenItems
, collectGenItemsM
73
, traverseNestedGenItemsM
74
, traverseNestedGenItems
75 76 77
, traverseAsgnsM
, traverseAsgns
, collectAsgnsM
78 79 80
, traverseStmtAsgnsM
, traverseStmtAsgns
, collectStmtAsgnsM
81 82 83
, traverseNestedModuleItemsM
, traverseNestedModuleItems
, collectNestedModuleItemsM
84
, traverseNestedStmtsM
85
, traverseNestedStmts
86
, collectNestedStmtsM
87
, traverseNestedExprsM
88 89
, traverseNestedExprs
, collectNestedExprsM
90 91 92
, traverseSinglyNestedExprsM
, traverseSinglyNestedExprs
, collectSinglyNestedExprsM
93 94 95
, traverseLHSExprsM
, traverseLHSExprs
, collectLHSExprsM
96 97 98
, traverseNestedLHSsM
, traverseNestedLHSs
, collectNestedLHSsM
99 100 101
, traverseSinglyNestedLHSsM
, traverseSinglyNestedLHSs
, collectSinglyNestedLHSsM
102
, traverseFilesM
103
, traverseFiles
104 105
, traverseSinglyNestedGenItemsM
, traverseSinglyNestedStmtsM
106 107
, traverseSinglyNestedStmts
, collectSinglyNestedStmtsM
108 109 110
, traverseNetAsVarM
, traverseNetAsVar
, collectNetAsVarM
111 112
) where

113
import Data.Bitraversable (bimapM)
114
import Data.Functor.Identity (Identity, runIdentity)
115
import Control.Monad.Writer.Strict
116 117
import Language.SystemVerilog.AST

118
type MapperM m t = t -> m t
119
type Mapper t = t -> t
120
type CollectorM m t = t -> m ()
121

122 123
unmonad :: (MapperM Identity a -> MapperM Identity b) -> Mapper a -> Mapper b
unmonad traverser mapper = runIdentity . traverser (return . mapper)
124

125
collectify :: Monad m => (MapperM m a -> MapperM m b) -> CollectorM m a -> CollectorM m b
126 127
collectify traverser collector =
    traverser mapper >=> \_ -> return ()
128
    where mapper x = collector x >>= \() -> return x
129 130

traverseDescriptionsM :: Monad m => MapperM m Description -> MapperM m AST
131
traverseDescriptionsM = mapM
132
traverseDescriptions :: Mapper Description -> Mapper AST
133
traverseDescriptions = map
134
collectDescriptionsM :: Monad m => CollectorM m Description -> CollectorM m AST
135
collectDescriptionsM = mapM_
136

137 138 139 140 141 142 143 144 145 146
breakGenerate :: ModuleItem -> [ModuleItem] -> [ModuleItem]
breakGenerate (Generate genItems) items =
    foldr breakGenerateStep items genItems
breakGenerate item items = item : items

breakGenerateStep :: GenItem -> [ModuleItem] -> [ModuleItem]
breakGenerateStep (GenModuleItem item) items = item : items
breakGenerateStep genItem (Generate genItems : items) =
    Generate (genItem : genItems) : items
breakGenerateStep genItem items = Generate [genItem] : items
147

148
traverseModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m Description
149
traverseModuleItemsM mapper (Part attrs extern kw lifetime name ports items) = do
150
    items' <- mapM (traverseNestedModuleItemsM mapper) items
151
    let items'' = foldr breakGenerate [] items'
152
    return $ Part attrs extern kw lifetime name ports items''
153
    where
154 155
traverseModuleItemsM mapper (PackageItem packageItem) = do
    let item = MIPackageItem packageItem
156
    item' <- traverseNestedModuleItemsM mapper item
157 158 159
    return $ case item' of
        MIPackageItem packageItem' -> PackageItem packageItem'
        other -> error $ "encountered bad package module item: " ++ show other
160 161 162 163
traverseModuleItemsM mapper (Package lifetime name items) = do
    let itemsWrapped = map MIPackageItem items
    itemsWrapped' <- mapM (traverseNestedModuleItemsM mapper) itemsWrapped
    let items' = map (\(MIPackageItem item) -> item) $
164
                    foldr breakGenerate [] itemsWrapped'
165 166 167 168 169
    return $ Package lifetime name items'
traverseModuleItemsM mapper (Class lifetime name decls items) = do
    let declsWrapped = map (MIPackageItem . Decl) decls
    declsWrapped' <- mapM (traverseNestedModuleItemsM mapper) declsWrapped
    let decls' = map (\(MIPackageItem (Decl decl)) -> decl) $
170
                    foldr breakGenerate [] declsWrapped'
171
    items' <- fmap concat $ mapM indirect items
172
    return $ Class lifetime name decls' items'
173 174
    where
        indirect (qualifier, item) =
175
            fmap (map (unwrap qualifier) . flip breakGenerate []) $
176 177
            traverseNestedModuleItemsM mapper (MIPackageItem item)
        unwrap qualifier = \(MIPackageItem item) -> (qualifier, item)
178 179 180

traverseModuleItems :: Mapper ModuleItem -> Mapper Description
traverseModuleItems = unmonad traverseModuleItemsM
181 182
collectModuleItemsM :: Monad m => CollectorM m ModuleItem -> CollectorM m Description
collectModuleItemsM = collectify traverseModuleItemsM
183

184 185
traverseStmtsM :: Monad m => MapperM m Stmt -> MapperM m ModuleItem
traverseStmtsM mapper = moduleItemMapper
186 187
    where
        moduleItemMapper (AlwaysC kw stmt) =
188
            mapper stmt >>= return . AlwaysC kw
189
        moduleItemMapper (MIPackageItem (Function lifetime ret name decls stmts)) = do
190
            stmts' <- mapM mapper stmts
191
            return $ MIPackageItem $ Function lifetime ret name decls stmts'
192
        moduleItemMapper (MIPackageItem (Task lifetime name decls stmts)) = do
193
            stmts' <- mapM mapper stmts
194
            return $ MIPackageItem $ Task lifetime name decls stmts'
195
        moduleItemMapper (Initial stmt) =
196
            mapper stmt >>= return . Initial
197
        moduleItemMapper (Final stmt) =
198
            mapper stmt >>= return . Final
199
        moduleItemMapper other = return $ other
200 201

traverseStmts :: Mapper Stmt -> Mapper ModuleItem
202
traverseStmts = unmonad traverseStmtsM
203
collectStmtsM :: Monad m => CollectorM m Stmt -> CollectorM m ModuleItem
204
collectStmtsM = collectify traverseStmtsM
205 206 207

traverseNestedStmtsM :: Monad m => MapperM m Stmt -> MapperM m Stmt
traverseNestedStmtsM mapper = fullMapper
208
    where fullMapper = mapper >=> traverseSinglyNestedStmtsM fullMapper
209

210 211 212 213 214
traverseNestedStmts :: Mapper Stmt -> Mapper Stmt
traverseNestedStmts = unmonad traverseNestedStmtsM
collectNestedStmtsM :: Monad m => CollectorM m Stmt -> CollectorM m Stmt
collectNestedStmtsM = collectify traverseNestedStmtsM

215 216 217
traverseSinglyNestedStmtsM :: Monad m => MapperM m Stmt -> MapperM m Stmt
traverseSinglyNestedStmtsM fullMapper = cs
    where
218
        cs (StmtAttr a stmt) = fullMapper stmt >>= return . StmtAttr a
219
        cs (Block _ "" [] []) = return Null
220
        cs (Block _ "" [] [CommentStmt{}]) = return Null
Zachary Snow committed
221
        cs (Block _ "" [] [stmt]) = fullMapper stmt
222
        cs (Block _ "" [CommentDecl{}] []) = return Null
223 224 225 226 227 228 229
        cs (Block Seq name decls stmts) = do
            stmts' <- mapM fullMapper stmts
            return $ Block Seq name decls $ concatMap explode stmts'
            where
                explode :: Stmt -> [Stmt]
                explode (Block Seq "" [] ss) = ss
                explode other = [other]
230 231
        cs (Block kw name decls stmts) =
            mapM fullMapper stmts >>= return . Block kw name decls
232
        cs (Case u kw expr cases) = do
233 234
            caseStmts <- mapM fullMapper $ map snd cases
            let cases' = zip (map fst cases) caseStmts
235
            return $ Case u kw expr cases'
236
        cs (Asgn op mt lhs expr) = return $ Asgn op mt lhs expr
237
        cs (For a b c stmt) = fullMapper stmt >>= return . For a b c
238 239 240 241
        cs (While   e stmt) = fullMapper stmt >>= return . While   e
        cs (RepeatL e stmt) = fullMapper stmt >>= return . RepeatL e
        cs (DoWhile e stmt) = fullMapper stmt >>= return . DoWhile e
        cs (Forever   stmt) = fullMapper stmt >>= return . Forever
242
        cs (Foreach x vars stmt) = fullMapper stmt >>= return . Foreach x vars
243 244 245 246 247 248 249
        cs (If NoCheck (Number n) s1 s2) = do
            s1' <- fullMapper s1
            s2' <- fullMapper s2
            return $ case numberToInteger n of
                Nothing -> If NoCheck (Number n) s1' s2'
                Just 0 -> s2'
                Just _ -> s1'
250
        cs (If u e s1 s2) = do
251 252
            s1' <- fullMapper s1
            s2' <- fullMapper s2
253
            return $ If u e s1' s2'
254
        cs (Timing event stmt) = fullMapper stmt >>= return . Timing event
255
        cs (Return expr) = return $ Return expr
256
        cs (Subroutine expr exprs) = return $ Subroutine expr exprs
257
        cs (Trigger blocks x) = return $ Trigger blocks x
258 259
        cs (Assertion a) =
            traverseAssertionStmtsM fullMapper a >>= return . Assertion
260 261
        cs (Continue) = return Continue
        cs (Break) = return Break
262
        cs (Null) = return Null
263
        cs (CommentStmt c) = return $ CommentStmt c
264

265 266 267 268 269
traverseSinglyNestedStmts :: Mapper Stmt -> Mapper Stmt
traverseSinglyNestedStmts = unmonad traverseSinglyNestedStmtsM
collectSinglyNestedStmtsM :: Monad m => CollectorM m Stmt -> CollectorM m Stmt
collectSinglyNestedStmtsM = collectify traverseSinglyNestedStmtsM

270 271 272
traverseAssertionStmtsM :: Monad m => MapperM m Stmt -> MapperM m Assertion
traverseAssertionStmtsM mapper = assertionMapper
    where
273
        actionBlockMapper (ActionBlock s1 s2) = do
274 275
            s1' <- mapper s1
            s2' <- mapper s2
276
            return $ ActionBlock s1' s2'
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
        assertionMapper (Assert e ab) =
            actionBlockMapper ab >>= return . Assert e
        assertionMapper (Assume e ab) =
            actionBlockMapper ab >>= return . Assume e
        assertionMapper (Cover e stmt) =
            mapper stmt >>= return . Cover e

-- Note that this does not include the expressions without the statements of the
-- actions associated with the assertions.
traverseAssertionExprsM :: Monad m => MapperM m Expr -> MapperM m Assertion
traverseAssertionExprsM mapper = assertionMapper
    where
        seqExprMapper (SeqExpr e) =
            mapper e >>= return . SeqExpr
        seqExprMapper (SeqExprAnd        s1 s2) =
            ssMapper   SeqExprAnd        s1 s2
        seqExprMapper (SeqExprOr         s1 s2) =
            ssMapper   SeqExprOr         s1 s2
        seqExprMapper (SeqExprIntersect  s1 s2) =
            ssMapper   SeqExprIntersect  s1 s2
        seqExprMapper (SeqExprWithin     s1 s2) =
            ssMapper   SeqExprWithin     s1 s2
        seqExprMapper (SeqExprThroughout e s) = do
            e' <- mapper e
            s' <- seqExprMapper s
            return $ SeqExprThroughout e' s'
        seqExprMapper (SeqExprDelay ms e s) = do
            ms' <- case ms of
                Nothing -> return Nothing
                Just x -> seqExprMapper x >>= return . Just
            e' <- mapper e
            s' <- seqExprMapper s
            return $ SeqExprDelay ms' e' s'
        seqExprMapper (SeqExprFirstMatch s items) = do
            s' <- seqExprMapper s
            items' <- mapM seqMatchItemMapper items
            return $ SeqExprFirstMatch s' items'
314
        seqMatchItemMapper (SeqMatchAsgn (a, b, c)) = do
315
            c' <- mapper c
316 317
            return $ SeqMatchAsgn (a, b, c')
        seqMatchItemMapper (SeqMatchCall x (Args l p)) = do
Zachary Snow committed
318 319
            l' <- mapM mapper l
            pes <- mapM mapper $ map snd p
320
            let p' = zip (map fst p) pes
321
            return $ SeqMatchCall x (Args l' p')
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        ppMapper constructor p1 p2 = do
            p1' <- propExprMapper p1
            p2' <- propExprMapper p2
            return $ constructor p1' p2'
        ssMapper constructor s1 s2 = do
            s1' <- seqExprMapper s1
            s2' <- seqExprMapper s2
            return $ constructor s1' s2'
        spMapper constructor se pe = do
            se' <- seqExprMapper se
            pe' <- propExprMapper pe
            return $ constructor se' pe'
        propExprMapper (PropExpr se) =
            seqExprMapper se >>= return . PropExpr
        propExprMapper (PropExprImpliesO se pe) =
            spMapper PropExprImpliesO se pe
        propExprMapper (PropExprImpliesNO se pe) =
            spMapper PropExprImpliesNO se pe
        propExprMapper (PropExprFollowsO se pe) =
            spMapper PropExprFollowsO se pe
        propExprMapper (PropExprFollowsNO se pe) =
            spMapper PropExprFollowsNO se pe
        propExprMapper (PropExprIff p1 p2) =
            ppMapper PropExprIff p1 p2
Zachary Snow committed
346 347
        propSpecMapper (PropertySpec ms e pe) = do
            e' <- mapper e
348
            pe' <- propExprMapper pe
Zachary Snow committed
349
            return $ PropertySpec ms e' pe'
350 351 352 353
        assertionExprMapper (Concurrent e) =
            propSpecMapper e >>= return . Concurrent
        assertionExprMapper (Immediate d e) =
            mapper e >>= return . Immediate d
354 355 356 357 358 359 360 361 362 363
        assertionMapper (Assert e ab) = do
            e' <- assertionExprMapper e
            return $ Assert e' ab
        assertionMapper (Assume e ab) = do
            e' <- assertionExprMapper e
            return $ Assume e' ab
        assertionMapper (Cover e stmt) = do
            e' <- assertionExprMapper e
            return $ Cover e' stmt

364
traverseStmtLHSsM :: Monad m => MapperM m LHS -> MapperM m Stmt
365
traverseStmtLHSsM mapper = stmtMapper
366
    where
367
        fullMapper = mapper
368 369 370
        stmtMapper (Timing (Event sense) stmt) = do
            sense' <- senseMapper sense
            return $ Timing (Event sense') stmt
371
        stmtMapper (Asgn op (Just (Event sense)) lhs expr) = do
372 373
            lhs' <- fullMapper lhs
            sense' <- senseMapper sense
374 375 376
            return $ Asgn op (Just $ Event sense') lhs' expr
        stmtMapper (Asgn op mt lhs expr) =
            fullMapper lhs >>= \lhs' -> return $ Asgn op mt lhs' expr
377
        stmtMapper (For inits me incrs stmt) = do
378
            inits' <- mapM (bimapM fullMapper return) inits
379 380 381 382
            let (lhss, asgnOps, exprs) = unzip3 incrs
            lhss' <- mapM fullMapper lhss
            let incrs' = zip3 lhss' asgnOps exprs
            return $ For inits' me incrs' stmt
383 384
        stmtMapper (Assertion a) =
            assertionMapper a >>= return . Assertion
385
        stmtMapper other = return other
386 387 388 389 390 391 392 393
        senseMapper (Sense        lhs) = fullMapper lhs >>= return . Sense
        senseMapper (SensePosedge lhs) = fullMapper lhs >>= return . SensePosedge
        senseMapper (SenseNegedge lhs) = fullMapper lhs >>= return . SenseNegedge
        senseMapper (SenseOr    s1 s2) = do
            s1' <- senseMapper s1
            s2' <- senseMapper s2
            return $ SenseOr s1' s2'
        senseMapper (SenseStar       ) = return SenseStar
394
        assertionExprMapper (Concurrent (PropertySpec (Just sense) me pe)) = do
395
            sense' <- senseMapper sense
396 397
            return $ Concurrent $ PropertySpec (Just sense') me pe
        assertionExprMapper other = return other
398 399 400 401 402 403 404 405 406
        assertionMapper (Assert e ab) = do
            e' <- assertionExprMapper e
            return $ Assert e' ab
        assertionMapper (Assume e ab) = do
            e' <- assertionExprMapper e
            return $ Assume e' ab
        assertionMapper (Cover e stmt) = do
            e' <- assertionExprMapper e
            return $ Cover e' stmt
407 408 409 410 411

traverseStmtLHSs :: Mapper LHS -> Mapper Stmt
traverseStmtLHSs = unmonad traverseStmtLHSsM
collectStmtLHSsM :: Monad m => CollectorM m LHS -> CollectorM m Stmt
collectStmtLHSsM = collectify traverseStmtLHSsM
412 413 414

traverseNestedExprsM :: Monad m => MapperM m Expr -> MapperM m Expr
traverseNestedExprsM mapper = exprMapper
415 416 417 418 419 420 421 422 423
    where exprMapper = mapper >=> traverseSinglyNestedExprsM exprMapper

traverseNestedExprs :: Mapper Expr -> Mapper Expr
traverseNestedExprs = unmonad traverseNestedExprsM
collectNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr
collectNestedExprsM = collectify traverseNestedExprsM

traverseSinglyNestedExprsM :: Monad m => MapperM m Expr -> MapperM m Expr
traverseSinglyNestedExprsM exprMapper = em
424
    where
425
        typeOrExprMapper (Left t) = return $ Left t
426 427
        typeOrExprMapper (Right e) =
            exprMapper e >>= return . Right
428
        em (String s) = return $ String s
429 430
        em (Real   s) = return $ Real   s
        em (Number n) = return $ Number n
431
        em (Time   s) = return $ Time   s
432
        em (Ident  i) = return $ Ident  i
433
        em (PSIdent x y) = return $ PSIdent x y
434 435 436 437
        em (CSIdent x ps y) = do
            tes' <- mapM typeOrExprMapper $ map snd ps
            let ps' = zip (map fst ps) tes'
            return $ CSIdent x ps' y
438
        em (Range e m (e1, e2)) = do
439 440 441
            e' <- exprMapper e
            e1' <- exprMapper e1
            e2' <- exprMapper e2
442
            return $ Range e' m (e1', e2')
443
        em (Bit   e1 e2) = do
444 445
            e1' <- exprMapper e1
            e2' <- exprMapper e2
446
            return $ Bit e1' e2'
447 448 449 450 451 452
        em (Repeat     e l) = do
            e' <- exprMapper e
            l' <- mapM exprMapper l
            return $ Repeat e' l'
        em (Concat     l) =
            mapM exprMapper l >>= return . Concat
453 454 455 456
        em (Stream o e l) = do
            e' <- exprMapper e
            l' <- mapM exprMapper l
            return $ Stream o e' l'
457 458
        em (Call  e (Args l p)) = do
            e' <- exprMapper e
Zachary Snow committed
459 460
            l' <- mapM exprMapper l
            pes <- mapM exprMapper $ map snd p
461
            let p' = zip (map fst p) pes
462
            return $ Call e' (Args l' p')
463 464 465 466 467 468 469 470 471 472 473
        em (UniOp      o e) =
            exprMapper e >>= return . UniOp o
        em (BinOp      o e1 e2) = do
            e1' <- exprMapper e1
            e2' <- exprMapper e2
            return $ BinOp o e1' e2'
        em (Mux        e1 e2 e3) = do
            e1' <- exprMapper e1
            e2' <- exprMapper e2
            e3' <- exprMapper e3
            return $ Mux e1' e2' e3'
474 475 476 477
        em (Cast tore e) = do
            tore' <- typeOrExprMapper tore
            e' <- exprMapper e
            return $ Cast tore' e'
478 479 480 481 482 483
        em (DimsFn f tore) =
            typeOrExprMapper tore >>= return . DimsFn f
        em (DimFn f tore e) = do
            tore' <- typeOrExprMapper tore
            e' <- exprMapper e
            return $ DimFn f tore' e'
484 485
        em (Dot e x) =
            exprMapper e >>= \e' -> return $ Dot e' x
486
        em (Pattern l) = do
487
            names <- mapM typeOrExprMapper $ map fst l
488
            exprs <- mapM exprMapper $ map snd l
489
            return $ Pattern $ zip names exprs
490 491
        em (Inside e l) = do
            e' <- exprMapper e
492
            l' <- mapM exprMapper l
493
            return $ Inside e' l'
494 495 496 497 498
        em (MinTypMax e1 e2 e3) = do
            e1' <- exprMapper e1
            e2' <- exprMapper e2
            e3' <- exprMapper e3
            return $ MinTypMax e1' e2' e3'
499
        em (Nil) = return Nil
500

501 502 503 504 505
traverseSinglyNestedExprs :: Mapper Expr -> Mapper Expr
traverseSinglyNestedExprs = unmonad traverseSinglyNestedExprsM
collectSinglyNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr
collectSinglyNestedExprsM = collectify traverseSinglyNestedExprsM

506 507 508
traverseLHSExprsM :: Monad m => MapperM m Expr -> MapperM m LHS
traverseLHSExprsM exprMapper =
    lhsMapper
509
    where
510 511 512 513 514 515 516 517
        lhsMapper (LHSRange l m r) =
            mapBothM exprMapper r >>= return . LHSRange l m
        lhsMapper (LHSBit l e) =
            exprMapper e >>= return . LHSBit l
        lhsMapper (LHSStream o e ls) = do
            e' <- exprMapper e
            return $ LHSStream o e' ls
        lhsMapper other = return other
518

519 520 521 522 523
traverseLHSExprs :: Mapper Expr -> Mapper LHS
traverseLHSExprs = unmonad traverseLHSExprsM
collectLHSExprsM :: Monad m => CollectorM m Expr -> CollectorM m LHS
collectLHSExprsM = collectify traverseLHSExprsM

524
mapBothM :: Monad m => MapperM m t -> MapperM m (t, t)
Zachary Snow committed
525
mapBothM mapper = bimapM mapper mapper
526

527
traverseExprsM :: Monad m => MapperM m Expr -> MapperM m ModuleItem
528 529
traverseExprsM exprMapper =
    traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper
530
    where
531
    declMapper = traverseDeclNodesM typeMapper exprMapper
532 533
    typeMapper = traverseNestedTypesM (traverseTypeExprsM exprMapper)
    lhsMapper = traverseNestedLHSsM (traverseLHSExprsM exprMapper)
534
    stmtMapper = traverseNestedStmtsM (traverseStmtExprsM exprMapper)
535

536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
traverseExprs :: Mapper Expr -> Mapper ModuleItem
traverseExprs = unmonad traverseExprsM
collectExprsM :: Monad m => CollectorM m Expr -> CollectorM m ModuleItem
collectExprsM = collectify traverseExprsM

traverseNodesM
    :: Monad m
    => MapperM m Expr
    -> MapperM m Decl
    -> MapperM m Type
    -> MapperM m LHS
    -> MapperM m Stmt
    -> MapperM m ModuleItem
traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper =
    moduleItemMapper
    where

Zachary Snow committed
553 554
    portBindingMapper (p, e) =
        exprMapper e >>= \e' -> return (p, e')
555

556 557 558 559 560
    paramBindingMapper (p, Left t) =
        typeMapper t >>= \t' -> return (p, Left t')
    paramBindingMapper (p, Right e) =
        exprMapper e >>= \e' -> return (p, Right e')

561 562 563
    moduleItemMapper (MIAttr attr mi) =
        -- note: we exclude expressions in attributes from conversion
        return $ MIAttr attr mi
564 565
    moduleItemMapper (MIPackageItem (Decl decl)) =
        declMapper decl >>= return . MIPackageItem . Decl
566 567 568 569
    moduleItemMapper (Defparam lhs expr) = do
        lhs' <- lhsMapper lhs
        expr' <- exprMapper expr
        return $ Defparam lhs' expr'
570 571
    moduleItemMapper (AlwaysC kw stmt) =
        stmtMapper stmt >>= return . AlwaysC kw
572 573
    moduleItemMapper (Initial stmt) =
        stmtMapper stmt >>= return . Initial
574 575
    moduleItemMapper (Final stmt) =
        stmtMapper stmt >>= return . Final
576 577 578
    moduleItemMapper (Assign opt lhs expr) = do
        opt' <- case opt of
            AssignOptionNone -> return $ AssignOptionNone
579
            AssignOptionDrive s0 s1 -> return $ AssignOptionDrive s0 s1
580 581
            AssignOptionDelay delay ->
                exprMapper delay >>= return . AssignOptionDelay
582
        lhs' <- lhsMapper lhs
583
        expr' <- exprMapper expr
584
        return $ Assign opt' lhs' expr'
585
    moduleItemMapper (MIPackageItem (Function lifetime ret f decls stmts)) = do
586
        ret' <- typeMapper ret
587 588
        decls' <- mapM declMapper decls
        stmts' <- mapM stmtMapper stmts
589
        return $ MIPackageItem $ Function lifetime ret' f decls' stmts'
590
    moduleItemMapper (MIPackageItem (Task lifetime f decls stmts)) = do
591 592
        decls' <- mapM declMapper decls
        stmts' <- mapM stmtMapper stmts
593
        return $ MIPackageItem $ Task lifetime f decls' stmts'
594
    moduleItemMapper (Instance m p x rs l) = do
595
        p' <- mapM paramBindingMapper p
596
        l' <- mapM portBindingMapper l
597
        rs' <- mapM (mapBothM exprMapper) rs
598
        return $ Instance m p' x rs' l'
599 600
    moduleItemMapper (Modport x l) =
        mapM modportDeclMapper l >>= return . Modport x
601
    moduleItemMapper (NInputGate  kw d x lhs exprs) = do
Zachary Snow committed
602
        d' <- exprMapper d
603
        exprs' <- mapM exprMapper exprs
604
        lhs' <- lhsMapper lhs
605 606
        return $ NInputGate kw d' x lhs' exprs'
    moduleItemMapper (NOutputGate kw d x lhss expr) = do
Zachary Snow committed
607
        d' <- exprMapper d
608 609
        lhss' <- mapM lhsMapper lhss
        expr' <- exprMapper expr
610
        return $ NOutputGate kw d' x lhss' expr'
611
    moduleItemMapper (Genvar   x) = return $ Genvar   x
612 613 614
    moduleItemMapper (Generate items) = do
        items' <- mapM (traverseNestedGenItemsM genItemMapper) items
        return $ Generate items'
615 616
    moduleItemMapper (MIPackageItem (Directive c)) =
        return $ MIPackageItem $ Directive c
617 618
    moduleItemMapper (MIPackageItem (Import x y)) =
        return $ MIPackageItem $ Import x y
619 620
    moduleItemMapper (MIPackageItem (Export x y)) =
        return $ MIPackageItem $ Export x y
621 622 623 624
    moduleItemMapper (AssertionItem (mx, a)) = do
        a' <- traverseAssertionStmtsM stmtMapper a
        a'' <- traverseAssertionExprsM exprMapper a'
        return $ AssertionItem (mx, a'')
625 626 627 628 629
    moduleItemMapper (ElabTask severity (Args pnArgs kwArgs)) = do
        pnArgs' <- mapM exprMapper pnArgs
        kwArgs' <- fmap (zip kwNames) $ mapM exprMapper kwExprs
        return $ ElabTask severity $ Args pnArgs' kwArgs'
        where (kwNames, kwExprs) = unzip kwArgs
630

631 632
    genItemMapper = traverseGenItemExprsM exprMapper

633
    modportDeclMapper (dir, ident, e) = do
634
        e' <- exprMapper e
635
        return (dir, ident, e')
636

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
traverseNodes
    :: Mapper Expr
    -> Mapper Decl
    -> Mapper Type
    -> Mapper LHS
    -> Mapper Stmt
    -> Mapper ModuleItem
traverseNodes exprMapper declMapper typeMapper lhsMapper stmtMapper =
    runIdentity . traverseNodesM
        (return . exprMapper)
        (return . declMapper)
        (return . typeMapper)
        (return . lhsMapper )
        (return . stmtMapper)

652 653 654 655
traverseStmtExprsM :: Monad m => MapperM m Expr -> MapperM m Stmt
traverseStmtExprsM exprMapper = flatStmtMapper
    where

656 657
    declMapper = traverseDeclExprsM exprMapper
    lhsMapper = traverseNestedLHSsM (traverseLHSExprsM exprMapper)
658 659 660 661 662 663 664 665

    caseMapper (exprs, stmt) = do
        exprs' <- mapM exprMapper exprs
        return (exprs', stmt)
    stmtMapper = traverseNestedStmtsM flatStmtMapper
    flatStmtMapper (StmtAttr attr stmt) =
        -- note: we exclude expressions in attributes from conversion
        return $ StmtAttr attr stmt
666
    flatStmtMapper (Block kw name decls stmts) = do
667
        decls' <- mapM declMapper decls
668
        return $ Block kw name decls' stmts
669
    flatStmtMapper (Case u kw e cases) = do
670 671
        e' <- exprMapper e
        cases' <- mapM caseMapper cases
672
        return $ Case u kw e' cases'
673
    flatStmtMapper (Asgn op mt lhs expr) = do
674 675
        lhs' <- lhsMapper lhs
        expr' <- exprMapper expr
676
        return $ Asgn op mt lhs' expr'
677
    flatStmtMapper (For inits cc asgns stmt) = do
678
        inits' <- mapM (bimapM return exprMapper) inits
679
        cc' <- exprMapper cc
680 681 682 683 684 685 686 687 688
        asgns' <- mapM asgnMapper asgns
        return $ For inits' cc' asgns' stmt
    flatStmtMapper (While   e stmt) =
        exprMapper e >>= \e' -> return $ While   e' stmt
    flatStmtMapper (RepeatL e stmt) =
        exprMapper e >>= \e' -> return $ RepeatL e' stmt
    flatStmtMapper (DoWhile e stmt) =
        exprMapper e >>= \e' -> return $ DoWhile e' stmt
    flatStmtMapper (Forever   stmt) = return $ Forever stmt
689
    flatStmtMapper (Foreach x vars stmt) = return $ Foreach x vars stmt
690 691 692
    flatStmtMapper (If u cc s1 s2) =
        exprMapper cc >>= \cc' -> return $ If u cc' s1 s2
    flatStmtMapper (Timing event stmt) = return $ Timing event stmt
693 694
    flatStmtMapper (Subroutine e (Args l p)) = do
        e' <- exprMapper e
Zachary Snow committed
695 696
        l' <- mapM exprMapper l
        pes <- mapM exprMapper $ map snd p
697
        let p' = zip (map fst p) pes
698
        return $ Subroutine e' (Args l' p')
699 700
    flatStmtMapper (Return expr) =
        exprMapper expr >>= return . Return
701
    flatStmtMapper (Trigger blocks x) = return $ Trigger blocks x
702 703 704 705
    flatStmtMapper (Assertion a) = do
        a' <- traverseAssertionStmtsM stmtMapper a
        a'' <- traverseAssertionExprsM exprMapper a'
        return $ Assertion a''
706 707
    flatStmtMapper (Continue) = return Continue
    flatStmtMapper (Break) = return Break
708
    flatStmtMapper (Null) = return Null
709
    flatStmtMapper (CommentStmt c) = return $ CommentStmt c
710 711 712 713 714 715 716 717

    asgnMapper (l, op, e) = exprMapper e >>= \e' -> return $ (l, op, e')

traverseStmtExprs :: Mapper Expr -> Mapper Stmt
traverseStmtExprs = unmonad traverseStmtExprsM
collectStmtExprsM :: Monad m => CollectorM m Expr -> CollectorM m Stmt
collectStmtExprsM = collectify traverseStmtExprsM

718 719
traverseLHSsM :: Monad m => MapperM m LHS -> MapperM m ModuleItem
traverseLHSsM mapper =
720 721
    traverseStmtsM (traverseNestedStmtsM $ traverseStmtLHSsM mapper)
        >=> traverseModuleItemLHSsM
722
    where
723
        traverseModuleItemLHSsM (Assign delay lhs expr) = do
724
            lhs' <- mapper lhs
725
            return $ Assign delay lhs' expr
726
        traverseModuleItemLHSsM (Defparam lhs expr) = do
727
            lhs' <- mapper lhs
728
            return $ Defparam lhs' expr
729
        traverseModuleItemLHSsM (NOutputGate kw d x lhss expr) = do
730
            lhss' <- mapM mapper lhss
731 732
            return $ NOutputGate kw d x lhss' expr
        traverseModuleItemLHSsM (NInputGate  kw d x lhs exprs) = do
733
            lhs' <- mapper lhs
734
            return $ NInputGate kw d x lhs' exprs
735
        traverseModuleItemLHSsM (AssertionItem (mx, a)) = do
736 737 738 739 740 741
            converted <-
                traverseNestedStmtsM (traverseStmtLHSsM mapper) (Assertion a)
            return $ case converted of
                Assertion a' -> AssertionItem (mx, a')
                _ -> error $ "redirected AssertionItem traverse failed: "
                        ++ show converted
742 743 744
        traverseModuleItemLHSsM (Generate items) = do
            items' <- mapM (traverseNestedGenItemsM traverGenItemLHSsM) items
            return $ Generate items'
745
        traverseModuleItemLHSsM other = return other
746 747
        traverGenItemLHSsM (GenFor (x1, e1) cc (x2, op2, e2) subItem) = do
            wrapped_x1' <- mapper $ LHSIdent x1
748 749 750
            wrapped_x2' <- mapper $ LHSIdent x2
            let LHSIdent x1' = wrapped_x1'
            let LHSIdent x2' = wrapped_x2'
751
            return $ GenFor (x1', e1) cc (x2', op2, e2) subItem
752
        traverGenItemLHSsM other = return other
753 754

traverseLHSs :: Mapper LHS -> Mapper ModuleItem
755
traverseLHSs = unmonad traverseLHSsM
756
collectLHSsM :: Monad m => CollectorM m LHS -> CollectorM m ModuleItem
757
collectLHSsM = collectify traverseLHSsM
758

759 760
traverseNestedLHSsM :: Monad m => MapperM m LHS -> MapperM m LHS
traverseNestedLHSsM mapper = fullMapper
761
    where fullMapper = mapper >=> traverseSinglyNestedLHSsM fullMapper
762

763 764 765 766 767
traverseNestedLHSs :: Mapper LHS -> Mapper LHS
traverseNestedLHSs = unmonad traverseNestedLHSsM
collectNestedLHSsM :: Monad m => CollectorM m LHS -> CollectorM m LHS
collectNestedLHSsM = collectify traverseNestedLHSsM

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
traverseSinglyNestedLHSsM :: Monad m => MapperM m LHS -> MapperM m LHS
traverseSinglyNestedLHSsM mapper = tl
    where
        tl (LHSIdent  x       ) = return $ LHSIdent x
        tl (LHSBit    l e     ) = mapper l >>= \l' -> return $ LHSBit    l' e
        tl (LHSRange  l m r   ) = mapper l >>= \l' -> return $ LHSRange  l' m r
        tl (LHSDot    l x     ) = mapper l >>= \l' -> return $ LHSDot    l' x
        tl (LHSConcat     lhss) = mapM mapper lhss >>= return . LHSConcat
        tl (LHSStream o e lhss) = mapM mapper lhss >>= return . LHSStream o e

traverseSinglyNestedLHSs :: Mapper LHS -> Mapper LHS
traverseSinglyNestedLHSs = unmonad traverseSinglyNestedLHSsM
collectSinglyNestedLHSsM :: Monad m => CollectorM m LHS -> CollectorM m LHS
collectSinglyNestedLHSsM = collectify traverseSinglyNestedLHSsM

783
traverseDeclsM :: Monad m => MapperM m Decl -> MapperM m ModuleItem
784
traverseDeclsM mapper = miMapper
785
    where
786 787
        miMapper (MIPackageItem (Decl decl)) =
            mapper decl >>= return . MIPackageItem . Decl
788
        miMapper other = return other
789 790

traverseDecls :: Mapper Decl -> Mapper ModuleItem
791
traverseDecls = unmonad traverseDeclsM
792
collectDeclsM :: Monad m => CollectorM m Decl -> CollectorM m ModuleItem
793
collectDeclsM = collectify traverseDeclsM
794

795 796 797 798 799 800 801 802 803 804 805 806 807
traverseStmtDeclsM :: Monad m => MapperM m Decl -> MapperM m Stmt
traverseStmtDeclsM mapper = stmtMapper
    where
        stmtMapper (Block kw name decls stmts) = do
            decls' <- mapM mapper decls
            return $ Block kw name decls' stmts
        stmtMapper other = return other

traverseStmtDecls :: Mapper Decl -> Mapper Stmt
traverseStmtDecls = unmonad traverseStmtDeclsM
collectStmtDeclsM :: Monad m => CollectorM m Decl -> CollectorM m Stmt
collectStmtDeclsM = collectify traverseStmtDeclsM

808 809
traverseSinglyNestedTypesM :: Monad m => MapperM m Type -> MapperM m Type
traverseSinglyNestedTypesM mapper = tm
810
    where
811 812
        typeOrExprMapper (Left t) = mapper t >>= return . Left
        typeOrExprMapper (Right e) = return $ Right e
813 814
        tm (Alias         xx    rs) = return $ Alias         xx    rs
        tm (PSAlias ps    xx    rs) = return $ PSAlias ps    xx    rs
815 816 817 818
        tm (CSAlias ps pm xx    rs) = do
            vals' <- mapM typeOrExprMapper $ map snd pm
            let pm' = zip (map fst pm) vals'
            return $ CSAlias ps pm' xx rs
819 820 821 822
        tm (Implicit         sg rs) = return $ Implicit         sg rs
        tm (IntegerVector kw sg rs) = return $ IntegerVector kw sg rs
        tm (IntegerAtom   kw sg   ) = return $ IntegerAtom   kw sg
        tm (NonInteger    kw      ) = return $ NonInteger    kw
823
        tm (TypeOf        expr    ) = return $ TypeOf        expr
824
        tm (TypedefRef    expr    ) = return $ TypedefRef    expr
825
        tm (InterfaceT x y r) = return $ InterfaceT x y r
826
        tm (Enum t vals r) = do
827
            t' <- mapper t
828
            return $ Enum t' vals r
829
        tm (Struct p fields r) = do
830
            types <- mapM mapper $ map fst fields
831 832
            let idents = map snd fields
            return $ Struct p (zip types idents) r
833
        tm (Union p fields r) = do
834
            types <- mapM mapper $ map fst fields
835 836
            let idents = map snd fields
            return $ Union p (zip types idents) r
837
        tm (UnpackedType t r) = do
838
            t' <- mapper t
839
            return $ UnpackedType t' r
840

841 842 843 844 845 846 847 848 849
traverseSinglyNestedTypes :: Mapper Type -> Mapper Type
traverseSinglyNestedTypes = unmonad traverseSinglyNestedTypesM
collectSinglyNestedTypesM :: Monad m => CollectorM m Type -> CollectorM m Type
collectSinglyNestedTypesM = collectify traverseSinglyNestedTypesM

traverseNestedTypesM :: Monad m => MapperM m Type -> MapperM m Type
traverseNestedTypesM mapper = fullMapper
    where fullMapper = mapper >=> traverseSinglyNestedTypesM fullMapper

850 851 852 853 854
traverseNestedTypes :: Mapper Type -> Mapper Type
traverseNestedTypes = unmonad traverseNestedTypesM
collectNestedTypesM :: Monad m => CollectorM m Type -> CollectorM m Type
collectNestedTypesM = collectify traverseNestedTypesM

855 856
traverseExprTypesM :: Monad m => MapperM m Type -> MapperM m Expr
traverseExprTypesM mapper = exprMapper
857
    where
858 859
        typeOrExprMapper (Right e) = return $ Right e
        typeOrExprMapper (Left t) =
860
            mapper t >>= return . Left
861 862
        exprMapper (Cast tore e) =
            typeOrExprMapper tore >>= return . flip Cast e
863 864 865 866 867
        exprMapper (DimsFn f tore) =
            typeOrExprMapper tore >>= return . DimsFn f
        exprMapper (DimFn f tore e) = do
            tore' <- typeOrExprMapper tore
            return $ DimFn f tore' e
868 869 870 871
        exprMapper (Pattern l) = do
            names <- mapM typeOrExprMapper $ map fst l
            let exprs = map snd l
            return $ Pattern $ zip names exprs
872
        exprMapper other = return other
873 874 875 876 877 878

traverseExprTypes :: Mapper Type -> Mapper Expr
traverseExprTypes = unmonad traverseExprTypesM
collectExprTypesM :: Monad m => CollectorM m Type -> CollectorM m Expr
collectExprTypesM = collectify traverseExprTypesM

879
traverseTypeExprsM :: Monad m => MapperM m Expr -> MapperM m Type
880
traverseTypeExprsM exprMapper =
881
    typeMapper
882 883 884 885 886
    where
        typeOrExprMapper (Left t) = return $ Left t
        typeOrExprMapper (Right e) = exprMapper e >>= return . Right
        typeMapper (TypeOf expr) =
            exprMapper expr >>= return . TypeOf
887 888 889 890 891 892 893 894 895 896
        -- TypedefRef root is a reference to a port, but the "field" here is
        -- really a typename; this indirection circumvents the interface
        -- expression resolution check and ensures the underlying modport is
        -- appropriately resolved to the corresponding interface instance
        typeMapper (TypedefRef expr) = do
            let Dot inn typ = expr
            let wrap = Dot inn "*"
            wrap' <- exprMapper wrap
            let Dot inn' "*" = wrap'
            return $ TypedefRef $ Dot inn' typ
897 898 899 900 901
        typeMapper (CSAlias ps pm xx rs) = do
            vals' <- mapM typeOrExprMapper $ map snd pm
            let pm' = zip (map fst pm) vals'
            rs' <- mapM (mapBothM exprMapper) rs
            return $ CSAlias ps pm' xx rs'
902 903 904 905 906
        typeMapper (Enum t enumItems rs) = do
            enumItems' <- mapM enumItemMapper enumItems
            rs' <- mapM (mapBothM exprMapper) rs
            return $ Enum t enumItems' rs'
            where enumItemMapper (x, e) = exprMapper e >>= \e' -> return (x, e')
907 908 909 910
        typeMapper t = do
            let (tf, rs) = typeRanges t
            rs' <- mapM (mapBothM exprMapper) rs
            return $ tf rs'
911 912 913 914 915 916

traverseTypeExprs :: Mapper Expr -> Mapper Type
traverseTypeExprs = unmonad traverseTypeExprsM
collectTypeExprsM :: Monad m => CollectorM m Expr -> CollectorM m Type
collectTypeExprsM = collectify traverseTypeExprsM

917
traverseGenItemExprsM :: Monad m => MapperM m Expr -> MapperM m GenItem
918
traverseGenItemExprsM exprMapper =
919
    genItemMapper
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
    where
        genItemMapper (GenFor (x1, e1) cc (x2, op2, e2) subItem) = do
            e1' <- exprMapper e1
            e2' <- exprMapper e2
            cc' <- exprMapper cc
            return $ GenFor (x1, e1') cc' (x2, op2, e2') subItem
        genItemMapper (GenIf e i1 i2) = do
            e' <- exprMapper e
            return $ GenIf e' i1 i2
        genItemMapper (GenCase e cases) = do
            e' <- exprMapper e
            caseExprs <- mapM (mapM exprMapper . fst) cases
            let cases' = zip caseExprs (map snd cases)
            return $ GenCase e' cases'
        genItemMapper other = return other
935 936 937 938 939 940

traverseGenItemExprs :: Mapper Expr -> Mapper GenItem
traverseGenItemExprs = unmonad traverseGenItemExprsM
collectGenItemExprsM :: Monad m => CollectorM m Expr -> CollectorM m GenItem
collectGenItemExprsM = collectify traverseGenItemExprsM

941 942 943
traverseDeclNodesM
    :: Monad m => MapperM m Type -> MapperM m Expr -> MapperM m Decl
traverseDeclNodesM typeMapper exprMapper =
944
    declMapper
945 946 947 948 949
    where
        declMapper (Param s t x e) = do
            t' <- typeMapper t
            e' <- exprMapper e
            return $ Param s t' x e'
950 951 952
        declMapper (ParamType s x t) = do
            t' <- typeMapper t
            return $ ParamType s x t'
953 954 955 956 957
        declMapper (Variable d t x a e) = do
            t' <- typeMapper t
            a' <- mapM (mapBothM exprMapper) a
            e' <- exprMapper e
            return $ Variable d t' x a' e'
958 959 960 961 962
        declMapper (Net d n s t x a e) = do
            t' <- typeMapper t
            a' <- mapM (mapBothM exprMapper) a
            e' <- exprMapper e
            return $ Net d n s t' x a' e'
963 964
        declMapper (CommentDecl c) =
            return $ CommentDecl c
965

966 967 968 969 970 971 972 973 974 975
traverseDeclNodes :: Mapper Type -> Mapper Expr -> Mapper Decl
traverseDeclNodes typeMapper exprMapper =
    runIdentity . traverseDeclNodesM
        (return . typeMapper)
        (return . exprMapper)

traverseDeclExprsM :: Monad m => MapperM m Expr -> MapperM m Decl
traverseDeclExprsM exprMapper = traverseDeclNodesM typeMapper exprMapper
    where typeMapper = traverseNestedTypesM (traverseTypeExprsM exprMapper)

976 977 978 979 980
traverseDeclExprs :: Mapper Expr -> Mapper Decl
traverseDeclExprs = unmonad traverseDeclExprsM
collectDeclExprsM :: Monad m => CollectorM m Expr -> CollectorM m Decl
collectDeclExprsM = collectify traverseDeclExprsM

981
traverseDeclTypesM :: Monad m => MapperM m Type -> MapperM m Decl
982 983
traverseDeclTypesM typeMapper = traverseDeclNodesM typeMapper exprMapper
    where exprMapper = traverseNestedExprsM (traverseExprTypesM typeMapper)
984 985 986 987 988 989

traverseDeclTypes :: Mapper Type -> Mapper Decl
traverseDeclTypes = unmonad traverseDeclTypesM
collectDeclTypesM :: Monad m => CollectorM m Type -> CollectorM m Decl
collectDeclTypesM = collectify traverseDeclTypesM

990 991 992
traverseTypesM :: Monad m => MapperM m Type -> MapperM m ModuleItem
traverseTypesM typeMapper =
    traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper
993
    where
994 995 996 997
        exprMapper = traverseNestedExprsM (traverseExprTypesM typeMapper)
        lhsMapper = traverseNestedLHSsM (traverseLHSExprsM exprMapper)
        stmtMapper = traverseNestedStmtsM $
            traverseStmtDeclsM declMapper >=> traverseStmtExprsM exprMapper
998
        declMapper = traverseDeclNodesM typeMapper exprMapper
999 1000

traverseTypes :: Mapper Type -> Mapper ModuleItem
1001
traverseTypes = unmonad traverseTypesM
1002
collectTypesM :: Monad m => CollectorM m Type -> CollectorM m ModuleItem
1003
collectTypesM = collectify traverseTypesM
1004 1005 1006 1007 1008

traverseGenItemsM :: Monad m => MapperM m GenItem -> MapperM m ModuleItem
traverseGenItemsM mapper = moduleItemMapper
    where
        moduleItemMapper (Generate genItems) =
1009
            mapM mapper genItems >>= return . Generate
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
        moduleItemMapper other = return other

traverseGenItems :: Mapper GenItem -> Mapper ModuleItem
traverseGenItems = unmonad traverseGenItemsM
collectGenItemsM :: Monad m => CollectorM m GenItem -> CollectorM m ModuleItem
collectGenItemsM = collectify traverseGenItemsM

-- traverses all GenItems within a given GenItem, but doesn't inspect within
-- GenModuleItems
traverseNestedGenItemsM :: Monad m => MapperM m GenItem -> MapperM m GenItem
traverseNestedGenItemsM mapper = fullMapper
1021
    where fullMapper = mapper >=> traverseSinglyNestedGenItemsM fullMapper
1022

1023 1024 1025
traverseNestedGenItems :: Mapper GenItem -> Mapper GenItem
traverseNestedGenItems = unmonad traverseNestedGenItemsM

1026
flattenGenBlocks :: GenItem -> [GenItem]
1027
flattenGenBlocks (GenModuleItem (Generate items)) = items
1028 1029 1030 1031
flattenGenBlocks (GenFor _ _ _ GenNull) = []
flattenGenBlocks GenNull = []
flattenGenBlocks other = [other]

1032 1033 1034
traverseSinglyNestedGenItemsM :: Monad m => MapperM m GenItem -> MapperM m GenItem
traverseSinglyNestedGenItemsM fullMapper = gim
    where
1035 1036
        gim (GenBlock x subItems) = do
            subItems' <- mapM fullMapper subItems
1037
            return $ GenBlock x (concatMap flattenGenBlocks subItems')
1038 1039 1040
        gim (GenFor a b c subItem) = do
            subItem' <- fullMapper subItem
            return $ GenFor a b c subItem'
1041 1042 1043 1044
        gim (GenIf e i1 i2) = do
            i1' <- fullMapper i1
            i2' <- fullMapper i2
            return $ GenIf e i1' i2'
1045
        gim (GenCase e cases) = do
1046 1047
            caseItems <- mapM (fullMapper . snd) cases
            let cases' = zip (map fst cases) caseItems
1048
            return $ GenCase e cases'
1049 1050 1051
        gim (GenModuleItem moduleItem) =
            return $ GenModuleItem moduleItem
        gim (GenNull) = return GenNull
1052

1053 1054
traverseAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m ModuleItem
traverseAsgnsM mapper = moduleItemMapper
1055
    where
1056
        moduleItemMapper = miMapperA >=> miMapperB
1057

1058
        miMapperA (Assign delay lhs expr) = do
1059
            (lhs', expr') <- mapper (lhs, expr)
1060
            return $ Assign delay lhs' expr'
1061 1062 1063
        miMapperA (Defparam lhs expr) = do
            (lhs', expr') <- mapper (lhs, expr)
            return $ Defparam lhs' expr'
1064 1065
        miMapperA other = return other

1066
        miMapperB = traverseStmtsM $ traverseNestedStmtsM stmtMapper
1067
        stmtMapper = traverseStmtAsgnsM mapper
1068 1069

traverseAsgns :: Mapper (LHS, Expr) -> Mapper ModuleItem
1070
traverseAsgns = unmonad traverseAsgnsM
1071
collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem
1072
collectAsgnsM = collectify traverseAsgnsM
1073

1074 1075 1076
traverseStmtAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m Stmt
traverseStmtAsgnsM mapper = stmtMapper
    where
1077
        stmtMapper (Asgn op mt lhs expr) = do
1078
            (lhs', expr') <- mapper (lhs, expr)
1079
            return $ Asgn op mt lhs' expr'
1080 1081 1082 1083 1084 1085 1086
        stmtMapper other = return other

traverseStmtAsgns :: Mapper (LHS, Expr) -> Mapper Stmt
traverseStmtAsgns = unmonad traverseStmtAsgnsM
collectStmtAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m Stmt
collectStmtAsgnsM = collectify traverseStmtAsgnsM

1087
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
1088 1089 1090
traverseNestedModuleItemsM mapper = fullMapper
    where
        fullMapper (Generate genItems) = do
1091
            let genItems' = concatMap flattenGenBlocks genItems
1092 1093 1094
            mapM fullGenItemMapper genItems' >>= mapper . Generate
        fullMapper (MIAttr attr mi) =
            fullMapper mi >>= mapper . MIAttr attr
1095
        fullMapper (Initial Null) = return $ Generate []
1096 1097
        fullMapper other = mapper other
        fullGenItemMapper = traverseNestedGenItemsM genItemMapper
1098 1099
        genItemMapper (GenModuleItem moduleItem) =
            fullMapper moduleItem >>= return . GenModuleItem
1100
        genItemMapper (GenIf _ GenNull GenNull) = return GenNull
1101 1102 1103 1104 1105
        genItemMapper (GenIf (Number n) s1 s2) = do
            case numberToInteger n of
                Nothing -> return $ GenIf (Number n) s1 s2
                Just 0 -> genItemMapper s2
                Just _ -> genItemMapper s1
1106 1107
        genItemMapper (GenBlock _ []) = return GenNull
        genItemMapper other = return other
1108 1109 1110 1111 1112 1113

traverseNestedModuleItems :: Mapper ModuleItem -> Mapper ModuleItem
traverseNestedModuleItems = unmonad traverseNestedModuleItemsM
collectNestedModuleItemsM :: Monad m => CollectorM m ModuleItem -> CollectorM m ModuleItem
collectNestedModuleItemsM = collectify traverseNestedModuleItemsM

1114 1115 1116 1117 1118 1119 1120 1121 1122
-- In many conversions, we want to resolve items locally first, and then fall
-- back to looking at other source files, if necessary. This helper captures
-- this behavior, allowing a conversion to fall back to arbitrary global
-- collected item, if one exists. While this isn't foolproof (we could
-- inadvertently resolve a name that doesn't exist in the given file), many
-- projects rely on their toolchain to locate their modules, interfaces,
-- packages, or typenames in other files. Global resolution of modules and
-- interfaces is more commonly expected than global resolution of typenames and
-- packages.
1123 1124
traverseFilesM
    :: (Monoid w, Monad m)
1125
    => CollectorM (Writer w) AST
1126 1127 1128 1129
    -> (w -> MapperM m AST)
    -> MapperM m [AST]
traverseFilesM fileCollectorM fileMapperM files =
    mapM traverseFileM files
1130 1131
    where
        globalNotes = execWriter $ mapM fileCollectorM files
1132 1133
        traverseFileM file =
            fileMapperM notes file
1134 1135 1136
            where
                localNotes = execWriter $ fileCollectorM file
                notes = localNotes <> globalNotes
1137 1138 1139 1140 1141 1142
traverseFiles
    :: Monoid w
    => CollectorM (Writer w) AST
    -> (w -> Mapper AST)
    -> Mapper [AST]
traverseFiles fileCollectorM fileMapper files =
1143
    runIdentity (traverseFilesM fileCollectorM fileMapperM  files)
1144
    where fileMapperM = (\w -> return . fileMapper w)
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158

traverseNetAsVarM :: Monad m => MapperM m Decl -> MapperM m Decl
traverseNetAsVarM func net = do
    let Net d n s t x a e = net
    let var = Variable d t x a e
    var' <- func var
    let Variable d' t' x' a' e' = var'
    let net' = Net d' n s t' x' a' e'
    return net'

traverseNetAsVar :: Mapper Decl -> Mapper Decl
traverseNetAsVar = unmonad traverseNetAsVarM
collectNetAsVarM :: Monad m => CollectorM m Decl -> CollectorM m Decl
collectNetAsVarM = collectify traverseNetAsVarM