Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sv2v
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
sv2v
Commits
50b7bf28
Commit
50b7bf28
authored
Feb 24, 2019
by
Zachary Snow
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
huge pass at revamping AST to be more general, easy to work with
parent
e795109f
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
233 additions
and
237 deletions
+233
-237
Convert/Logic.hs
+4
-4
Convert/PackedArrayFlatten.hs
+20
-28
Convert/Template/Stmt.hs
+3
-5
Convert/Typedef.hs
+73
-10
Language/SystemVerilog/AST.hs
+79
-98
Language/SystemVerilog/Parser/Parse.y
+54
-92
No files found.
Convert/Logic.hs
View file @
50b7bf28
...
...
@@ -34,8 +34,8 @@ getStmtLHSs :: Stmt -> [LHS]
getStmtLHSs
(
Block
_
stmts
)
=
concat
$
map
getStmtLHSs
stmts
getStmtLHSs
(
Case
kw
e
cases
(
Just
stmt
))
=
(
getStmtLHSs
stmt
)
++
(
getStmtLHSs
$
Case
kw
e
cases
Nothing
)
getStmtLHSs
(
Case
_
_
cases
Nothing
)
=
concat
$
map
getStmtLHSs
$
map
snd
cases
getStmtLHSs
(
BlockingAssignment
lhs
_
)
=
[
lhs
]
getStmtLHSs
(
NonBlockingAssignment
lhs
_
)
=
[
lhs
]
getStmtLHSs
(
AsgnBlk
lhs
_
)
=
[
lhs
]
getStmtLHSs
(
Asgn
lhs
_
)
=
[
lhs
]
getStmtLHSs
(
For
_
_
_
stmt
)
=
getStmtLHSs
stmt
getStmtLHSs
(
If
_
s1
s2
)
=
(
getStmtLHSs
s1
)
++
(
getStmtLHSs
s2
)
getStmtLHSs
(
Timing
_
s
)
=
getStmtLHSs
s
...
...
@@ -56,8 +56,8 @@ getRegIdents (AlwaysC _ stmt) =
getRegIdents
_
=
Set
.
empty
convertModuleItem
::
RegIdents
->
ModuleItem
->
ModuleItem
convertModuleItem
idents
(
LocalNet
(
Logic
mr
)
ident
val
)
=
LocalNet
(
t
mr
)
ident
val
convertModuleItem
idents
(
MIDecl
(
Variable
dir
(
Logic
mr
)
ident
a
me
)
)
=
MIDecl
$
Variable
dir
(
t
mr
)
ident
a
me
where
t
=
if
Set
.
member
ident
idents
then
Reg
else
Wire
convertModuleItem
idents
(
Generate
items
)
=
Generate
$
map
(
convertGenItem
$
convertModuleItem
idents
)
items
...
...
Convert/PackedArrayFlatten.hs
View file @
50b7bf28
...
...
@@ -40,7 +40,7 @@ convert = map convertDescription
convertDescription
::
Description
->
Description
convertDescription
(
Module
name
ports
items
)
=
-- Insert the new items right after the
LocalNet
for the item to preserve
-- Insert the new items right after the
Variable
for the item to preserve
-- declaration order, which some toolchains care about.
Module
name
ports
$
concat
$
map
addUnflattener
items'
where
...
...
@@ -49,18 +49,18 @@ convertDescription (Module name ports items) =
items'
=
map
(
convertModuleItem
dimMap
)
items
outputs
=
Set
.
fromList
$
mapMaybe
getOutput
items
getOutput
::
ModuleItem
->
Maybe
Identifier
getOutput
(
PortDecl
Output
_
ident
)
=
Just
ident
getOutput
(
MIDecl
(
Variable
Output
_
ident
_
_
)
)
=
Just
ident
getOutput
_
=
Nothing
getExtraDims
::
ModuleItem
->
Maybe
(
Identifier
,
(
Type
,
Range
))
getExtraDims
(
LocalNet
t
ident
_
)
=
getExtraDims
(
MIDecl
(
Variable
_
t
ident
_
_
)
)
=
if
length
rs
>
1
then
Just
(
ident
,
(
tf
$
tail
rs
,
head
rs
))
else
Nothing
where
(
tf
,
rs
)
=
typeDims
t
getExtraDims
_
=
Nothing
addUnflattener
::
ModuleItem
->
[
ModuleItem
]
addUnflattener
(
LocalNet
t
ident
val
)
=
LocalNet
t
ident
val
:
addUnflattener
(
orig
@
(
MIDecl
(
Variable
_
_
ident
_
_
))
)
=
orig
:
case
Map
.
lookup
ident
dimMap
of
Nothing
->
[]
Just
desc
->
unflattener
outputs
(
ident
,
desc
)
...
...
@@ -84,10 +84,10 @@ simplify other = other
unflattener
::
Set
.
Set
Identifier
->
(
Identifier
,
(
Type
,
Range
))
->
[
ModuleItem
]
unflattener
outputs
(
arr
,
(
t
,
(
majorHi
,
majorLo
)))
=
[
Comment
$
"sv2v packed-array-flatten unflattener for "
++
arr
,
LocalNet
t
arrUnflat
(
Left
[(
majorHi
,
majorLo
)])
,
MIDecl
$
Variable
Local
t
arrUnflat
[(
majorHi
,
majorLo
)]
Nothing
,
Generate
[
GenModuleItem
$
Genvar
index
,
GenModuleItem
$
MI
IntegerV
$
IntegerV
(
arrUnflat
++
"_repeater_index"
)
(
Right
Nothing
)
,
GenModuleItem
$
MI
Decl
$
Variable
Local
IntegerT
(
arrUnflat
++
"_repeater_index"
)
[]
Nothing
,
GenFor
(
index
,
majorLo
)
(
BinOp
Le
(
Ident
index
)
majorHi
)
...
...
@@ -110,7 +110,7 @@ unflattener outputs (arr, (t, (majorHi, majorLo))) =
(
minorHi
,
minorLo
)
=
head
$
snd
$
typeDims
t
size
=
simplify
$
BinOp
Add
(
BinOp
Sub
minorHi
minorLo
)
(
Number
"1"
)
localparam
::
Identifier
->
Expr
->
GenItem
localparam
x
v
=
GenModuleItem
$
MI
Localparam
$
Localparam
Nothing
x
v
localparam
x
v
=
GenModuleItem
$
MI
Decl
$
Localparam
(
Implicit
[]
)
x
v
origRange
=
(
(
BinOp
Add
(
Ident
startBit
)
(
BinOp
Sub
size
(
Number
"1"
)))
,
Ident
startBit
)
...
...
@@ -120,16 +120,13 @@ typeDims (Reg r) = (Reg , r)
typeDims
(
Wire
r
)
=
(
Wire
,
r
)
typeDims
(
Logic
r
)
=
(
Logic
,
r
)
typeDims
(
Alias
t
r
)
=
(
Alias
t
,
r
)
typeDims
(
Implicit
r
)
=
(
Implicit
,
r
)
typeDims
(
IntegerT
)
=
(
error
"ranges cannot be applied to IntegerT"
,
[]
)
typeDims
(
Enum
t
v
r
)
=
(
Enum
t
v
,
r
)
prefix
::
Identifier
->
Identifier
prefix
ident
=
"_sv2v_"
++
ident
rewriteRangesOrAssignment
::
DimMap
->
RangesOrAssignment
->
RangesOrAssignment
rewriteRangesOrAssignment
dimMap
(
Right
(
Just
e
))
=
Right
$
Just
$
rewriteExpr
dimMap
e
rewriteRangesOrAssignment
_
other
=
other
rewriteRange
::
DimMap
->
Range
->
Range
rewriteRange
dimMap
(
a
,
b
)
=
(
r
a
,
r
b
)
where
r
=
rewriteExpr
dimMap
...
...
@@ -208,8 +205,8 @@ rewriteStmt dimMap orig = rs orig
case
def
of
Nothing
->
Nothing
Just
stmt
->
Just
$
rs
stmt
rs
(
BlockingAssignment
lhs
expr
)
=
convertAssignment
BlockingAssignment
lhs
expr
rs
(
NonBlockingAssignment
lhs
expr
)
=
convertAssignment
NonBlockingAssignment
lhs
expr
rs
(
AsgnBlk
lhs
expr
)
=
convertAssignment
AsgnBlk
lhs
expr
rs
(
Asgn
lhs
expr
)
=
convertAssignment
Asgn
lhs
expr
rs
(
For
(
x1
,
e1
)
cc
(
x2
,
e2
)
stmt
)
=
For
(
x1
,
e1'
)
cc'
(
x2
,
e2'
)
(
rs
stmt
)
where
e1'
=
rewriteExpr
dimMap
e1
...
...
@@ -236,18 +233,15 @@ rewriteStmt dimMap orig = rs orig
constructor
(
rewriteLHS
dimMap
lhs
)
(
rewriteExpr
dimMap
expr
)
convertModuleItem
::
DimMap
->
ModuleItem
->
ModuleItem
convertModuleItem
dimMap
(
LocalNet
t
x
val
)
=
convertModuleItem
dimMap
(
MIDecl
(
Variable
d
t
x
a
me
)
)
=
if
Map
.
member
x
dimMap
then
LocalNet
t'
x
val
'
else
LocalNet
t
x
val
'
then
MIDecl
$
Variable
d
t'
x
a'
me
'
else
MIDecl
$
Variable
d
t
x
a'
me
'
where
(
tf
,
rs
)
=
typeDims
t
t'
=
tf
$
flattenRanges
rs
val'
=
rewriteRangesOrAssignment
dimMap
val
convertModuleItem
dimMap
(
PortDecl
dir
rs
x
)
=
if
Map
.
member
x
dimMap
then
PortDecl
dir
(
flattenRanges
rs
)
x
else
PortDecl
dir
rs
x
a'
=
map
(
rewriteRange
dimMap
)
a
me'
=
maybe
Nothing
(
Just
.
rewriteExpr
dimMap
)
me
convertModuleItem
dimMap
(
Generate
items
)
=
Generate
$
map
(
convertGenItem
dimMap
)
items
convertModuleItem
dimMap
(
Assign
lhs
expr
)
=
...
...
@@ -264,11 +258,9 @@ convertModuleItem dimMap (Instance m params x (Just l)) =
convertPortBinding
::
PortBinding
->
PortBinding
convertPortBinding
(
p
,
Nothing
)
=
(
p
,
Nothing
)
convertPortBinding
(
p
,
Just
e
)
=
(
p
,
Just
$
rewriteExpr
dimMap
e
)
convertModuleItem
_
(
Comment
x
)
=
Comment
x
convertModuleItem
_
(
Genvar
x
)
=
Genvar
x
convertModuleItem
_
(
MIParameter
x
)
=
MIParameter
x
convertModuleItem
_
(
MILocalparam
x
)
=
MILocalparam
x
convertModuleItem
_
(
MIIntegerV
x
)
=
MIIntegerV
x
convertModuleItem
_
(
Comment
x
)
=
Comment
x
convertModuleItem
_
(
Genvar
x
)
=
Genvar
x
convertModuleItem
_
(
MIDecl
x
)
=
MIDecl
x
convertGenItem
::
DimMap
->
GenItem
->
GenItem
convertGenItem
dimMap
item
=
convertGenItem'
item
...
...
Convert/Template/Stmt.hs
View file @
50b7bf28
...
...
@@ -32,11 +32,9 @@ convertStmt f = f . convertStmt'
Case
kw
expr
cases'
def'
where
cases'
=
map
(
\
(
exprs
,
stmt
)
->
(
exprs
,
cs
stmt
))
cases
def'
=
case
def
of
Nothing
->
Nothing
Just
stmt
->
Just
(
cs
stmt
)
convertStmt'
(
BlockingAssignment
lhs
expr
)
=
BlockingAssignment
lhs
expr
convertStmt'
(
NonBlockingAssignment
lhs
expr
)
=
NonBlockingAssignment
lhs
expr
def'
=
maybe
Nothing
(
Just
.
cs
)
def
convertStmt'
(
AsgnBlk
lhs
expr
)
=
AsgnBlk
lhs
expr
convertStmt'
(
Asgn
lhs
expr
)
=
Asgn
lhs
expr
convertStmt'
(
For
a
b
c
stmt
)
=
For
a
b
c
(
cs
stmt
)
convertStmt'
(
If
e
s1
s2
)
=
If
e
(
cs
s1
)
(
cs
s2
)
convertStmt'
(
Timing
sense
stmt
)
=
Timing
sense
(
cs
stmt
)
...
...
Convert/Typedef.hs
View file @
50b7bf28
...
...
@@ -2,13 +2,11 @@
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `typedef`
-
- Aliased types can (probably) appear in all item declarations, including
- modules, blocks, and function parameters.
-}
-- TODO: Right now we only support typedefs for module data items. Function
-- parameters, block items, etc., probably support typedefs, too.
-- TODO FIXME XXX: `Cast` contains a type, which we'll need to resolve/convert?
module
Convert.Typedef
(
convert
)
where
import
Data.Maybe
...
...
@@ -37,9 +35,11 @@ convertDescription types (Module name ports items) =
convertDescription
_
other
=
other
resolveType
::
Types
->
Type
->
Type
resolveType
_
(
Reg
rs
)
=
Reg
rs
resolveType
_
(
Wire
rs
)
=
Wire
rs
resolveType
_
(
Logic
rs
)
=
Logic
rs
resolveType
_
(
Reg
rs
)
=
Reg
rs
resolveType
_
(
Wire
rs
)
=
Wire
rs
resolveType
_
(
Logic
rs
)
=
Logic
rs
resolveType
_
(
Implicit
rs
)
=
Implicit
rs
resolveType
_
(
IntegerT
)
=
IntegerT
resolveType
_
(
Enum
Nothing
vals
rs
)
=
Enum
Nothing
vals
rs
resolveType
types
(
Enum
(
Just
t
)
vals
rs
)
=
Enum
(
Just
$
resolveType
types
t
)
vals
rs
resolveType
types
(
Alias
st
rs1
)
=
...
...
@@ -48,9 +48,72 @@ resolveType types (Alias st rs1) =
(
Wire
rs2
)
->
Wire
$
rs2
++
rs1
(
Logic
rs2
)
->
Logic
$
rs2
++
rs1
(
Enum
t
v
rs2
)
->
Enum
t
v
$
rs2
++
rs1
(
Implicit
rs2
)
->
Implicit
$
rs2
++
rs1
(
IntegerT
)
->
error
$
"resolveType encountered packed `integer` on "
++
st
(
Alias
_
_
)
->
error
$
"resolveType invariant failed on "
++
st
convertDecl
::
Types
->
Decl
->
Decl
convertDecl
types
decl
=
case
decl
of
Parameter
t
x
e
->
Parameter
(
rt
t
)
x
(
re
e
)
Localparam
t
x
e
->
Localparam
(
rt
t
)
x
(
re
e
)
Variable
d
t
x
a
me
->
Variable
d
(
rt
t
)
x
a
me'
where
me'
=
if
isJust
me
then
Just
(
re
$
fromJust
me
)
else
me
where
rt
=
resolveType
types
re
=
convertExpr
types
convertModuleItem
::
Types
->
ModuleItem
->
ModuleItem
convertModuleItem
types
(
LocalNet
t
ident
val
)
=
LocalNet
(
resolveType
types
t
)
ident
val
convertModuleItem
types
(
MIDecl
decl
)
=
MIDecl
$
convertDecl
types
decl
convertModuleItem
types
(
Function
t
x
decls
stmt
)
=
Function
(
resolveType
types
t
)
x
(
map
(
convertDecl
types
)
decls
)
(
convertStmt
types
stmt
)
convertModuleItem
types
(
Assign
lhs
expr
)
=
Assign
lhs
(
convertExpr
types
expr
)
convertModuleItem
types
(
AlwaysC
kw
stmt
)
=
AlwaysC
kw
(
convertStmt
types
stmt
)
convertModuleItem
_
other
=
other
convertStmt
::
Types
->
Stmt
->
Stmt
convertStmt
types
=
rs
where
rd
=
convertDecl
types
re
=
convertExpr
types
rs
::
Stmt
->
Stmt
rs
(
Block
header
stmts
)
=
Block
header'
(
map
rs
stmts
)
where
header'
=
maybe
Nothing
(
\
(
x
,
decls
)
->
Just
(
x
,
map
rd
decls
))
header
rs
(
Case
kw
e
cases
def
)
=
Case
kw
(
re
e
)
(
map
convertCase
cases
)
def'
where
convertCase
(
exprs
,
stmt
)
=
(
map
re
exprs
,
rs
stmt
)
def'
=
maybe
Nothing
(
Just
.
rs
)
def
rs
(
AsgnBlk
lhs
expr
)
=
AsgnBlk
lhs
(
re
expr
)
rs
(
Asgn
lhs
expr
)
=
Asgn
lhs
(
re
expr
)
rs
(
For
(
x1
,
e1
)
e
(
x2
,
e2
)
stmt
)
=
For
(
x1
,
re
e1
)
(
re
e
)
(
x2
,
re
e2
)
(
rs
stmt
)
rs
(
If
e
s1
s2
)
=
If
(
re
e
)
(
rs
s1
)
(
rs
s2
)
rs
(
Timing
sense
stmt
)
=
Timing
sense
(
rs
stmt
)
rs
(
Null
)
=
Null
convertExpr
::
Types
->
Expr
->
Expr
convertExpr
types
=
re
where
re
::
Expr
->
Expr
re
(
String
s
)
=
String
s
re
(
Number
s
)
=
Number
s
re
(
ConstBool
b
)
=
ConstBool
b
re
(
Ident
i
)
=
Ident
i
re
(
IdentRange
i
r
)
=
IdentRange
i
r
re
(
IdentBit
i
e
)
=
IdentBit
i
(
re
e
)
re
(
Repeat
e
l
)
=
Repeat
(
re
e
)
(
map
re
l
)
re
(
Concat
l
)
=
Concat
(
map
re
l
)
re
(
Call
f
l
)
=
Call
f
(
map
re
l
)
re
(
UniOp
o
e
)
=
UniOp
o
(
re
e
)
re
(
BinOp
o
e1
e2
)
=
BinOp
o
(
re
e1
)
(
re
e2
)
re
(
Mux
e1
e2
e3
)
=
Mux
(
re
e1
)
(
re
e2
)
(
re
e3
)
re
(
Bit
e
n
)
=
Bit
(
re
e
)
n
-- This is the reason we have to convert expressions in this module.
re
(
Cast
t
e
)
=
Cast
(
resolveType
types
t
)
(
re
e
)
Language/SystemVerilog/AST.hs
View file @
50b7bf28
...
...
@@ -10,19 +10,15 @@ module Language.SystemVerilog.AST
,
UniOp
(
..
)
,
BinOp
(
..
)
,
Sense
(
..
)
,
BlockItemDeclaration
(
..
)
,
Parameter
(
..
)
,
Localparam
(
..
)
,
IntegerV
(
..
)
,
GenItem
(
..
)
,
AlwaysKW
(
..
)
,
CaseKW
(
..
)
,
Decl
(
..
)
,
AST
,
PortBinding
,
Case
,
Range
,
GenCase
,
RangesOrAssignment
)
where
import
Data.List
...
...
@@ -65,49 +61,64 @@ data Direction
=
Input
|
Output
|
Inout
|
Local
deriving
Eq
instance
Show
Direction
where
show
Input
=
"input"
show
Output
=
"output"
show
Inout
=
"inout"
show
Local
=
""
data
Type
=
Reg
[
Range
]
|
Wire
[
Range
]
|
Logic
[
Range
]
|
Alias
String
[
Range
]
=
Reg
[
Range
]
|
Wire
[
Range
]
|
Logic
[
Range
]
|
Alias
Identifier
[
Range
]
|
Implicit
[
Range
]
|
IntegerT
|
Enum
(
Maybe
Type
)
[(
Identifier
,
Maybe
Expr
)]
[
Range
]
deriving
Eq
instance
Show
Type
where
show
(
Reg
r
)
=
"reg"
++
(
showRanges
r
)
show
(
Wire
r
)
=
"wire"
++
(
showRanges
r
)
show
(
Logic
r
)
=
"logic"
++
(
showRanges
r
)
show
(
Alias
t
r
)
=
t
++
(
showRanges
r
)
show
(
Reg
r
)
=
"reg"
++
(
showRanges
r
)
show
(
Wire
r
)
=
"wire"
++
(
showRanges
r
)
show
(
Logic
r
)
=
"logic"
++
(
showRanges
r
)
show
(
Alias
t
r
)
=
t
++
(
showRanges
r
)
show
(
Implicit
r
)
=
(
showRanges
r
)
show
(
IntegerT
)
=
"integer"
show
(
Enum
mt
vals
r
)
=
printf
"enum %s{%s}%s"
tStr
(
commas
$
map
showVal
vals
)
(
showRanges
r
)
where
tStr
=
case
mt
of
Nothing
->
""
Just
t
->
(
show
t
)
++
" "
tStr
=
maybe
""
showPad
mt
showVal
::
(
Identifier
,
Maybe
Expr
)
->
String
showVal
(
x
,
e
)
=
x
++
(
showAssignment
e
)
data
Decl
=
Parameter
Type
Identifier
Expr
|
Localparam
Type
Identifier
Expr
|
Variable
Direction
Type
Identifier
[
Range
]
(
Maybe
Expr
)
deriving
Eq
instance
Show
Decl
where
showList
l
_
=
unlines'
$
map
show
l
show
(
Parameter
t
x
e
)
=
printf
"parameter %s%s = %s;"
(
showPad
t
)
x
(
show
e
)
show
(
Localparam
t
x
e
)
=
printf
"localparam %s%s = %s;"
(
showPad
t
)
x
(
show
e
)
show
(
Variable
d
t
x
a
me
)
=
printf
"%s%s %s%s%s;"
(
showPad
d
)
(
show
t
)
x
(
showRanges
a
)
(
showAssignment
me
)
data
ModuleItem
=
Comment
String
|
MIParameter
Parameter
|
MILocalparam
Localparam
|
MIIntegerV
IntegerV
|
PortDecl
Direction
[
Range
]
Identifier
|
LocalNet
Type
Identifier
RangesOrAssignment
|
MIDecl
Decl
|
AlwaysC
AlwaysKW
Stmt
|
Assign
LHS
Expr
|
Instance
Identifier
[
PortBinding
]
Identifier
(
Maybe
[
PortBinding
])
-- `Nothing` represents `.*`
|
Function
(
Maybe
FuncRet
)
Identifier
[(
Bool
,
BlockItemDeclaration
)
]
Stmt
|
Function
Type
Identifier
[
Decl
]
Stmt
|
Genvar
Identifier
|
Generate
[
GenItem
]
deriving
Eq
-- "function inputs and outputs are inferred to be of type reg if no internal
-- data types for the ports are declared"
data
AlwaysKW
=
Always
|
AlwaysComb
...
...
@@ -121,61 +132,29 @@ instance Show AlwaysKW where
show
AlwaysFF
=
"always_ff"
show
AlwaysLatch
=
"always_latch"
-- "function inputs and outputs are inferred to be of type reg if no internal
-- data types for the ports are declared"
type
PortBinding
=
(
Identifier
,
Maybe
Expr
)
data
Parameter
=
Parameter
(
Maybe
Range
)
Identifier
Expr
deriving
Eq
instance
Show
Parameter
where
show
(
Parameter
r
n
e
)
=
printf
"parameter %s%s = %s;"
(
showRange
r
)
n
(
show
e
)
data
Localparam
=
Localparam
(
Maybe
Range
)
Identifier
Expr
deriving
Eq
instance
Show
Localparam
where
show
(
Localparam
r
n
e
)
=
printf
"localparam %s%s = %s;"
(
showRange
r
)
n
(
show
e
)
data
IntegerV
=
IntegerV
Identifier
RangesOrAssignment
deriving
Eq
instance
Show
IntegerV
where
show
(
IntegerV
x
v
)
=
printf
"integer %s%s;"
x
(
showRangesOrAssignment
v
)
instance
Show
ModuleItem
where
show
thing
=
case
thing
of
Comment
c
->
"// "
++
c
MIParameter
nest
->
show
nest
MILocalparam
nest
->
show
nest
MIIntegerV
nest
->
show
nest
PortDecl
d
r
x
->
printf
"%s%s %s;"
(
show
d
)
(
showRanges
r
)
x
LocalNet
t
x
v
->
printf
"%s %s%s;"
(
show
t
)
x
(
showRangesOrAssignment
v
)
MIDecl
nest
->
show
nest
AlwaysC
k
b
->
printf
"%s %s"
(
show
k
)
(
show
b
)
Assign
a
b
->
printf
"assign %s = %s;"
(
show
a
)
(
show
b
)
Instance
m
params
i
ports
|
null
params
->
printf
"%s %s%s;"
m
i
(
showMaybePorts
ports
)
|
otherwise
->
printf
"%s #%s %s%s;"
m
(
showPorts
params
)
i
(
showMaybePorts
ports
)
Function
t
x
i
b
->
printf
"function %s%s;
\n
%s
\n
%s
\n
endfunction"
(
show
FuncRet
t
)
x
(
indent
$
unlines'
$
map
showFunctionItem
i
)
(
indent
$
show
b
)
Function
t
x
i
b
->
printf
"function %s%s;
\n
%s
\n
%s
\n
endfunction"
(
show
Pad
t
)
x
(
indent
$
show
i
)
(
indent
$
show
b
)
Genvar
x
->
printf
"genvar %s;"
x
Generate
b
->
printf
"generate
\n
%s
\n
endgenerate"
(
indent
$
unlines'
$
map
show
b
)
where
showMaybePorts
::
Maybe
[(
Identifier
,
Maybe
Expr
)]
->
String
showMaybePorts
Nothing
=
"(.*)"
showMaybePorts
(
Just
ports
)
=
showPorts
ports
showPorts
::
[(
Identifier
,
Maybe
Expr
)]
->
String
showPorts
ports
=
indentedParenList
[
if
i
==
""
then
show
(
fromJust
arg
)
else
printf
".%s(%s)"
i
(
if
isJust
arg
then
show
$
fromJust
arg
else
""
)
|
(
i
,
arg
)
<-
ports
]
showFunctionItem
::
(
Bool
,
BlockItemDeclaration
)
->
String
showFunctionItem
(
b
,
item
)
=
prefix
++
(
show
item
)
where
prefix
=
if
b
then
"input "
else
""
type
FuncRet
=
Either
Range
()
showFuncRet
::
Maybe
FuncRet
->
String
showFuncRet
Nothing
=
""
showFuncRet
(
Just
(
Left
r
))
=
showRange
$
Just
r
showFuncRet
(
Just
(
Right
()
))
=
"integer "
type
RangesOrAssignment
=
Either
[
Range
]
(
Maybe
Expr
)
showRangesOrAssignment
::
Either
[
Range
]
(
Maybe
Expr
)
->
String
showRangesOrAssignment
(
Left
ranges
)
=
showRanges
ranges
showRangesOrAssignment
(
Right
val
)
=
showAssignment
val
showMaybePorts
=
maybe
"(.*)"
showPorts
showPorts
::
[
PortBinding
]
->
String
showPorts
ports
=
indentedParenList
$
map
showPort
ports
showPort
::
PortBinding
->
String
showPort
(
i
,
arg
)
=
if
i
==
""
then
show
(
fromJust
arg
)
else
printf
".%s(%s)"
i
(
if
isJust
arg
then
show
$
fromJust
arg
else
""
)
showAssignment
::
Maybe
Expr
->
String
showAssignment
Nothing
=
""
...
...
@@ -190,6 +169,13 @@ showRange :: Maybe Range -> String
showRange
Nothing
=
""
showRange
(
Just
(
h
,
l
))
=
printf
"[%s:%s] "
(
show
h
)
(
show
l
)
showPad
::
Show
t
=>
t
->
String
showPad
x
=
if
str
==
""
then
""
else
str
++
" "
where
str
=
show
x
indent
::
String
->
String
indent
a
=
'
\t
'
:
f
a
where
...
...
@@ -331,13 +317,13 @@ instance Show CaseKW where
show
CaseX
=
"casex"
data
Stmt
=
Block
(
Maybe
(
Identifier
,
[
BlockItemDeclaration
]))
[
Stmt
]
|
Case
CaseKW
Expr
[
Case
]
(
Maybe
Stmt
)
|
BlockingAssignment
LHS
Expr
|
NonBlockingAssignment
LHS
Expr
|
For
(
Identifier
,
Expr
)
Expr
(
Identifier
,
Expr
)
Stmt
|
If
Expr
Stmt
Stmt
|
Timing
Sense
Stmt
=
Block
(
Maybe
(
Identifier
,
[
Decl
]))
[
Stmt
]
|
Case
CaseKW
Expr
[
Case
]
(
Maybe
Stmt
)
|
For
(
Identifier
,
Expr
)
Expr
(
Identifier
,
Expr
)
Stmt
|
AsgnBlk
LHS
Expr
|
Asgn
LHS
Expr
|
If
Expr
Stmt
Stmt
|
Timing
Sense
Stmt
|
Null
deriving
Eq
...
...
@@ -345,32 +331,27 @@ commas :: [String] -> String
commas
=
intercalate
", "
instance
Show
Stmt
where
show
(
Block
Nothing
b
)
=
printf
"begin
\n
%s
\n
end"
$
indent
$
unlines'
$
map
show
b
show
(
Block
(
Just
(
a
,
i
))
b
)
=
printf
"begin : %s
\n
%s
\n
end"
a
$
indent
$
unlines'
$
(
map
show
i
++
map
show
b
)
show
(
Case
kw
a
b
Nothing
)
=
printf
"%s (%s)
\n
%s
\n
endcase"
(
show
kw
)
(
show
a
)
(
indent
$
unlines'
$
map
showCase
b
)
show
(
Case
kw
a
b
(
Just
c
)
)
=
printf
"%s (%s)
\n
%s
\n\t
default:
\n
%s
\n
endcase"
(
show
kw
)
(
show
a
)
(
indent
$
unlines'
$
map
showCase
b
)
(
indent
$
indent
$
show
c
)
show
(
BlockingAssignment
a
b
)
=
printf
"%s = %s;"
(
show
a
)
(
show
b
)
show
(
NonBlockingAssignment
a
b
)
=
printf
"%s <= %s;"
(
show
a
)
(
show
b
)
show
(
For
(
a
,
b
)
c
(
d
,
e
)
f
)
=
printf
"for (%s = %s; %s; %s = %s)
\n
%s"
a
(
show
b
)
(
show
c
)
d
(
show
e
)
$
indent
$
show
f
show
(
If
a
b
Null
)
=
printf
"if (%s)
\n
%s"
(
show
a
)
(
indent
$
show
b
)
show
(
If
a
b
c
)
=
printf
"if (%s)
\n
%s
\n
else
\n
%s"
(
show
a
)
(
indent
$
show
b
)
(
indent
$
show
c
)
show
(
Timing
t
s
)
=
printf
"@(%s) %s"
(
show
t
)
(
show
s
)
show
(
Null
)
=
";"
data
BlockItemDeclaration
-- TODO: Maybe BIDReg should use [Range] for the first arg as well, but it's
-- really not clear to me what *useful* purpose this would have.
=
BIDReg
(
Maybe
Range
)
Identifier
[
Range
]
|
BIDParameter
Parameter
|
BIDLocalparam
Localparam
|
BIDIntegerV
IntegerV
deriving
Eq
instance
Show
BlockItemDeclaration
where
show
(
BIDReg
mr
x
rs
)
=
printf
"reg %s%s%s;"
(
showRange
mr
)
x
(
showRanges
rs
)
show
(
BIDParameter
nest
)
=
show
nest
show
(
BIDLocalparam
nest
)
=
show
nest
show
(
BIDIntegerV
nest
)
=
show
nest
show
(
Block
header
stmts
)
=
printf
"begin%s
\n
%s
\n
end"
extra
(
block
stmts
)
where
block
::
Show
t
=>
[
t
]
->
String
block
=
indent
.
unlines'
.
map
show
extra
=
case
header
of
Nothing
->
""
Just
(
x
,
i
)
->
printf
" : %s
\n
%s"
x
(
block
i
)
show
(
Case
kw
e
cs
def
)
=
printf
"%s (%s)
\n
%s%s
\n
endcase"
(
show
kw
)
(
show
e
)
(
indent
$
unlines'
$
map
showCase
cs
)
defStr
where
defStr
=
case
def
of
Nothing
->
""
Just
c
->
printf
"
\n\t
default:
\n
%s"
(
indent
$
indent
$
show
c
)
show
(
For
(
a
,
b
)
c
(
d
,
e
)
f
)
=
printf
"for (%s = %s; %s; %s = %s)
\n
%s"
a
(
show
b
)
(
show
c
)
d
(
show
e
)
$
indent
$
show
f
show
(
AsgnBlk
v
e
)
=
printf
"%s = %s;"
(
show
v
)
(
show
e
)
show
(
Asgn
v
e
)
=
printf
"%s <= %s;"
(
show
v
)
(
show
e
)
show
(
If
a
b
Null
)
=
printf
"if (%s)
\n
%s"
(
show
a
)
(
indent
$
show
b
)
show
(
If
a
b
c
)
=
printf
"if (%s)
\n
%s
\n
else
\n
%s"
(
show
a
)
(
indent
$
show
b
)
(
indent
$
show
c
)
show
(
Timing
t
s
)
=
printf
"@(%s) %s"
(
show
t
)
(
show
s
)
show
(
Null
)
=
";"
type
Case
=
([
Expr
],
Stmt
)
...
...
@@ -413,7 +394,7 @@ data GenItem
instance
Show
GenItem
where
showList
i
_
=
unlines'
$
map
show
i
show
(
GenBlock
Nothing
i
)
=
printf
"begin
\n
%s
\n
end"
(
indent
$
unlines'
$
map
show
i
)
show
(
GenBlock
Nothing
i
)
=
printf
"begin
\n
%s
\n
end"
(
indent
$
unlines'
$
map
show
i
)
show
(
GenBlock
(
Just
x
)
i
)
=
printf
"begin : %s
\n
%s
\n
end"
x
(
indent
$
unlines'
$
map
show
i
)
show
(
GenCase
e
c
Nothing
)
=
printf
"case (%s)
\n
%s
\n
endcase"
(
show
e
)
(
indent
$
unlines'
$
map
showCase
c
)
show
(
GenCase
e
c
(
Just
d
))
=
printf
"case (%s)
\n
%s
\n\t
default:
\n
%s
\n
endcase"
(
show
e
)
(
indent
$
unlines'
$
map
showCase
c
)
(
indent
$
indent
$
show
d
)
...
...
Language/SystemVerilog/Parser/Parse.y
View file @
50b7bf28
{
module Language.SystemVerilog.Parser.Parse (descriptions) where
import Data.Bits
import Data.List
import Data.Maybe
import Language.SystemVerilog.AST
import Language.SystemVerilog.Parser.Tokens
}
...
...
@@ -200,7 +199,7 @@ ParamDecls :: { [ModuleItem] }
: ParamDecl(")") { $1 }
| ParamDecl(",") ParamDecls { $1 ++ $2 }
ParamDecl(delim) :: { [ModuleItem] }
: "parameter"
opt(Range) DeclAsgns delim { map (MIParameter
. (uncurry $ Parameter $2)) $3 }
: "parameter"
ParamType DeclAsgns delim { map (MIDecl
. (uncurry $ Parameter $2)) $3 }
Identifier :: { Identifier }
: simpleIdentifier { tokenString $1 }
...
...
@@ -223,15 +222,16 @@ PortDeclsFollow :: { [ModuleItem] }
| PortDecl(",") PortDeclsFollow { $1 ++ $2 }
PortDecl(delim) :: { [ModuleItem] }
: "inout"
opt(NetType) Dimensions Identifiers delim { portDeclToModuleItems Inout $2 $3
(zip $4 (repeat Nothing)) }
| "input"
opt(NetType) Dimensions Identifiers delim { portDeclToModuleItems Input $2 $3
(zip $4 (repeat Nothing)) }
| "output"
Dimensions Identifiers delim { portDeclToModuleItems Output Nothing $2
(zip $3 (repeat Nothing)) }
| "output" "wire"
Dimensions Identifiers delim { portDeclToModuleItems Output (Just Wire ) $3
(zip $4 (repeat Nothing)) }
| "output" "reg"
Dimensions VariablePortIdentifiers delim { portDeclToModuleItems Output (Just Reg ) $3
$4 }
| "output" "logic"
Dimensions VariablePortIdentifiers delim { portDeclToModuleItems Output (Just Logic) $3
$4 }
: "inout"
NetType Dimensions Identifiers delim { portDeclToModuleItems Inout ($2 $3)
(zip $4 (repeat Nothing)) }
| "input"
NetType Dimensions Identifiers delim { portDeclToModuleItems Input ($2 $3)
(zip $4 (repeat Nothing)) }
| "output"
Dimensions Identifiers delim { portDeclToModuleItems Output (Implicit $2)
(zip $3 (repeat Nothing)) }
| "output" "wire"
Dimensions Identifiers delim { portDeclToModuleItems Output (Wire $3)
(zip $4 (repeat Nothing)) }
| "output" "reg"
Dimensions VariablePortIdentifiers delim { portDeclToModuleItems Output (Reg $3)
$4 }
| "output" "logic"
Dimensions VariablePortIdentifiers delim { portDeclToModuleItems Output (Logic $3)
$4 }
NetType :: { [Range] -> Type }
: "wire" { Wire }
| "logic" { Logic }
: "wire" { Wire }
| "logic" { Logic }
| {- empty -} { Implicit }
VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] }
: VariablePortIdentifier { [$1] }
| VariablePortIdentifiers "," VariablePortIdentifier { $1 ++ [$3] }
...
...
@@ -245,18 +245,15 @@ ModuleItems :: { [ModuleItem] }
ModuleItem :: { [ModuleItem] }
: PortDecl(";") { $1 }
-- TODO: Allowing Ranges on aliases creates conflicts
| Identifier VariableIdentifiers ";" { map (uncurry $ LocalNet (Alias $1 [])) $2 }
| Identifier DimensionsNonEmpty VariableIdentifiers ";" { map (uncurry $ LocalNet (Alias $1 $2)) $3 }
| TypeNonAlias VariableIdentifiers ";" { map (uncurry $ LocalNet $1) $2 }
| ParameterDeclaration { map MIParameter $1 }
| LocalparamDeclaration { map MILocalparam $1 }
| IntegerDeclaration { map MIIntegerV $1 }
| Identifier VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local (Alias $1 []) x a e) $2 }
| Identifier DimensionsNonEmpty VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local (Alias $1 $2) x a e) $3 }
| TypeNonAlias VariableIdentifiers ";" { map (\(x, a, e) -> MIDecl $ Variable Local $1 x a e) $2 }
| Declaration { map MIDecl $1 }
| "assign" LHS "=" Expr ";" { [Assign $2 $4] }
| AlwaysKW Stmt { [AlwaysC $1 $2] }
| Identifier ModuleInstantiations ";" { map (uncurry $ Instance $1 []) $2 }
| Identifier ParameterBindings ModuleInstantiations ";" { map (uncurry $ Instance $1 $2) $3 }
| "function"
opt(RangeOrType)
Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] }
| "function"
ParamType
Identifier FunctionItems Stmt "endfunction" { [Function $2 $3 $4 $5] }
| "genvar" Identifiers ";" { map Genvar $2 }
| "generate" GenItems "endgenerate" { [Generate $2] }
...
...
@@ -273,35 +270,32 @@ ModuleInstantiation :: { (Identifier, Maybe [PortBinding]) }
: Identifier "(" Bindings ")" { ($1, Just $3) }
| Identifier "(" ".*" ")" { ($1, Nothing) }
FunctionItems :: { [
(Bool, BlockItemDeclaration)
] }
: "(" FunctionPortList ";" BlockItemDeclarations {
(map ((,) True) $2) ++ (map ((,) False) $4)
}
| "(" FunctionPortList ";" {
(map ((,) True) $2)
}
FunctionItems :: { [
Decl
] }
: "(" FunctionPortList ";" BlockItemDeclarations {
$2 ++ $4
}
| "(" FunctionPortList ";" {
$2
}
| ";" FunctionItemDeclarations { $2 }
FunctionPortList :: { [
BlockItemDeclaration
] }
FunctionPortList :: { [
Decl
] }
: FunctionInputDeclaration(")") { $1 }
| FunctionInputDeclaration(",") FunctionPortList { $1 ++ $2 }
FunctionItemDeclarations :: { [
(Bool, BlockItemDeclaration)
] }
FunctionItemDeclarations :: { [
Decl
] }
: FunctionItemDeclaration { $1 }
| FunctionItemDeclarations FunctionItemDeclaration { $1 ++ $2 }
FunctionItemDeclaration :: { [(Bool, BlockItemDeclaration)] }
: BlockItemDeclaration { map ((,) False) $1 }
| FunctionInputDeclaration(";") { map ((,) True ) $1 }
FunctionInputDeclaration(delim) :: { [BlockItemDeclaration] }
: "input" opt("reg") opt(Range) Identifiers delim { map (\x -> BIDReg $3 x []) $4 }
| "input" "integer" Identifiers delim { map (\x -> BIDIntegerV $ IntegerV x $ Left []) $3 }
ParameterDeclaration :: { [Parameter] }
: "parameter" opt(Range) DeclAsgns ";" { map (uncurry $ Parameter $2) $3 }
LocalparamDeclaration :: { [Localparam] }
: "localparam" opt(Range) DeclAsgns ";" { map (uncurry $ Localparam $2) $3 }
IntegerDeclaration :: { [IntegerV] }
: "integer" VariableIdentifiers ";" { map (uncurry IntegerV) $2 }
RangeOrType :: { Either Range () }
: Range { Left $1 }
| "integer" { Right () }
FunctionItemDeclaration :: { [Decl] }
: BlockItemDeclaration { $1 }
| FunctionInputDeclaration(";") { $1 }
FunctionInputDeclaration(delim) :: { [Decl] }
: "input" Dimensions Identifiers delim { map (\x -> Variable Input (Implicit $2) x [] Nothing) $3 }
| "input" "reg" Dimensions Identifiers delim { map (\x -> Variable Input (Reg $3) x [] Nothing) $4 }
| "input" "integer" Identifiers delim { map (\x -> Variable Input IntegerT x [] Nothing) $3 }
Declaration :: { [Decl] }
: "parameter" ParamType DeclAsgns ";" { map (uncurry $ Parameter $2) $3 }
| "localparam" ParamType DeclAsgns ";" { map (uncurry $ Localparam $2) $3 }
| "integer" VariableIdentifiers ";" { map (\(x, a, e) -> Variable Local IntegerT x a e) $2 }
ParamType :: { Type }
: Dimensions { Implicit $1 }
| "integer" { IntegerT }
EventControl :: { Sense }
: "@" "(" Sense ")" { $3 }
...
...
@@ -310,13 +304,12 @@ EventControl :: { Sense }
| "@" "*" { SenseStar }
| "@*" { SenseStar }
VariableIdentifiers :: { [(Identifier,
Either [Range] (Maybe Expr)
)] }
VariableIdentifiers :: { [(Identifier,
[Range], Maybe Expr
)] }
: VariableType { [$1] }
| VariableIdentifiers "," VariableType { $1 ++ [$3] }
VariableType :: { (Identifier, Either [Range] (Maybe Expr)) }
: Identifier { ($1, Right $ Nothing) }
| Identifier "=" Expr { ($1, Right $ Just $3) }
| Identifier DimensionsNonEmpty { ($1, Left $2) }
VariableType :: { (Identifier, [Range], Maybe Expr) }
: Identifier Dimensions { ($1, $2, Nothing) }
| Identifier Dimensions "=" Expr { ($1, $2, Just $4) }
Dimensions :: { [Range] }
: {- empty -} { [] }
...
...
@@ -360,7 +353,7 @@ BindingsNonEmpty :: { [(Identifier, Maybe Expr)] }
: Binding { [$1] }
| Binding "," BindingsNonEmpty { $1 : $3}
Binding :: { (Identifier, Maybe Expr) }
: "." Identifier "("
MaybeExpr
")" { ($2, $4) }
: "." Identifier "("
opt(Expr)
")" { ($2, $4) }
| "." Identifier { ($2, Just $ Ident $2) }
| Expr { ("", Just $1) }
...
...
@@ -379,20 +372,18 @@ Stmt :: { Stmt }
| "if" "(" Expr ")" Stmt "else" Stmt { If $3 $5 $7 }
| "if" "(" Expr ")" Stmt %prec NoElse { If $3 $5 Null }
| "for" "(" Identifier "=" Expr ";" Expr ";" Identifier "=" Expr ")" Stmt { For ($3, $5) $7 ($9, $11) $13 }
| LHS "=" Expr ";" {
BlockingAssignment
$1 $3 }
| LHS "<=" Expr ";" {
NonBlockingAssignment
$1 $3 }
| LHS "=" Expr ";" {
AsgnBlk
$1 $3 }
| LHS "<=" Expr ";" {
Asgn
$1 $3 }
| CaseKW "(" Expr ")" Cases opt(CaseDefault) "endcase" { Case $1 $3 $5 $6 }
| EventControl Stmt { Timing $1 $2 }
BlockItemDeclarations :: { [
BlockItemDeclaration
] }
BlockItemDeclarations :: { [
Decl
] }
: BlockItemDeclaration { $1 }
| BlockItemDeclarations BlockItemDeclaration { $1 ++ $2 }
BlockItemDeclaration :: { [BlockItemDeclaration] }
: "reg" opt(Range) BlockVariableIdentifiers ";" { map (uncurry $ BIDReg $2) $3 }
| ParameterDeclaration { map BIDParameter $1 }
| LocalparamDeclaration { map BIDLocalparam $1 }
| IntegerDeclaration { map BIDIntegerV $1 }
BlockItemDeclaration :: { [Decl] }
: "reg" Dimensions BlockVariableIdentifiers ";" { map (\(x, rs) -> Variable Local (Reg $2) x rs Nothing) $3 }
| Declaration { $1 }
BlockVariableIdentifiers :: { [(Identifier, [Range])] }
: BlockVariableType { [$1] }
| BlockVariableIdentifiers "," BlockVariableType { $1 ++ [$3] }
...
...
@@ -420,16 +411,12 @@ Number :: { String }
: number { tokenString $1 }
String :: { String }
: string { to
String $1 }
: string { tail $ init $ token
String $1 }
CallArgs :: { [Expr] }
: Expr { [$1] }
| CallArgs "," Expr { $1 ++ [$3] }
MaybeExpr :: { Maybe Expr }
: { Nothing }
| Expr { Just $1 }
Exprs :: { [Expr] }
: Expr { [$1] }
| Exprs "," Expr { $1 ++ [$3] }
...
...
@@ -513,44 +500,19 @@ parseError a = case a of
[] -> error "Parse error: no tokens left to parse."
Token t s p : _ -> error $ "Parse error: unexpected token '" ++ s ++ "' (" ++ show t ++ ") at " ++ show p ++ "."
toString :: Token -> String
toString = tail . init . tokenString
portDeclToModuleItems
:: Direction
-> (Maybe ([Range] -> Type))
-> [Range]
-> [(Identifier, Maybe Expr)]
-> [ModuleItem]
portDeclToModuleItems dir Nothing rs l =
map (PortDecl dir rs) $ map toIdentifier $ l
where
toIdentifier (x, Just _) = error "ParseError: Incomplete port decl cannot have initialization"
toIdentifier (x, Nothing) = x
portDeclToModuleItems dir (Just tf) rs l =
concat $ map toItems l
where
toItems (x, e) =
[ PortDecl dir rs x
, LocalNet (tf rs) x (Right e) ]
portDeclToModuleItems :: Direction -> Type -> [PortBinding] -> [ModuleItem]
portDeclToModuleItems dir t l =
map (\(x, me) -> MIDecl $ Variable dir t x [] me) l
getPortNames :: [ModuleItem] -> [Identifier]
getPortNames items =
mapMaybe getPortName items
where
getPortName :: ModuleItem -> Maybe Identifier
getPortName (PortDecl _ _ ident) = Just ident
getPortName (MIDecl (Variable Local _ _ _ _)) = Nothing
getPortName (MIDecl (Variable _ _ ident _ _)) = Just ident
getPortName _ = Nothing
stmtsToStmt :: [Stmt] -> Stmt
stmtsToStmt [] = error "stmtsToStmt given empty list!"
stmtsToStmt [s] = s
stmtsToStmt ss = Block Nothing ss
moduleItemsToSingleGenItem :: [ModuleItem] -> GenItem
moduleItemsToSingleGenItem [x] = GenModuleItem x
moduleItemsToSingleGenItem other = error $ "multiple module items in a generate block where only one was allowed" ++ show other
genItemsToGenItem :: [GenItem] -> GenItem
genItemsToGenItem [] = error "genItemsToGenItem given empty list!"
genItemsToGenItem [x] = x
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment