Skip to content

Commit

Permalink
extract codegen & introduce optparse-applicative (#73)
Browse files Browse the repository at this point in the history
- introduce `optparse-applicative` to parse CLI input
- extract `codegen` to simplify program

With optparse, user can get CLI helps
```shell
$ witc-exe -h instance
Usage: witc-exe instance COMMAND

  Generate code for instance (wasm)

Available commands:
  import                   Generate import code for instance (wasm)
  export                   Generate export code for instance (wasm)
```
  • Loading branch information
dm4 authored Mar 21, 2023
2 parents 4630af2 + c25bff5 commit 2bb8b07
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 41 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
122 changes: 82 additions & 40 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,101 @@ 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"
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.0" (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
( codegen Import Instance
<$> strArgument (metavar "FILE" <> help "Wit file")
<*> strArgument (value "wasmedge" <> help "Name of import")
)
(progDesc "Generate import code for instance (wasm)")
)
<> command
"export"
( info
((\f -> codegen Export Instance f "wasmedge") <$> strArgument (metavar "FILE" <> help "Wit file"))
(progDesc "Generate export code for instance (wasm)")
)
)
)
(progDesc "Generate code for instance (wasm)")
)
<> command
"runtime"
( info
( subparser
( command
"import"
( info
( codegen Import Runtime
<$> strArgument (metavar "FILE" <> help "Wit file")
<*> strArgument (value "wasmedge" <> help "Name of import")
)
(progDesc "Generate import code for runtime (WasmEdge)")
)
<> command
"export"
( info
((\f -> codegen Export Runtime f "wasmedge") <$> strArgument (metavar "FILE" <> help "Wit file"))
(progDesc "Generate export code for runtime (WasmEdge)")
)
)
)
(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
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)
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")
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")
bad -> putStrLn $ "unknown option: " ++ bad
handle _ = putStrLn "bad usage"

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
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)
5 changes: 4 additions & 1 deletion bindings/rust/invoke-witc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dependencies:
- prettyprinter
- prettyprinter-ansi-terminal
- template-haskell
- optparse-applicative

ghc-options:
- -Wall
Expand Down
3 changes: 3 additions & 0 deletions witc.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ library
, directory
, megaparsec
, mtl
, optparse-applicative
, prettyprinter
, prettyprinter-ansi-terminal
, primitive
Expand All @@ -79,6 +80,7 @@ executable witc-exe
, directory
, megaparsec
, mtl
, optparse-applicative
, prettyprinter
, prettyprinter-ansi-terminal
, primitive
Expand Down Expand Up @@ -111,6 +113,7 @@ test-suite witc-test
, hspec-megaparsec
, megaparsec
, mtl
, optparse-applicative
, prettyprinter
, prettyprinter-ansi-terminal
, primitive
Expand Down

0 comments on commit 2bb8b07

Please sign in to comment.