Sockeye: Implement import support
authorDaniel Schwyn <schwyda@student.ethz.ch>
Tue, 18 Jul 2017 12:32:27 +0000 (14:32 +0200)
committerDaniel Schwyn <schwyda@student.ethz.ch>
Tue, 18 Jul 2017 12:32:27 +0000 (14:32 +0200)
Signed-off-by: Daniel Schwyn <schwyda@student.ethz.ch>

tools/sockeye/Main.hs
tools/sockeye/SockeyeASTParser.hs
tools/sockeye/SockeyeParser.hs

index c93cf21..9b9a1d1 100644 (file)
@@ -16,6 +16,8 @@ module Main where
 import Control.Monad
 
 import Data.List
+import Data.Map (Map)
+import qualified Data.Map as Map
 
 import System.Console.GetOpt
 import System.Exit
@@ -32,6 +34,9 @@ import SockeyeNetBuilder
 
 import qualified SockeyeBackendProlog as Prolog
 
+import Debug.Trace
+import Text.Groom(groom)
+
 {- Exit codes -}
 usageError :: ExitCode
 usageError = ExitFailure 1
@@ -120,7 +125,36 @@ compilerOpts argv =
             usage errors
             exitWith $ usageError
 
-{- Runs the parser -}
+{- Parse Sockeye and resolve imports -}
+parseSpec :: FilePath -> IO (ParseAST.SockeyeSpec)
+parseSpec file = do
+    let
+        rootImport = ParseAST.Import file
+    specMap <- parseWithImports Map.empty rootImport
+    let
+        specs = Map.elems specMap
+        topLevelSpec = specMap Map.! file
+        modules = concat $ map ParseAST.modules specs
+    return topLevelSpec
+        { ParseAST.imports = []
+        , ParseAST.modules = modules
+        }
+    where
+        parseWithImports importMap (ParseAST.Import fileName) = do
+            let
+                file = if '.' `elem` fileName
+                    then fileName
+                    else fileName ++ ".soc"
+            if file `Map.member` importMap
+                then return importMap
+                else do
+                    ast <- parseFile file
+                    let
+                        specMap = Map.insert file ast importMap
+                        imports = ParseAST.imports ast
+                    foldM parseWithImports specMap imports
+
+{- Runs the parser on a single file -}
 parseFile :: FilePath -> IO (ParseAST.SockeyeSpec)
 parseFile file = do
     src <- readFile file
@@ -164,7 +198,8 @@ main = do
     args <- getArgs
     opts <- compilerOpts args
     let inFile = optInputFile opts
-    parsedAst <- parseFile inFile
+    parsedAst <- parseSpec inFile
+    -- trace (groom parsedAst) $ return ()
     ast <- checkAST parsedAst
     netAst <- buildNet ast
     out <- compile (optTarget opts) netAst
index 06de7f3..e74c9bf 100644 (file)
@@ -35,10 +35,16 @@ import SockeyeAST
     )
 
 data SockeyeSpec = SockeyeSpec
-    { modules :: [Module]
+    { imports :: [Import]
+    , modules :: [Module]
     , net     :: [NetSpec]
     } deriving (Show)
 
+
+data Import = Import 
+    { filePath :: !FilePath }
+    deriving (Show)
+
 data Module = Module
     { name       :: String
     , parameters :: [ModuleParam]
index 9ac7778..78bd0fc 100644 (file)
@@ -38,13 +38,21 @@ sockeyeFile = do
     return spec
 
 sockeyeSpec = do
+    imports <- many imports
     modules <- many sockeyeModule
     net <- many netSpecs
     return AST.SockeyeSpec
-        { AST.modules = modules
+        { AST.imports = imports
+        , AST.modules = modules
         , AST.net     = concat net
         }
 
+imports = do
+    reserved "import"
+    path <- try importPath <?> "import path"
+    return $ AST.Import path
+
+
 sockeyeModule = do
     reserved "module"
     name <- moduleName
@@ -325,7 +333,7 @@ identString    = P.identifier lexer
 hexadecimal   = symbol "0" *> P.hexadecimal lexer <* whiteSpace
 decimal       = P.decimal lexer <* whiteSpace
 
-keywords = ["module",
+keywords = ["import", "module",
             "input", "output",
             "in",
             "as", "with",
@@ -337,6 +345,7 @@ keywords = ["module",
 identStart     = letter
 identLetter    = alphaNum <|> char '_' <|> char '-'
 
+importPath     = many (identLetter <|> char '/') <* whiteSpace
 moduleName     = identString <?> "module name"
 parameterName  = identString <?> "parameter name"
 variableName   = identString <?> "variable name"