Traverse.hs 45.7 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
Zachary Snow committed
220
        cs (Block _ "" [] [stmt]) = fullMapper stmt
221 222 223 224 225 226 227
        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]
228 229
        cs (Block kw name decls stmts) =
            mapM fullMapper stmts >>= return . Block kw name decls
230
        cs (Case u kw expr cases) = do
231 232
            caseStmts <- mapM fullMapper $ map snd cases
            let cases' = zip (map fst cases) caseStmts
233
            return $ Case u kw expr cases'
234
        cs (Asgn op mt lhs expr) = return $ Asgn op mt lhs expr
235
        cs (For a b c stmt) = fullMapper stmt >>= return . For a b c
236 237 238 239
        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
240
        cs (Foreach x vars stmt) = fullMapper stmt >>= return . Foreach x vars
241 242 243 244 245 246 247
        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'
248
        cs (If u e s1 s2) = do
249 250
            s1' <- fullMapper s1
            s2' <- fullMapper s2
251
            return $ If u e s1' s2'
252
        cs (Timing event stmt) = fullMapper stmt >>= return . Timing event
253
        cs (Return expr) = return $ Return expr
254
        cs (Subroutine expr exprs) = return $ Subroutine expr exprs
255
        cs (Trigger blocks x) = return $ Trigger blocks x
256 257
        cs (Assertion a) =
            traverseAssertionStmtsM fullMapper a >>= return . Assertion
258 259
        cs (Continue) = return Continue
        cs (Break) = return Break
260
        cs (Null) = return Null
261
        cs (CommentStmt c) = return $ CommentStmt c
262

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

268 269 270
traverseAssertionStmtsM :: Monad m => MapperM m Stmt -> MapperM m Assertion
traverseAssertionStmtsM mapper = assertionMapper
    where
271
        actionBlockMapper (ActionBlock s1 s2) = do
272 273
            s1' <- mapper s1
            s2' <- mapper s2
274
            return $ ActionBlock s1' s2'
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
        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'
312
        seqMatchItemMapper (SeqMatchAsgn (a, b, c)) = do
313
            c' <- mapper c
314 315
            return $ SeqMatchAsgn (a, b, c')
        seqMatchItemMapper (SeqMatchCall x (Args l p)) = do
Zachary Snow committed
316 317
            l' <- mapM mapper l
            pes <- mapM mapper $ map snd p
318
            let p' = zip (map fst p) pes
319
            return $ SeqMatchCall x (Args l' p')
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
        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
344 345
        propSpecMapper (PropertySpec ms e pe) = do
            e' <- mapper e
346
            pe' <- propExprMapper pe
Zachary Snow committed
347
            return $ PropertySpec ms e' pe'
348 349 350 351 352 353 354 355 356 357 358 359 360 361
        assertionExprMapper (Left e) =
            propSpecMapper e >>= return . Left
        assertionExprMapper (Right e) =
            mapper e >>= return . Right
        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

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

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

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

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

504 505 506
traverseLHSExprsM :: Monad m => MapperM m Expr -> MapperM m LHS
traverseLHSExprsM exprMapper =
    lhsMapper
507
    where
508 509 510 511 512 513 514 515
        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
516

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

522 523 524 525 526
mapBothM :: Monad m => MapperM m t -> MapperM m (t, t)
mapBothM mapper (a, b) = do
    a' <- mapper a
    b' <- mapper b
    return (a', b')
527

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

537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
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
554 555
    portBindingMapper (p, e) =
        exprMapper e >>= \e' -> return (p, e')
556

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

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

632 633
    genItemMapper = traverseGenItemExprsM exprMapper

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

638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
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)

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

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

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

    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

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

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

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

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

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
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

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

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

796 797 798 799 800 801 802 803 804 805 806 807 808
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

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

842 843 844 845 846 847 848 849 850
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

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

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

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

880
traverseTypeExprsM :: Monad m => MapperM m Expr -> MapperM m Type
881
traverseTypeExprsM exprMapper =
882
    typeMapper
883 884 885 886 887
    where
        typeOrExprMapper (Left t) = return $ Left t
        typeOrExprMapper (Right e) = exprMapper e >>= return . Right
        typeMapper (TypeOf expr) =
            exprMapper expr >>= return . TypeOf
