From 6167580bc4407dc40fe1e5d81512d44f894b221e Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Sat, 18 Feb 2017 17:57:37 +0100 Subject: [PATCH] first commit for lish --- .gitignore | 2 ++ .travis.yml | 35 +++++++++++++++++++ CHANGELOG.md | 12 +++++++ LICENSE | 13 +++++++ README.md | 6 ++++ Setup.hs | 2 ++ lish.cabal | 79 +++++++++++++++++++++++++++++++++++++++++++ src-benchmark/Main.hs | 7 ++++ src-doctest/Main.hs | 5 +++ src-exe/Main.hs | 4 +++ src-test/Main.hs | 38 +++++++++++++++++++++ src/Lib.hs | 24 +++++++++++++ src/Lish/Core.hs | 66 ++++++++++++++++++++++++++++++++++++ stack.yaml | 67 ++++++++++++++++++++++++++++++++++++ 14 files changed, 360 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 Setup.hs create mode 100644 lish.cabal create mode 100644 src-benchmark/Main.hs create mode 100644 src-doctest/Main.hs create mode 100644 src-exe/Main.hs create mode 100644 src-test/Main.hs create mode 100644 src/Lib.hs create mode 100644 src/Lish/Core.hs create mode 100644 stack.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f25d1fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/tutorial.md +/.stack-work/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3066175 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +# Use new container infrastructure to enable caching +sudo: false + +# Choose a lightweight base image; we provide our own build tools. +language: c + +# GHC depends on GMP. You can add other dependencies here as well. +addons: + apt: + packages: + - libgmp-dev + +# The different configurations we want to test. You could also do things like +# change flags or use --stack-yaml to point to a different file. +env: +- ARGS="" +#- ARGS="--resolver lts-2" +- ARGS="--resolver lts" +- ARGS="--resolver nightly" + +before_install: +# Download and unpack the stack executable +- mkdir -p ~/.local/bin +- export PATH=$HOME/.local/bin:$PATH +- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' + +# This line does all of the work: installs GHC if necessary, builds the +# library, executables, and test suites, and runs the test suites. +# `--no-terminal works` around some quirks in Travis's terminal implementation. +script: stack $ARGS --no-terminal --install-ghc test + +# Caching so the next build will be fast too. +cache: + directories: + - $HOME/.stack diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9bba350 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +Change log +========== + +lish uses [Semantic Versioning][1]. +The change log is available [on GitHub][2]. + +[1]: http://semver.org/spec/v2.0.0.html +[2]: https://github.com/yogsototh/lish/releases + +## v0.1.0.0 + +* Initially created. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..becd8f8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2017, Yann Esposito + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2c7bb10 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +lish +========== + +New Haskell project using stack template `tasty-travis`. + +Please read file `tutorial.md` for first steps in using the template. diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/lish.cabal b/lish.cabal new file mode 100644 index 0000000..eb463df --- /dev/null +++ b/lish.cabal @@ -0,0 +1,79 @@ +name: lish +version: 0.1.0.0 +-- synopsis: +description: LISP Shell written in Haskell + +license: ISC +license-file: LICENSE +author: Yann Esposito +maintainer: yann.esposito@gmail.com +copyright: © 2017 Yann Esposito +homepage: https://github.com/yogsototh/lish +bug-reports: https://github.com/yogsototh/lish/issues + +category: Test +build-type: Simple +stability: alpha (experimental) +cabal-version: >=1.10 + +extra-source-files: + README.md + stack.yaml + +source-repository head + type: git + location: https://github.com/yogsototh/lish + +library + default-language: Haskell2010 + ghc-options: -Wall -Werror -O2 + hs-source-dirs: src + exposed-modules: Lib + , Lish.Core + build-depends: base >= 4.8 && < 5 + , haskeline + , parsec >= 3 && < 4 + , protolude + , process + +executable lish-exe + default-language: Haskell2010 + ghc-options: -Wall -Werror -O2 -threaded -rtsopts -with-rtsopts=-N + hs-source-dirs: src-exe + main-is: Main.hs + build-depends: base >= 4.8 && < 5 + , lish + +test-suite lish-test + type: exitcode-stdio-1.0 + default-language: Haskell2010 + ghc-options: -Wall -Werror -O2 -threaded -rtsopts -with-rtsopts=-N + hs-source-dirs: src-test + main-is: Main.hs + build-depends: base >= 4.8 && < 5 + , tasty >= 0.11 + , tasty-hunit >= 0.9 + , tasty-smallcheck >= 0.8 + , lish + +test-suite lish-doctest + type: exitcode-stdio-1.0 + default-language: Haskell2010 + ghc-options: -Wall -Werror -O2 -threaded -rtsopts -with-rtsopts=-N + hs-source-dirs: src-doctest + main-is: Main.hs + build-depends: base >= 4.8 && < 5 + , doctest >=0.10 + , Glob >= 0.7 + , QuickCheck >= 2.5 + , lish + +benchmark lish-benchmark + type: exitcode-stdio-1.0 + default-language: Haskell2010 + ghc-options: -Wall -Werror -O2 -threaded -rtsopts -with-rtsopts=-N + hs-source-dirs: src-benchmark + main-is: Main.hs + build-depends: base >= 4.8 && < 5 + , criterion >= 1.1 + , lish diff --git a/src-benchmark/Main.hs b/src-benchmark/Main.hs new file mode 100644 index 0000000..e69835d --- /dev/null +++ b/src-benchmark/Main.hs @@ -0,0 +1,7 @@ +import Criterion +import Criterion.Main + +import Lib (inc) + +main :: IO () +main = defaultMain [bench "inc 41" (whnf inc (41 :: Int))] diff --git a/src-doctest/Main.hs b/src-doctest/Main.hs new file mode 100644 index 0000000..4e85e16 --- /dev/null +++ b/src-doctest/Main.hs @@ -0,0 +1,5 @@ +import System.FilePath.Glob +import Test.DocTest + +main :: IO () +main = glob "src/**/*.hs" >>= doctest diff --git a/src-exe/Main.hs b/src-exe/Main.hs new file mode 100644 index 0000000..63b9ffd --- /dev/null +++ b/src-exe/Main.hs @@ -0,0 +1,4 @@ +import Lish.Core (runLish) + +main :: IO () +main = runLish diff --git a/src-test/Main.hs b/src-test/Main.hs new file mode 100644 index 0000000..aef50a4 --- /dev/null +++ b/src-test/Main.hs @@ -0,0 +1,38 @@ +import Test.Tasty +import Test.Tasty.HUnit +import Test.Tasty.SmallCheck + +import Lib (inc) + +main :: IO () +main = defaultMain $ testGroup "all-tests" tests + +tests :: [TestTree] +tests = + [ testGroup "SmallCheck" scTests + , testGroup "Unit tests" huTests + ] + +scTests :: [TestTree] +scTests = + [ testProperty "inc == succ" prop_succ + , testProperty "inc . negate == negate . pred" prop_pred + ] + +huTests :: [TestTree] +huTests = + [ testCase "Increment below TheAnswer" case_inc_below + , testCase "Decrement above TheAnswer" case_dec_above + ] + +prop_succ :: Int -> Bool +prop_succ n = inc n == succ n + +prop_pred :: Int -> Bool +prop_pred n = inc (negate n) == negate (pred n) + +case_inc_below :: Assertion +case_inc_below = inc 41 @?= (42 :: Int) + +case_dec_above :: Assertion +case_dec_above = negate (inc (negate 43)) @?= (42 :: Int) diff --git a/src/Lib.hs b/src/Lib.hs new file mode 100644 index 0000000..91fdc67 --- /dev/null +++ b/src/Lib.hs @@ -0,0 +1,24 @@ +-- | Example of a library file. It is also used for testing the test suites. +module Lib + ( + -- * Exported functions + inc + ) where + +-- | Increment one 'Num' value. +-- +-- >>> let answer = 42 :: Int +-- >>> let prev = answer - 1 +-- >>> inc prev +-- 42 +-- >>> succ . Prelude.last . Prelude.take prev . iterate inc $ 1 +-- 42 +-- +-- Properties: +-- +-- prop> succ x == inc x +-- prop> inc (negate x) == negate (pred x) +-- +inc :: Num a => a -- ^ value to increment + -> a -- ^ result +inc x = x + 1 diff --git a/src/Lish/Core.hs b/src/Lish/Core.hs new file mode 100644 index 0000000..4843e69 --- /dev/null +++ b/src/Lish/Core.hs @@ -0,0 +1,66 @@ +{-# LANGUAGE OverloadedStrings #-} +-- | Lish core +module Lish.Core + ( + runLish + ) where + +import Control.Monad.IO.Class +import Data.List (intercalate) +import GHC.IO.Handle (hGetContents) +import System.Console.Haskeline +import System.Process +import Text.Parsec + +-- | Start an interactive lish shell +runLish :: IO () +runLish = runInputT defaultSettings mainLoop + +mainLoop :: InputT IO () +mainLoop = do + maybeLine <- getInputLine ":€ > " + case maybeLine of + -- EOF / control-d + Nothing -> outputStrLn "bye bye!" + Just "exit" -> outputStrLn "bye bye!" + Just "logout" -> outputStrLn "bye bye!" + Just line -> do + eval (parseCmd line) + mainLoop + +data Cmd = Cmd String [String] deriving (Eq, Show) + +type Command = [String] -> IO () + +internalCommands :: [(String,Command)] +internalCommands = [("pr",\args -> putStrLn (intercalate " " args))] + +-- PARSE +parseCmd :: String -> Either ParseError Cmd +parseCmd = parse sExprParser "S-Expr" + +identifier :: Parsec String () String +identifier = many1 (noneOf " \t") + +sExprParser :: Parsec String () Cmd +sExprParser = do + (cmdname:args) <- many1 (identifier <* spaces) + return $ Cmd cmdname args + +-- EVAL +internalFunction :: String -> Maybe Command +internalFunction cmdname = lookup cmdname internalCommands + +execute :: String -> [String] -> IO () +execute cmd args = do + res <- createProcess (proc cmd args) { std_out = CreatePipe } + case res of + (_, Just hout, _, _) -> hGetContents hout >>= mapM_ putStrLn . (map ("o-o " ++)) . lines + _ -> putStrLn "no output" + +eval :: Either ParseError Cmd -> InputT IO () +eval parsed = case parsed of + Right (Cmd cmdname args) -> case internalFunction cmdname of + Just f -> liftIO (f args) + Nothing -> liftIO (execute cmdname args) + Left err -> outputStrLn (show err) diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..8c81be8 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,67 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# http://docs.haskellstack.org/en/stable/yaml_configuration/ + +# Resolver to choose a 'specific' stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# resolver: lts-3.5 +# resolver: nightly-2015-09-21 +# resolver: ghc-7.10.2 +# resolver: ghcjs-0.1.0_ghc-7.10.2 +# resolver: +# name: custom-snapshot +# location: "./custom-snapshot.yaml" +resolver: lts-8.0 + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# - location: +# git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# extra-dep: true +# subdirs: +# - auto-update +# - wai +# +# A package marked 'extra-dep: true' will only be built if demanded by a +# non-dependency (i.e. a user package), and its test suites and benchmarks +# will not be run. This is useful for tweaking upstream packages. +packages: +- '.' +# Dependency packages to be pulled from upstream that are not in the resolver +# (e.g., acme-missiles-0.3) +extra-deps: +- haskeline-0.7.3.1 + +# Override default flag values for local packages and extra-deps +flags: {} + +# Extra package databases containing global packages +extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=1.3" +# +# Override the architecture used by stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor