Sockeye: Introduce for loops
authorDaniel Schwyn <schwyda@student.ethz.ch>
Fri, 30 Jun 2017 20:47:04 +0000 (22:47 +0200)
committerDaniel Schwyn <schwyda@student.ethz.ch>
Fri, 30 Jun 2017 21:08:33 +0000 (23:08 +0200)
Signed-off-by: Daniel Schwyn <schwyda@student.ethz.ch>

tools/sockeye/SockeyeASTFrontend.hs
tools/sockeye/SockeyeParser.hs

index f41e935..ce3569d 100644 (file)
@@ -37,14 +37,20 @@ data ModuleParamType
     deriving (Show)
 
 data ModuleBody = ModuleBody
-    { inputPorts  :: [Identifier]
-    , outputPorts :: [Identifier]
-    , moduleNet   :: [NetSpec]
+    { ports     :: [PortDef]
+    , moduleNet :: [NetSpec]
     } deriving (Show)
 
+data PortDef
+    = InputPortDef [Identifier]
+    | OutputPortDef [Identifier]
+    | MultiPortDef (For [PortDef])
+    deriving (Show)
+
 data NetSpec
     = NodeDeclSpec NodeDecl
     | ModuleInstSpec ModuleInst
+    | MultiNetSpec (For [NetSpec])
     deriving (Show)
 
 data ModuleInst
@@ -52,7 +58,7 @@ data ModuleInst
         { moduleName   :: String
         , nameSpace    :: Identifier
         , arguments    :: [ModuleArg]
-        , portMappings :: [ModulePortMap]
+        , portMappings :: [PortMap]
         } deriving (Show)
 
 data ModuleArg
@@ -61,7 +67,7 @@ data ModuleArg
     | ParamArg !String
     deriving (Show)
 
-data ModulePortMap
+data PortMap
     = InputPortMap
         { port   :: Identifier
         , nodeId :: Identifier
@@ -69,7 +75,9 @@ data ModulePortMap
     | OutputPortMap
         { port   :: Identifier
         , nodeId :: Identifier
-        } deriving (Show)
+        }
+    | MultiPortMap (For [PortMap])
+    deriving (Show)
 
 data NodeDecl
     = NodeDecl
@@ -78,22 +86,14 @@ data NodeDecl
         } deriving (Show)
 
 data Identifier