888
        -- TypedefRef is excluded because it isn't really an expression
889 890 891 892 893
        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'
894 895 896 897 898
        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')
899 900 901 902
        typeMapper t = do
            let (tf, rs) = typeRanges t
            rs' <- mapM (mapBothM exprMapper) rs
            return $ tf rs'
903 904 905 906 907 908

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

909
traverseGenItemExprsM :: Monad m => MapperM m Expr -> MapperM m GenItem
910
traverseGenItemExprsM exprMapper =
911
    genItemMapper
912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
    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
927 928 929 930 931 932

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

933 934 935
traverseDeclNodesM
    :: Monad m => MapperM m Type -> MapperM m Expr -> MapperM m Decl
traverseDeclNodesM typeMapper exprMapper =
936
    declMapper
937 938 939 940 941
    where
        declMapper (Param s t x e) = do
            t' <- typeMapper t
            e' <- exprMapper e
            return $ Param s t' x e'
942 943 944
        declMapper (ParamType s x t) = do
            t' <- typeMapper t
            return $ ParamType s x t'
945 946 947 948 949
        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'
950 951 952 953 954
        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'
955 956
        declMapper (CommentDecl c) =
            return $ CommentDecl c
957

958 959 960 961 962 963 964 965 966 967
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)

968 969 970 971 972
traverseDeclExprs :: Mapper Expr -> Mapper Decl
traverseDeclExprs = unmonad traverseDeclExprsM
collectDeclExprsM :: Monad m => CollectorM m Expr -> CollectorM m Decl
collectDeclExprsM = collectify traverseDeclExprsM

973
traverseDeclTypesM :: Monad m => MapperM m Type -> MapperM m Decl
974 975
traverseDeclTypesM typeMapper = traverseDeclNodesM typeMapper exprMapper
    where exprMapper = traverseNestedExprsM (traverseExprTypesM typeMapper)
976 977 978 979 980 981

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

982 983 984
traverseTypesM :: Monad m => MapperM m Type -> MapperM m ModuleItem
traverseTypesM typeMapper =
    traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper
985
    where
986 987 988 989
        exprMapper = traverseNestedExprsM (traverseExprTypesM typeMapper)
        lhsMapper = traverseNestedLHSsM (traverseLHSExprsM exprMapper)
        stmtMapper = traverseNestedStmtsM $
            traverseStmtDeclsM declMapper >=> traverseStmtExprsM exprMapper
990
        declMapper = traverseDeclNodesM typeMapper exprMapper
991 992

traverseTypes :: Mapper Type -> Mapper ModuleItem
993
traverseTypes = unmonad traverseTypesM
994
collectTypesM :: Monad m => CollectorM m Type -> CollectorM m ModuleItem
995
collectTypesM = collectify traverseTypesM
996 997 998 999 1000

traverseGenItemsM :: Monad m => MapperM m GenItem -> MapperM m ModuleItem
traverseGenItemsM mapper = moduleItemMapper
    where
        moduleItemMapper (Generate genItems) =
1001
            mapM mapper genItems >>= return . Generate
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
        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
1013
    where fullMapper = mapper >=> traverseSinglyNestedGenItemsM fullMapper
1014

1015 1016 1017
traverseNestedGenItems :: Mapper GenItem -> Mapper GenItem
traverseNestedGenItems = unmonad traverseNestedGenItemsM

1018
flattenGenBlocks :: GenItem -> [GenItem]
1019
flattenGenBlocks (GenModuleItem (Generate items)) = items
1020 1021 1022 1023
flattenGenBlocks (GenFor _ _ _ GenNull) = []
flattenGenBlocks GenNull = []
flattenGenBlocks other = [other]

1024 1025 1026
traverseSinglyNestedGenItemsM :: Monad m => MapperM m GenItem -> MapperM m GenItem
traverseSinglyNestedGenItemsM fullMapper = gim
    where
1027 1028
        gim (GenBlock x subItems) = do
            subItems' <- mapM fullMapper subItems
1029
            return $ GenBlock x (concatMap flattenGenBlocks subItems')
1030 1031 1032
        gim (GenFor a b c subItem) = do
            subItem' <- fullMapper subItem
            return $ GenFor a b c subItem'
1033 1034 1035 1036
        gim (GenIf e i1 i2) = do
            i1' <- fullMapper i1
            i2' <- fullMapper i2
            return $ GenIf e i1' i2'
1037
        gim (GenCase e cases) = do
1038 1039
            caseItems <- mapM (fullMapper . snd) cases
            let cases' = zip (map fst cases) caseItems
1040
            return $ GenCase e cases'
1041 1042 1043
        gim (GenModuleItem moduleItem) =
            return $ GenModuleItem moduleItem
        gim (GenNull) = return GenNull
1044

1045 1046
traverseAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m ModuleItem
traverseAsgnsM mapper = moduleItemMapper
1047
    where
1048
        moduleItemMapper = miMapperA >=> miMapperB
1049

1050
        miMapperA (Assign delay lhs expr) = do
1051
            (lhs', expr') <- mapper (lhs, expr)
1052
            return $ Assign delay lhs' expr'
1053 1054 1055
        miMapperA (Defparam lhs expr) = do
            (lhs', expr') <- mapper (lhs, expr)
            return $ Defparam lhs' expr'
1056 1057
        miMapperA other = return other

1058
        miMapperB = traverseStmtsM $ traverseNestedStmtsM stmtMapper
1059
        stmtMapper = traverseStmtAsgnsM mapper
1060 1061

traverseAsgns :: Mapper (LHS, Expr) -> Mapper ModuleItem
1062
traverseAsgns = unmonad traverseAsgnsM
1063
collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem
1064
collectAsgnsM = collectify traverseAsgnsM
1065

1066 1067 1068
traverseStmtAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m Stmt
traverseStmtAsgnsM mapper = stmtMapper
    where
1069
        stmtMapper (Asgn op mt lhs expr) = do
1070
            (lhs', expr') <- mapper (lhs, expr)
1071
            return $ Asgn op mt lhs' expr'
1072 1073 1074 1075 1076 1077 1078
        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

1079
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
1080 1081 1082
traverseNestedModuleItemsM mapper = fullMapper
    where
        fullMapper (Generate genItems) = do
1083
            let genItems' = concatMap flattenGenBlocks genItems
1084 1085 1086
            mapM fullGenItemMapper genItems' >>= mapper . Generate
        fullMapper (MIAttr attr mi) =
            fullMapper mi >>= mapper . MIAttr attr
1087
        fullMapper (Initial Null) = return $ Generate []
1088 1089
        fullMapper other = mapper other
        fullGenItemMapper = traverseNestedGenItemsM genItemMapper
1090 1091
        genItemMapper (GenModuleItem moduleItem) =
            fullMapper moduleItem >>= return . GenModuleItem
1092
        genItemMapper (GenIf _ GenNull GenNull) = return GenNull
1093 1094 1095 1096 1097
        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
1098 1099
        genItemMapper (GenBlock _ []) = return GenNull
        genItemMapper other = return other
1100 1101 1102 1103 1104 1105

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

1106 1107 1108 1109 1110 1111 1112 1113 1114
-- 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.
1115 1116
traverseFilesM
    :: (Monoid w, Monad m)
1117
    => CollectorM (Writer w) AST
1118 1119 1120 1121
    -> (w -> MapperM m AST)
    -> MapperM m [AST]
traverseFilesM fileCollectorM fileMapperM files =
    mapM traverseFileM files
1122 1123
    where
        globalNotes = execWriter $ mapM fileCollectorM files
1124 1125
        traverseFileM file =
            fileMapperM notes file
1126 1127 1128
            where
                localNotes = execWriter $ fileCollectorM file
                notes = localNotes <> globalNotes
1129 1130 1131 1132 1133 1134
traverseFiles
    :: Monoid w
    => CollectorM (Writer w) AST
    -> (w -> Mapper AST)
    -> Mapper [AST]
traverseFiles fileCollectorM fileMapper files =
1135
    runIdentity (traverseFilesM fileCollectorM fileMapperM  files)
1136
    where fileMapperM = (\w -> return . fileMapper w)
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

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