From 4987ea755be63a3a49972bafdf4486aeaa174548 Mon Sep 17 00:00:00 2001 From: jecaro Date: Thu, 19 Oct 2023 15:45:29 +0200 Subject: [PATCH] restructure the project --- {eval-expr => app/eval-expr}/Main.hs | 4 +- {minihasklisp => app/minihasklisp}/Main.hs | 18 +++-- minihasklisp.cabal | 80 ++++++++++++++----- src/EvalExpr/JSONParser.hs | 25 ------ src/EvalExpr/UrlParser.hs | 37 --------- src/{EvalExpr => eval-expr}/Expression.hs | 19 +++-- src/{MiniHaskLisp => minihasklisp}/Eval.hs | 12 ++- .../ParseAndEval.hs | 10 +-- src/{MiniHaskLisp => minihasklisp}/SExpr.hs | 6 +- src/{ => parser}/Parser.hs | 23 ++++-- test/{ => eval-expr}/ExpressionSpec.hs | 12 ++- test/{ => eval-expr}/Spec.hs | 0 test/{ => minihasklisp}/SExprSpec.hs | 18 ++--- test/minihasklisp/Spec.hs | 1 + test/minihasklisp/{ => files}/bootstrap.scm | 0 test/minihasklisp/{ => files}/fact.scm | 0 test/minihasklisp/{ => files}/fib.scm | 0 test/minihasklisp/{ => files}/qsort3.scm | 0 test/minihasklisp/{ => files}/sort.scm | 0 test/{ => parser}/ParserSpec.hs | 20 +++-- test/parser/Spec.hs | 1 + 21 files changed, 151 insertions(+), 135 deletions(-) rename {eval-expr => app/eval-expr}/Main.hs (78%) rename {minihasklisp => app/minihasklisp}/Main.hs (87%) delete mode 100644 src/EvalExpr/JSONParser.hs delete mode 100644 src/EvalExpr/UrlParser.hs rename src/{EvalExpr => eval-expr}/Expression.hs (80%) rename src/{MiniHaskLisp => minihasklisp}/Eval.hs (97%) rename src/{MiniHaskLisp => minihasklisp}/ParseAndEval.hs (81%) rename src/{MiniHaskLisp => minihasklisp}/SExpr.hs (89%) rename src/{ => parser}/Parser.hs (90%) rename test/{ => eval-expr}/ExpressionSpec.hs (86%) rename test/{ => eval-expr}/Spec.hs (100%) rename test/{ => minihasklisp}/SExprSpec.hs (95%) create mode 100644 test/minihasklisp/Spec.hs rename test/minihasklisp/{ => files}/bootstrap.scm (100%) rename test/minihasklisp/{ => files}/fact.scm (100%) rename test/minihasklisp/{ => files}/fib.scm (100%) rename test/minihasklisp/{ => files}/qsort3.scm (100%) rename test/minihasklisp/{ => files}/sort.scm (100%) rename test/{ => parser}/ParserSpec.hs (90%) create mode 100644 test/parser/Spec.hs diff --git a/eval-expr/Main.hs b/app/eval-expr/Main.hs similarity index 78% rename from eval-expr/Main.hs rename to app/eval-expr/Main.hs index bb5a3b2..75c57bb 100644 --- a/eval-expr/Main.hs +++ b/app/eval-expr/Main.hs @@ -1,5 +1,5 @@ -import EvalExpr.Expression -import Parser +import Expression (eval, parseExpression) +import Parser (Parser (..)) main :: IO () main = interact (unlines . fmap interpret . lines) diff --git a/minihasklisp/Main.hs b/app/minihasklisp/Main.hs similarity index 87% rename from minihasklisp/Main.hs rename to app/minihasklisp/Main.hs index a43a891..18a2475 100644 --- a/minihasklisp/Main.hs +++ b/app/minihasklisp/Main.hs @@ -1,10 +1,16 @@ import Control.Monad.IO.Class (liftIO) -import Data.Either -import Data.Maybe -import MiniHaskLisp.Eval -import MiniHaskLisp.ParseAndEval -import System.Console.Haskeline -import System.Environment +import Data.Either (fromRight) +import Data.Maybe (isNothing) +import Eval (Env) +import ParseAndEval (Result, parseAndEval, renderResult) +import System.Console.Haskeline ( + InputT, + defaultSettings, + getInputLine, + outputStrLn, + runInputT, + ) +import System.Environment (getArgs, getProgName) data Options = Options { opFile :: Maybe String diff --git a/minihasklisp.cabal b/minihasklisp.cabal index 17d360c..b59fce0 100644 --- a/minihasklisp.cabal +++ b/minihasklisp.cabal @@ -9,6 +9,7 @@ common defaults default-extensions: OverloadedStrings ScopedTypeVariables + TupleSections ghc-options: -Wall -Wcompat @@ -19,42 +20,77 @@ common defaults -Wredundant-constraints build-depends: base -library +-- Parser library + +library parser-lib import: defaults - exposed-modules: - EvalExpr.Expression - EvalExpr.JSONParser - EvalExpr.UrlParser - MiniHaskLisp.Eval - MiniHaskLisp.ParseAndEval - MiniHaskLisp.SExpr - Parser - hs-source-dirs: src + exposed-modules: Parser + hs-source-dirs: src/parser + +test-suite parser-spec + import: defaults + type: exitcode-stdio-1.0 + main-is: Spec.hs + other-modules: ParserSpec + hs-source-dirs: test/parser + build-depends: + hspec, + parser-lib + +-- eval-expr project + +library eval-expr-lib + import: defaults + exposed-modules: Expression + hs-source-dirs: src/eval-expr + build-depends: parser-lib executable eval-expr import: defaults main-is: Main.hs - hs-source-dirs: eval-expr - build-depends: minihasklisp + hs-source-dirs: app/eval-expr + build-depends: + eval-expr-lib, + parser-lib + +test-suite eval-expr-spec + import: defaults + type: exitcode-stdio-1.0 + main-is: Spec.hs + other-modules: ExpressionSpec + hs-source-dirs: test/eval-expr + build-depends: + hspec, + eval-expr-lib, + parser-lib + +-- minihasklisp project + +library minihasklisp-lib + import: defaults + exposed-modules: + Eval + ParseAndEval + SExpr + hs-source-dirs: src/minihasklisp + build-depends: parser-lib executable minihasklisp import: defaults main-is: Main.hs - hs-source-dirs: minihasklisp + hs-source-dirs: app/minihasklisp build-depends: haskeline, - minihasklisp + minihasklisp-lib -test-suite spec +test-suite minihasklisp-spec import: defaults type: exitcode-stdio-1.0 main-is: Spec.hs - other-modules: - ExpressionSpec - ParserSpec - SExprSpec - hs-source-dirs: - test + other-modules: SExprSpec + hs-source-dirs: test/minihasklisp build-depends: hspec, - minihasklisp + minihasklisp-lib, + parser-lib + diff --git a/src/EvalExpr/JSONParser.hs b/src/EvalExpr/JSONParser.hs deleted file mode 100644 index 3eed556..0000000 --- a/src/EvalExpr/JSONParser.hs +++ /dev/null @@ -1,25 +0,0 @@ -module EvalExpr.JSONParser where - -import Control.Applicative -import Parser - -data JList = MkNum Int | MkList [JList] deriving (Show) - -parseJList :: Parser JList -parseJList = parseMkNum <|> parseList - where - parseMkNum = MkNum <$> parseInt - parseList = - MkList - <$> ( parseOpen *> parseSpace - *> many - ( parseJList <* parseSpace - <* optional (parseComa <* parseSpace) - ) - <* parseSpace - <* parseClose - ) - parseOpen = parseChar '[' - parseClose = parseChar ']' - parseComa = parseChar ',' - parseSpace = many (parseChar ' ') diff --git a/src/EvalExpr/UrlParser.hs b/src/EvalExpr/UrlParser.hs deleted file mode 100644 index 6797a5e..0000000 --- a/src/EvalExpr/UrlParser.hs +++ /dev/null @@ -1,37 +0,0 @@ -module EvalExpr.UrlParser where - -import Control.Applicative -import Parser - -data Protocol = Http | Https - deriving (Show) -type Domain = String -type Path = [String] - -data Url = Url Protocol Domain Path - deriving (Show) - -parseProtocol :: Parser Protocol -parseProtocol = parseHttps <|> parseHttp - where - parseHttps = Https <$ parseString "https" - parseHttp = Http <$ parseString "http" - -parseSlash :: Parser Char -parseSlash = parseChar '/' - -parseColon :: Parser Char -parseColon = parseChar ':' - -parseAlpha :: Parser String -parseAlpha = some (parseAnyChar $ '.' : ['a' .. 'z']) - -parseUrl :: Parser Url -parseUrl = - Url <$> parseProtocol - <* parseColon - <* parseSlash - <* parseSlash - <*> parseAlpha - <* parseSlash - <*> many (parseAlpha <* optional parseSlash) diff --git a/src/EvalExpr/Expression.hs b/src/eval-expr/Expression.hs similarity index 80% rename from src/EvalExpr/Expression.hs rename to src/eval-expr/Expression.hs index 2cc6284..eb8ae30 100644 --- a/src/EvalExpr/Expression.hs +++ b/src/eval-expr/Expression.hs @@ -1,7 +1,13 @@ -module EvalExpr.Expression where +module Expression ( + Expression (..), + Operator (..), + parseExpression, + parseOperator, + eval, +) where import Control.Applicative ((<|>)) -import Parser +import Parser (Parser (..), parseChar, parseDouble, parseWhitespaces) data Operator = Plus | Minus | Product | Divide | Power deriving (Eq, Show) @@ -16,16 +22,17 @@ parseExpression = withParenOrNot (parseBinary <|> parseNum) <* parseWhitespaces parseBinary = ( binaryWithPriority <$> parseNum - <*> parseOperator' - <*> parseExpression + <*> parseOperator' + <*> parseExpression ) - <|> ( Binary <$> (parseOpen' *> parseExpression <* parseClose') + <|> ( Binary + <$> (parseOpen' *> parseExpression <* parseClose') <*> parseOperator' <*> parseExpression ) binaryWithPriority l op r | (Binary l' op' r') <- r - , priority op' < priority op = + , priority op' < priority op = Binary (Binary l op l') op' r' | otherwise = Binary l op r parseOperator' = parseOperator <* parseWhitespaces diff --git a/src/MiniHaskLisp/Eval.hs b/src/minihasklisp/Eval.hs similarity index 97% rename from src/MiniHaskLisp/Eval.hs rename to src/minihasklisp/Eval.hs index c3007ee..497944a 100644 --- a/src/MiniHaskLisp/Eval.hs +++ b/src/minihasklisp/Eval.hs @@ -1,11 +1,9 @@ -{-# LANGUAGE TupleSections #-} +module Eval (Error (..), Env, eval, renderError) where -module MiniHaskLisp.Eval where - -import Control.Monad -import Data.Foldable -import MiniHaskLisp.SExpr -import Parser +import Control.Monad (liftM2, (<=<)) +import Data.Foldable (foldl') +import Parser (Parser (..), parseInt) +import SExpr (SExpr (..), toPairs) type Env = [(String, SExpr)] diff --git a/src/MiniHaskLisp/ParseAndEval.hs b/src/minihasklisp/ParseAndEval.hs similarity index 81% rename from src/MiniHaskLisp/ParseAndEval.hs rename to src/minihasklisp/ParseAndEval.hs index 702d4d7..9afc966 100644 --- a/src/MiniHaskLisp/ParseAndEval.hs +++ b/src/minihasklisp/ParseAndEval.hs @@ -1,11 +1,11 @@ -module MiniHaskLisp.ParseAndEval where +module ParseAndEval (Error (..), Result, parseAndEval, renderResult) where import Data.Bifunctor (second) -import MiniHaskLisp.Eval hiding (Error) -import MiniHaskLisp.SExpr -import Parser +import Eval (Env, eval, renderError) +import Parser (Parser (..)) +import SExpr (SExpr (..), parseSExpr, render, toPairs) -import qualified MiniHaskLisp.Eval as Eval +import qualified Eval data Error = ErParse String | ErEval Eval.Error deriving (Eq, Show) diff --git a/src/MiniHaskLisp/SExpr.hs b/src/minihasklisp/SExpr.hs similarity index 89% rename from src/MiniHaskLisp/SExpr.hs rename to src/minihasklisp/SExpr.hs index f63d13c..5dfb510 100644 --- a/src/MiniHaskLisp/SExpr.hs +++ b/src/minihasklisp/SExpr.hs @@ -1,7 +1,7 @@ -module MiniHaskLisp.SExpr where +module SExpr (SExpr (..), parseSExpr, render, toPairs) where -import Control.Applicative -import Parser +import Control.Applicative (some, (<|>)) +import Parser (Parser (..), parseChar, parsePred, parseString, parseWhitespaces) data SExpr = Atom String | SExpr [SExpr] deriving (Eq, Show) diff --git a/src/Parser.hs b/src/parser/Parser.hs similarity index 90% rename from src/Parser.hs rename to src/parser/Parser.hs index cc44339..add62b1 100644 --- a/src/Parser.hs +++ b/src/parser/Parser.hs @@ -1,8 +1,21 @@ -module Parser where - -import Control.Applicative -import Control.Monad -import Data.Foldable (asum) +module Parser ( + Parser (..), + parseAnd, + parseAndWith, + parseAnyChar, + parseChar, + parseDouble, + parsePred, + parseString, + parseInt, + parseUInt, + parseTuple, + parseTuple', + parseWhitespaces, +) where + +import Control.Applicative (Alternative (..), asum, liftA2, optional) +import Control.Monad (void) import qualified Data.List as L import Data.Maybe (fromMaybe) import Text.Read (readMaybe) diff --git a/test/ExpressionSpec.hs b/test/eval-expr/ExpressionSpec.hs similarity index 86% rename from test/ExpressionSpec.hs rename to test/eval-expr/ExpressionSpec.hs index 3a47a40..9bc910b 100644 --- a/test/ExpressionSpec.hs +++ b/test/eval-expr/ExpressionSpec.hs @@ -1,9 +1,15 @@ module ExpressionSpec (spec) where -import Test.Hspec +import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy) -import EvalExpr.Expression -import Parser +import Expression ( + Expression (..), + Operator (..), + eval, + parseExpression, + parseOperator, + ) +import Parser (Parser (..)) spec :: Spec spec = do diff --git a/test/Spec.hs b/test/eval-expr/Spec.hs similarity index 100% rename from test/Spec.hs rename to test/eval-expr/Spec.hs diff --git a/test/SExprSpec.hs b/test/minihasklisp/SExprSpec.hs similarity index 95% rename from test/SExprSpec.hs rename to test/minihasklisp/SExprSpec.hs index 1fcb3ef..6fb17a2 100644 --- a/test/SExprSpec.hs +++ b/test/minihasklisp/SExprSpec.hs @@ -1,10 +1,10 @@ module SExprSpec (spec) where -import MiniHaskLisp.Eval (Error (NotBound)) -import MiniHaskLisp.ParseAndEval -import MiniHaskLisp.SExpr -import Parser -import Test.Hspec +import Eval (Error (NotBound)) +import ParseAndEval (Error (..), parseAndEval) +import Parser (Parser (..)) +import SExpr (SExpr (..), parseSExpr) +import Test.Hspec (Spec, describe, it, shouldBe, shouldReturn) spec :: Spec spec = do @@ -202,11 +202,11 @@ spec = do `shouldBe` Right (Atom "here", []) describe "Files" $ do it "fact" $ do - evalFile "test/minihasklisp/fact.scm" `shouldReturn` Right (Atom "3628800") + evalFile "test/minihasklisp/files/fact.scm" `shouldReturn` Right (Atom "3628800") it "fib" $ do - evalFile "test/minihasklisp/fib.scm" `shouldReturn` Right (Atom "55") + evalFile "test/minihasklisp/files/fib.scm" `shouldReturn` Right (Atom "55") it "sort" $ do - evalFile "test/minihasklisp/sort.scm" + evalFile "test/minihasklisp/files/sort.scm" `shouldReturn` Right ( SExpr [ Atom "1" @@ -255,7 +255,7 @@ spec = do ] ) it "qsort3" $ do - evalFile "test/minihasklisp/qsort3.scm" + evalFile "test/minihasklisp/files/qsort3.scm" `shouldReturn` Right ( SExpr [ Atom "1" diff --git a/test/minihasklisp/Spec.hs b/test/minihasklisp/Spec.hs new file mode 100644 index 0000000..a824f8c --- /dev/null +++ b/test/minihasklisp/Spec.hs @@ -0,0 +1 @@ +{-# OPTIONS_GHC -F -pgmF hspec-discover #-} diff --git a/test/minihasklisp/bootstrap.scm b/test/minihasklisp/files/bootstrap.scm similarity index 100% rename from test/minihasklisp/bootstrap.scm rename to test/minihasklisp/files/bootstrap.scm diff --git a/test/minihasklisp/fact.scm b/test/minihasklisp/files/fact.scm similarity index 100% rename from test/minihasklisp/fact.scm rename to test/minihasklisp/files/fact.scm diff --git a/test/minihasklisp/fib.scm b/test/minihasklisp/files/fib.scm similarity index 100% rename from test/minihasklisp/fib.scm rename to test/minihasklisp/files/fib.scm diff --git a/test/minihasklisp/qsort3.scm b/test/minihasklisp/files/qsort3.scm similarity index 100% rename from test/minihasklisp/qsort3.scm rename to test/minihasklisp/files/qsort3.scm diff --git a/test/minihasklisp/sort.scm b/test/minihasklisp/files/sort.scm similarity index 100% rename from test/minihasklisp/sort.scm rename to test/minihasklisp/files/sort.scm diff --git a/test/ParserSpec.hs b/test/parser/ParserSpec.hs similarity index 90% rename from test/ParserSpec.hs rename to test/parser/ParserSpec.hs index f7977b0..2c5fe9e 100644 --- a/test/ParserSpec.hs +++ b/test/parser/ParserSpec.hs @@ -1,10 +1,20 @@ -module ParserSpec (spec) -where +module ParserSpec (spec) where -import Test.Hspec +import Test.Hspec (Spec, describe, it, shouldBe) -import Control.Applicative -import Parser +import Control.Applicative (many, some, (<|>)) +import Parser ( + Parser (..), + parseAnd, + parseAndWith, + parseAnyChar, + parseChar, + parseDouble, + parseInt, + parseTuple, + parseTuple', + parseUInt, + ) spec :: Spec spec = do diff --git a/test/parser/Spec.hs b/test/parser/Spec.hs new file mode 100644 index 0000000..a824f8c --- /dev/null +++ b/test/parser/Spec.hs @@ -0,0 +1 @@ +{-# OPTIONS_GHC -F -pgmF hspec-discover #-}