From 43d3dd7a2852136c43008cd80ab8020f3ec730f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Fri, 17 Mar 2023 14:51:15 +0800 Subject: [PATCH 1/6] extract `codegen` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- app/Main.hs | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 50c990a..b55d95c 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -18,43 +18,33 @@ import Wit handle :: [String] -> IO () handle ["version"] = putStrLn "0.2.0" +-- validation handle ["check", file] = checkFileWithDoneHint file handle ["check"] = do dir <- getCurrentDirectory witFileList <- filter (".wit" `isSuffixOf`) <$> listDirectory dir mapM_ checkFileWithDoneHint witFileList -handle ["instance", "import", file, importName] = - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Import, side = Instance} importName) -handle ["runtime", "import", file, importName] = - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Import, side = Runtime} importName) +-- codegen +handle ["instance", "import", file, importName] = codegen file Import Instance importName +handle ["runtime", "import", file, importName] = codegen file Import Runtime importName handle ["instance", mode, file] = do case mode of - "import" -> - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Import, side = Instance} "wasmedge") - "export" -> - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Export, side = Instance} "wasmedge") + "import" -> codegen file Import Instance "wasmedge" + "export" -> codegen file Export Instance "wasmedge" bad -> putStrLn $ "unknown option: " ++ bad handle ["runtime", mode, file] = case mode of - "import" -> - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Import, side = Runtime} "wasmedge") - "export" -> - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = Export, side = Runtime} "wasmedge") + "import" -> codegen file Import Runtime "wasmedge" + "export" -> codegen file Export Runtime "wasmedge" bad -> putStrLn $ "unknown option: " ++ bad handle _ = putStrLn "bad usage" +codegen :: FilePath -> Direction -> Side -> String -> IO () +codegen file direction side importName = + parseFile file + >>= eitherIO check0 + >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = direction, side = side} importName) + checkFileWithDoneHint :: FilePath -> IO () checkFileWithDoneHint file = do checkFile file $> () From da7ad857e439fced1b6e6f6bd83b21ef3641cfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 21 Mar 2023 11:10:48 +0800 Subject: [PATCH 2/6] introduce `optparse-applicative` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- app/Main.hs | 126 +++++++++++++++++++++++++++++++++++++++------------ package.yaml | 1 + witc.cabal | 3 ++ 3 files changed, 100 insertions(+), 30 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index b55d95c..48d4619 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -8,49 +8,115 @@ cli design -} module Main (main) where +import Control.Monad import Data.Functor import Data.List (isSuffixOf) +import Options.Applicative import Prettyprinter import Prettyprinter.Render.Terminal import System.Directory -import System.Environment import Wit -handle :: [String] -> IO () -handle ["version"] = putStrLn "0.2.0" --- validation -handle ["check", file] = checkFileWithDoneHint file -handle ["check"] = do +main :: IO () +main = do + join $ + execParser + ( info + (helper <*> versionOption <*> programOptions) + ( fullDesc + <> progDesc "compiler for wit" + <> header + "witc - compiler for wit, a language for describing wasm interface types" + ) + ) + where + versionOption :: Parser (a -> a) + versionOption = infoOption "0.2" (long "version" <> help "Show version") + programOptions :: Parser (IO ()) + programOptions = + subparser + ( command + "check" + ( info + (check <$> optional (strArgument (metavar "FILE" <> help "Name of the thing to create"))) + (progDesc "Validate wit file") + ) + <> command + "instance" + ( info + ( subparser + ( command + "import" + ( info + ( instanceImport + <$> strArgument (metavar "FILE" <> help "Wit file") + <*> optional (strArgument (metavar "NAME" <> help "Name of import")) + ) + (progDesc "test") + ) + <> command + "export" + ( info + (instanceExport <$> strArgument (metavar "FILE" <> help "Wit file")) + (progDesc "test") + ) + ) + ) + (progDesc "Generate code for instance (wasm)") + ) + <> command + "runtime" + ( info + ( subparser + ( command + "import" + ( info + ( runtimeImport + <$> strArgument (metavar "FILE" <> help "Wit file") + <*> optional (strArgument (metavar "NAME" <> help "Name of import")) + ) + (progDesc "test") + ) + <> command + "export" + ( info + (runtimeExport <$> strArgument (metavar "FILE" <> help "Wit file")) + (progDesc "test") + ) + ) + ) + (progDesc "Generate code for runtime (WasmEdge)") + ) + ) + +check :: Maybe FilePath -> IO () +check (Just file) = checkFileWithDoneHint file +check Nothing = do dir <- getCurrentDirectory witFileList <- filter (".wit" `isSuffixOf`) <$> listDirectory dir mapM_ checkFileWithDoneHint witFileList --- codegen -handle ["instance", "import", file, importName] = codegen file Import Instance importName -handle ["runtime", "import", file, importName] = codegen file Import Runtime importName -handle ["instance", mode, file] = do - case mode of - "import" -> codegen file Import Instance "wasmedge" - "export" -> codegen file Export Instance "wasmedge" - bad -> putStrLn $ "unknown option: " ++ bad -handle ["runtime", mode, file] = - case mode of - "import" -> codegen file Import Runtime "wasmedge" - "export" -> codegen file Export Runtime "wasmedge" - bad -> putStrLn $ "unknown option: " ++ bad -handle _ = putStrLn "bad usage" - -codegen :: FilePath -> Direction -> Side -> String -> IO () -codegen file direction side importName = - parseFile file - >>= eitherIO check0 - >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = direction, side = side} importName) checkFileWithDoneHint :: FilePath -> IO () checkFileWithDoneHint file = do checkFile file $> () putDoc $ pretty file <+> annotate (color Green) (pretty "OK") <+> line -main :: IO () -main = do - args <- getArgs - handle args +instanceImport :: FilePath -> Maybe String -> IO () +instanceImport file (Just importName) = codegen file Import Instance importName +instanceImport file Nothing = codegen file Import Instance "wasmedge" + +instanceExport :: FilePath -> IO () +instanceExport file = codegen file Export Instance "wasmedge" + +runtimeImport :: FilePath -> Maybe String -> IO () +runtimeImport file (Just importName) = codegen file Import Runtime importName +runtimeImport file Nothing = codegen file Import Runtime "wasmedge" + +runtimeExport :: FilePath -> IO () +runtimeExport file = codegen file Export Runtime "wasmedge" + +codegen :: FilePath -> Direction -> Side -> String -> IO () +codegen file d s importName = + parseFile file + >>= eitherIO check0 + >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = d, side = s} importName) diff --git a/package.yaml b/package.yaml index ae751af..0957499 100644 --- a/package.yaml +++ b/package.yaml @@ -32,6 +32,7 @@ dependencies: - prettyprinter - prettyprinter-ansi-terminal - template-haskell + - optparse-applicative ghc-options: - -Wall diff --git a/witc.cabal b/witc.cabal index d8a7823..64ffcb7 100644 --- a/witc.cabal +++ b/witc.cabal @@ -53,6 +53,7 @@ library , directory , megaparsec , mtl + , optparse-applicative , prettyprinter , prettyprinter-ansi-terminal , primitive @@ -79,6 +80,7 @@ executable witc-exe , directory , megaparsec , mtl + , optparse-applicative , prettyprinter , prettyprinter-ansi-terminal , primitive @@ -111,6 +113,7 @@ test-suite witc-test , hspec-megaparsec , megaparsec , mtl + , optparse-applicative , prettyprinter , prettyprinter-ansi-terminal , primitive From 5d52374e12fe75ae7e9c2dd5c4c271b71c07fbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 21 Mar 2023 11:24:49 +0800 Subject: [PATCH 3/6] remove middle helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- app/Main.hs | 38 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 48d4619..69f530b 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -48,17 +48,17 @@ main = do ( command "import" ( info - ( instanceImport + ( codegen Import Instance <$> strArgument (metavar "FILE" <> help "Wit file") - <*> optional (strArgument (metavar "NAME" <> help "Name of import")) + <*> strArgument (value "wasmedge" <> help "Name of import") ) - (progDesc "test") + (progDesc "Generate import code for instance (wasm)") ) <> command "export" ( info - (instanceExport <$> strArgument (metavar "FILE" <> help "Wit file")) - (progDesc "test") + ((\f -> codegen Export Instance f "wasmedge") <$> strArgument (metavar "FILE" <> help "Wit file")) + (progDesc "Generate export code for instance (wasm)") ) ) ) @@ -71,17 +71,17 @@ main = do ( command "import" ( info - ( runtimeImport + ( codegen Import Runtime <$> strArgument (metavar "FILE" <> help "Wit file") - <*> optional (strArgument (metavar "NAME" <> help "Name of import")) + <*> strArgument (value "wasmedge" <> help "Name of import") ) - (progDesc "test") + (progDesc "Generate import code for runtime (WasmEdge)") ) <> command "export" ( info - (runtimeExport <$> strArgument (metavar "FILE" <> help "Wit file")) - (progDesc "test") + ((\f -> codegen Export Runtime f "wasmedge") <$> strArgument (metavar "FILE" <> help "Wit file")) + (progDesc "Generate export code for runtime (WasmEdge)") ) ) ) @@ -101,22 +101,8 @@ checkFileWithDoneHint file = do checkFile file $> () putDoc $ pretty file <+> annotate (color Green) (pretty "OK") <+> line -instanceImport :: FilePath -> Maybe String -> IO () -instanceImport file (Just importName) = codegen file Import Instance importName -instanceImport file Nothing = codegen file Import Instance "wasmedge" - -instanceExport :: FilePath -> IO () -instanceExport file = codegen file Export Instance "wasmedge" - -runtimeImport :: FilePath -> Maybe String -> IO () -runtimeImport file (Just importName) = codegen file Import Runtime importName -runtimeImport file Nothing = codegen file Import Runtime "wasmedge" - -runtimeExport :: FilePath -> IO () -runtimeExport file = codegen file Export Runtime "wasmedge" - -codegen :: FilePath -> Direction -> Side -> String -> IO () -codegen file d s importName = +codegen :: Direction -> Side -> FilePath -> String -> IO () +codegen d s file importName = parseFile file >>= eitherIO check0 >>= eitherIO (putDoc . prettyFile Config {language = Rust, direction = d, side = s} importName) From 08bb53ac45bef9cce60b6fd8555fb0b8b91699dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 21 Mar 2023 11:36:30 +0800 Subject: [PATCH 4/6] update CHANGELOG at once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f53b6..2e80640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to the ## Unreleased +- command line interface get improved (with `--help` and subcommand) +- check imports existed, e.g. `use {a, b, c} from m` will ensure `m` does have type definition `a`, `b`, and `c` + ## 0.1.0.0 - wasm interface types supporting From 33f881b0d4a7e05c3ad55fa13e333ab6b7922265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 21 Mar 2023 11:37:33 +0800 Subject: [PATCH 5/6] fix version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- app/Main.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Main.hs b/app/Main.hs index 69f530b..9015d76 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -31,7 +31,7 @@ main = do ) where versionOption :: Parser (a -> a) - versionOption = infoOption "0.2" (long "version" <> help "Show version") + versionOption = infoOption "0.2.0" (long "version" <> help "Show version") programOptions :: Parser (IO ()) programOptions = subparser From c25bff5b8f4ad27c4be19ad4f5ed496fbabbfb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AEm=20Ts=C3=BA-thu=C3=A0n?= Date: Tue, 21 Mar 2023 13:13:16 +0800 Subject: [PATCH 6/6] fix version getting in bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lîm Tsú-thuàn --- bindings/rust/invoke-witc/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bindings/rust/invoke-witc/src/lib.rs b/bindings/rust/invoke-witc/src/lib.rs index 6ca11db..7988581 100644 --- a/bindings/rust/invoke-witc/src/lib.rs +++ b/bindings/rust/invoke-witc/src/lib.rs @@ -19,7 +19,10 @@ fn name_value_meta(meta: &Meta) -> (String, String) { } fn check_version() { - let ver_output = Command::new("witc-exe").args(["version"]).output().unwrap(); + let ver_output = Command::new("witc-exe") + .args(["--version"]) + .output() + .unwrap(); let ver = String::from_utf8(ver_output.stdout).unwrap(); if ver != "0.2.0\n" { panic!("witc-exe version mismatch: expected 0.2.0, got {}", ver);