-    = Single
-        { prefix :: !String }
-    | Indexed
-        { prefix :: !String }            
-    | Multi
-        { prefix :: !String
-        , start  :: IdentifierIndex
-        , end    :: IdentifierIndex
+    = SimpleIdent !String
+    | TemplateIdent
+        { prefix  :: !String
+        , varName :: !String
+        , suffix  :: Maybe Identifier
         }
     deriving (Show)
 
-data IdentifierIndex 
-    = NumberIndex !Word
-    | ParamIndex !String
-    deriving (Show)
-
 data NodeSpec = NodeSpec
     { nodeType  :: Maybe NodeType
     , accept    :: [BlockSpec]
@@ -124,10 +124,11 @@ data Address
     | ParamAddress !String
     deriving (Show)
 
-data MapSpec = MapSpec
-    { block :: BlockSpec
-    , dests :: [MapDest]
-    } deriving (Show)
+data MapSpec 
+    = MapSpec
+        { block :: BlockSpec
+        , dests :: [MapDest]
+        } deriving (Show)
 
 data MapDest
     = Direct
@@ -137,3 +138,16 @@ data MapDest
         , destBase :: Address
         }
     deriving (Show)
+
+data For a 
+    = For
+        { var     :: !String
+        , start   :: ForLimit
+        , end     :: ForLimit
+        , body    :: a
+        } deriving (Show)
+
+data ForLimit 
+    = NumberLimit !Word
+    | ParamLimit !String
+    deriving (Show)
index 47d9d2f..2d160b0 100644 (file)
@@ -33,6 +33,7 @@ lexer = P.makeTokenParser (
         P.reservedNames = [
             "module",
             "input", "output",
+            "for", "in",
             "as", "with",
             "is", "are",
             "accept", "map",
@@ -41,8 +42,8 @@ lexer = P.makeTokenParser (
         ],
 
         {- valid identifiers -}
-        P.identStart = letter,
-        P.identLetter = alphaNum <|> char '_' <|> char '-',
+        P.identStart = identStart,
+        P.identLetter = identLetter,
 
         {- comment start and end -}
         P.commentStart = "/*",
@@ -97,24 +98,30 @@ moduleParam = do
             return AST.AddressParam
 
 moduleBody = do
-    inputPorts <- many inputPort
-    outputPorts <- many outputPort
+    ports <- many $ try portDef
     net <- many netSpec
     return AST.ModuleBody
-        { AST.inputPorts  = concat inputPorts
-        , AST.outputPorts = concat outputPorts
-        , AST.moduleNet   = net
+        { AST.ports     = ports
+        , AST.moduleNet = net
         }
+
+portDef = choice [inputPort, outputPort, multiPorts]
     where
         inputPort = do
             reserved "input"
-            commaSep1 identifier
+            idens <- commaSep1 identifier
+            return $ AST.InputPortDef idens
         outputPort = do
             reserved "output"
-            commaSep1 identifier
+            idens <- commaSep1 identifier
+            return $ AST.OutputPortDef idens
+        multiPorts = do
+            for <- for $ many1 portDef
+            return $ AST.MultiPortDef for
 
 netSpec = choice [ inst <?> "module instantiation"
                  , decl <?> "node declaration"
+                 , multiSpecs
                  ]
     where
         inst = do
@@ -123,6 +130,9 @@ netSpec = choice [ inst <?> "module instantiation"
         decl = do
             nodeDecl <- nodeDecl
             return $ AST.NodeDeclSpec nodeDecl
+        multiSpecs = do
+            for <- for $ many1 netSpec
+            return $ AST.MultiNetSpec for
 
 moduleInst = do
     (name, args) <- try $ do
@@ -130,15 +140,28 @@ moduleInst = do
         args <- option [] $ parens (commaSep moduleArg)
         symbol "as"
         return (name, args)
-    nameSpace <- nonIndexedIdentifier
-    symbol "with"
-    portMappings <- many $ choice [inputMapping, outputMapping]
+    nameSpace <- identifier
+    portMappings <- option [] $ symbol "with" *> many1 portMapping
     return AST.ModuleInst
         { AST.moduleName = name
         , AST.nameSpace  = nameSpace
         , AST.arguments  = args 
         , AST.portMappings = portMappings
         }
+
+moduleArg = choice [addressArg, numberArg, paramArg]
+    where
+        addressArg = do
+            addr <- addressLiteral
+            return $ AST.AddressArg (fromIntegral addr)
+        numberArg = do
+            num <- numberLiteral
+            return $ AST.NumberArg (fromIntegral num)
+        paramArg = do
+            name <- parameterName
+            return $ AST.ParamArg name
+
+portMapping = choice [inputMapping, outputMapping, multiMapping]
     where
         inputMapping = do
             nodeId <- try $ identifier <* symbol ">"
@@ -154,18 +177,9 @@ moduleInst = do
                 { AST.port   = port
                 , AST.nodeId = nodeId
                 }
-
-moduleArg = choice [addressArg, numberArg, paramArg]
-    where
-        addressArg = do
-            addr <- addressLiteral
-            return $ AST.AddressArg (fromIntegral addr)
-        numberArg = do
-            num <- numberLiteral
-            return $ AST.NumberArg (fromIntegral num)
-        paramArg = do
-            name <- parameterName
-            return $ AST.ParamArg name
+        multiMapping = do
+            for <- for $ many1 portMapping
+            return $ AST.MultiPortMap for
 
 nodeDecl = do
     nodeIds <- choice [try single, try multiple]
@@ -175,48 +189,30 @@ nodeDecl = do
         , AST.nodeSpec = nodeSpec
         }
     where single = do
-            nodeId <- singleIdentifier
+            nodeId <- identifier
             reserved "is"
             return [nodeId]
           multiple = do
-            nodeIds <- many1 nonIndexedIdentifier
+            nodeIds <- commaSep1 identifier
             reserved "are"
             return nodeIds
 
-singleIdentifier = do
-    prefix <- identifierName
-    return $ AST.Single prefix
-
-indexedIdentifier = do
-    prefix <- try $ identifierName <* symbol "#"
-    return $ AST.Indexed prefix
-
-multiIdentifier = do
-    prefix <- try $ identifierName <* symbol "["
-    start <- index
-    symbol ".."
-    end <- index
-    symbol "]"
-    return AST.Multi
-        { AST.prefix = prefix
-        , AST.start  = start
-        , AST.end    = end
-        }
+identifier = choice [template identifierName, simple identifierName] <* whiteSpace
     where
-        index = choice [numberIndex, paramIndex]
-        numberIndex = do
-            num <- numberLiteral
-            return $ AST.NumberIndex (fromIntegral num)
-        paramIndex = do
-            name <- parameterName
-            return $ AST.ParamIndex name
-
-identifier = choice [ multiIdentifier
-                    , indexedIdentifier
-                    , singleIdentifier
-                    ]
-
-nonIndexedIdentifier = choice [multiIdentifier, singleIdentifier]
+        simple ident = do
+            name <- ident
+            return $ AST.SimpleIdent name
+        template ident = do
+            prefix <- try $ ident <* char '#'
+            varName <- char '{' *> variableName <* char '}'
+            suffix <- optionMaybe $ choice [ template $ many identLetter
+                                           , simple $ many1 identLetter
+                                           ]
+            return AST.TemplateIdent
+                { AST.prefix  = prefix
+                , AST.varName = varName
+                , AST.suffix   = suffix
+                }
 
 nodeSpec = do
     nodeType <- optionMaybe $ try nodeType
@@ -238,7 +234,7 @@ nodeSpec = do
             brackets $ many mapSpec
         overlay = do
             reserved "over"
-            singleIdentifier
+            identifier
 
 nodeType = choice [memory, device]
     where memory = do
@@ -287,6 +283,33 @@ mapDest = choice [baseAddress, direct]
             destBase <- address
             return $ AST.BaseAddress destNode destBase
 
+for body = do
+    reserved "for"
+    var <- variableName
+    reserved "in"
+    (start, end) <- brackets forRange
+    body <- braces body
+    return AST.For
+        { AST.var   = var
+        , AST.start = start
+        , AST.end   = end
+        , AST.body  = body
+        }
+        
+forRange = do
+    start <- index
+    symbol ".."
+    end <- index
+    return (start, end)
+    where
+        index = choice [numberIndex, paramIndex]
+        numberIndex = do
+            num <- numberLiteral
+            return $ AST.NumberLimit (fromIntegral num)
+        paramIndex = do
+            name <- parameterName
+            return $ AST.ParamLimit name
+
 {- Helper functions -}
 whiteSpace    = P.whiteSpace lexer
 reserved      = P.reserved lexer
@@ -303,7 +326,15 @@ decimal       = P.decimal lexer <* whiteSpace
 
 moduleName     = idenString <?> "module name"
 parameterName  = idenString <?> "parameter name"
-identifierName = idenString <?> "identifier"
+variableName   = idenString <?> "variable name"
+
+identStart      = letter
+identLetter     = alphaNum <|> char '_' <|> char '-'
+identifierName = do
+    start <- identStart
+    rest <- many identLetter
+    return $ start:rest
+    <?> "identifier"
 
 numberLiteral  = try decimal <?> "number literal"
 addressLiteral = try hexadecimal <?> "address literal (hex)"
\ No newline at end of file