Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project Reorganization #61

Merged
merged 3 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
HS_FILES = $(shell git ls-files '*.hs' '*.hs-boot')
CHANGED_HS_FILES = $(shell git diff --diff-filter=d --name-only `git merge-base HEAD origin/main` | grep '.*\(\.hs\|hs-boot\)$$')
NIX_FILES = $(shell git ls-files '*.nix' 'nix/*.nix')
SHELL_FILES = $(shell git ls-files '*.sh')
CHANGED_SHELL_FILES = $(shell git diff --diff-filter=d --name-only `git merge-base HEAD origin/main` | grep '.*\.sh$$')

NIX_FMT = nixpkgs-fmt
ORMOLU = ormolu
ORMOLU_VERSION = $(shell $(ORMOLU) --version | awk 'NR==1 { print $$2 }')

# Run Shellcheck with access to any file that's sourced, relative to the script's own directory
SHELLCHECK = shellcheck --external-sources --source-path=SCRIPTDIR

.PHONY: check-ormolu-version
check-ormolu-version:
@if ! [ "$(ORMOLU_VERSION)" = "$(ORMOLU_CHECK_VERSION)" ]; then \
echo "WARNING: ormolu version mismatch, expected $(ORMOLU_CHECK_VERSION) but got $(ORMOLU_VERSION)"; \
fi

.PHONY: format-hs
## format-hs: auto-format Haskell source code using ormolu
format-hs: check-ormolu-version
@echo running $(ORMOLU) --mode inplace
@$(ORMOLU) --mode inplace $(HS_FILES)

.PHONY: format-hs-changed
## format-hs-changed: auto-format Haskell source code using ormolu (changed files only)
format-hs-changed: check-ormolu-version
@echo running $(ORMOLU) --mode inplace
@if [ -n "$(CHANGED_HS_FILES)" ]; then \
$(ORMOLU) --mode inplace $(CHANGED_HS_FILES); \
fi

.PHONY: check-format-hs
## check-format-hs: check Haskell source code formatting using ormolu
check-format-hs: check-ormolu-version
@echo running $(ORMOLU) --mode check
@$(ORMOLU) --mode check $(HS_FILES)

.PHONY: check-format-hs-changed
## check-format-hs-changed: check Haskell source code formatting using ormolu (changed-files-only)
check-format-hs-changed: check-ormolu-version
@echo running $(ORMOLU) --mode check
@if [ -n "$(CHANGED_HS_FILES)" ]; then \
$(ORMOLU) --mode check $(CHANGED_HS_FILES); \
fi

.PHONY: format-nix
## format-nix: auto-format Nix source code using `nixpkgs-fmt`
format-nix:
@if command -v $(NIX_FMT) > /dev/null; then \
echo "running $(NIX_FMT)"; \
$(NIX_FMT) $(NIX_FILES); \
else \
echo "$(NIX_FMT) is not installed; skipping"; \
fi

.PHONY: check-format-nix
## check-format-nix: check Nix source code using `nixpkgs-fmt`
check-format-nix:
@if command -v $(NIX_FMT) > /dev/null; then \
echo "running $(NIX_FMT) --check"; \
$(NIX_FMT) --check $(NIX_FILES); \
else \
echo "$(NIX_FMT) is not installed; skipping"; \
fi

.PHONY: format
format: format-hs format-nix

.PHONY: format-changed
format-changed: format-hs-changed format-nix

.PHONY: check-format
check-format: check-format-hs check-format-nix

.PHONY: check-format-changed
check-format-changed: check-format-hs-changed check-format-nix

.PHONY: lint-shell
## lint-shell: lint shell scripts using `shellcheck`
lint-shell:
@echo running shellcheck
@$(SHELLCHECK) $(SHELL_FILES)

.PHONY: lint-shell-changed
## lint-shell-changed: lint shell scripts using `shellcheck` (changed files only)
lint-shell-changed:
@echo running shellcheck
@if [ -n "$(CHANGED_SHELL_FILES)" ]; then \
$(SHELLCHECK) $(CHANGED_SHELL_FILES); \
fi

.PHONY: build-all
## build-all: build all haskell packages, or "have i broken anything?"
build-all: $(GENERATED_CABAL_FILES)
cabal build all --enable-tests --enable-benchmarks

.PHONY: build-tests
## build-tests: build non-pro graphql executable tests
build-tests: $(GENERATED_CABAL_FILES)
cabal build chat-bots-contrib-test

.PHONY: clean
## build-tests: build non-pro graphql executable tests
clean: $(GENERATED_CABAL_FILES)
cabal clean

.PHONY: test
## test-no-backends
# the leftover tests with no particular backend, like Remote Schemas
test:
cabal run chat-bots-contrib-test
6 changes: 4 additions & 2 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
packages: *

packages: chat-bots
packages: chat-bots-contrib
packages: cofree-bot

source-repository-package
type: git
location: https://github.com/softwarefactory-project/matrix-client-haskell.git
Expand Down
62 changes: 17 additions & 45 deletions cofree-bot.cabal → chat-bots-contrib/chat-bots-contrib.cabal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cabal-version: 3.0
name: cofree-bot
name: chat-bots-contrib
version: 0.1.0.0
synopsis: A library for building bots compositionally.
synopsis: Bot behavior and Server modules for the chat-bots library.
bug-reports: https://github.com/cofree-coffee/cofree-bot
license: MIT
author: Solomon, Asad, and the Cofree-Coffee community
Expand Down Expand Up @@ -58,31 +58,6 @@ common common-libraries
, these
, typed-process

executable cofree-bot
import:
, common-libraries
, common-settings

main-is: Main.hs
hs-source-dirs: app
build-depends:
, aeson
, barbies
, cofree-bot
, directory
, filepath
, mtl
, optparse-applicative
, xdg-basedir
, yaml

other-modules:
, Options
, Options.Env
, Options.Config
, Options.Types
, Options.Parser

--------------------------------------------------------------------------------

library
Expand All @@ -92,27 +67,22 @@ library

hs-source-dirs: src
exposed-modules:
CofreeBot
CofreeBot.Bot
CofreeBot.Bot.Behaviors
CofreeBot.Bot.Behaviors.Calculator
CofreeBot.Bot.Behaviors.Calculator.Language
CofreeBot.Bot.Behaviors.CoinFlip
CofreeBot.Bot.Behaviors.GHCI
CofreeBot.Bot.Behaviors.Hello
CofreeBot.Bot.Behaviors.Jitsi
CofreeBot.Bot.Behaviors.Jitsi.Dictionary
CofreeBot.Bot.Behaviors.Magic8Ball
CofreeBot.Bot.Behaviors.Updog
CofreeBot.Bot.Context
CofreeBot.Utils
CofreeBot.Utils.ListT
Parsing
Data.Chat.Bot.Calculator
Data.Chat.Bot.Calculator.Language
Data.Chat.Bot.CoinFlip
Data.Chat.Bot.GHCI
Data.Chat.Bot.Hello
Data.Chat.Bot.Jitsi
Data.Chat.Bot.Jitsi.Dictionary
Data.Chat.Bot.Magic8Ball
Data.Chat.Bot.Updog
Data.Chat.Server.Matrix

build-depends:
, aeson
, attoparsec
, containers
, chat-bots
, data-fix
, directory
, hint
Expand All @@ -123,12 +93,13 @@ library
, pretty-simple
, process
, random
, transformers
, vector
, xdg-basedir

--------------------------------------------------------------------------------

test-suite cofree-bot-test
test-suite chat-bots-contrib-test
import:
, common-libraries
, common-settings
Expand All @@ -139,7 +110,8 @@ test-suite cofree-bot-test

build-depends:
, attoparsec
, cofree-bot
, chat-bots
, chat-bots-contrib
, data-fix
, hspec
, hspec-core
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
module CofreeBot.Bot.Behaviors.Calculator
module Data.Chat.Bot.Calculator
( calculatorBot,
simplifyCalculatorBot,
printCalcOutput,
module Language,
)
where

--------------------------------------------------------------------------------

import CofreeBot.Bot
import CofreeBot.Bot.Behaviors.Calculator.Language
import CofreeBot.Utils
import Control.Monad.Reader
import Control.Monad.State
import Data.Chat.Bot
import Data.Chat.Bot.Calculator.Language as Language
import Data.Chat.Bot.Monoidal
import Data.Chat.Utils
import Data.Profunctor
import Data.Text qualified as T
import Data.Text (Text)
import Data.Text qualified as Text

--------------------------------------------------------------------------------

Expand All @@ -22,7 +25,7 @@ calculatorBot = do
statement <- ask
state $ execCalculator statement

parseErrorBot :: Monad m => Bot m s ParseError T.Text
parseErrorBot :: Monad m => Bot m s ParseError Text
parseErrorBot = pureStatelessBot $ \ParseError {..} ->
"Failed to parse msg: \""
<> parseInput
Expand All @@ -33,12 +36,12 @@ parseErrorBot = pureStatelessBot $ \ParseError {..} ->
simplifyCalculatorBot ::
Monad m =>
Bot m s Statement (CalcError \/ CalcResp) ->
Bot m s T.Text T.Text
Bot m s Text Text
simplifyCalculatorBot bot =
dimap parseStatement indistinct $ parseErrorBot \/ rmap printCalcOutput bot

printCalcOutput :: Either CalcError CalcResp -> T.Text
printCalcOutput :: Either CalcError CalcResp -> Text
printCalcOutput = \case
Left err -> T.pack $ show err
Left err -> Text.pack $ show err
Right Ack -> "*variable saved*"
Right (Log e n) -> T.pack $ show e <> " = " <> show n
Right (Log e n) -> Text.pack $ show e <> " = " <> show n
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{-# LANGUAGE CPP #-}
{-# OPTIONS -fdefer-typed-holes -Wno-orphans #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}

module CofreeBot.Bot.Behaviors.Calculator.Language where
module Data.Chat.Bot.Calculator.Language where

import CofreeBot.Utils
import Control.Applicative
import Control.Monad.Error.Class
import Control.Monad.Except
Expand All @@ -16,19 +16,21 @@ import Data.Char
( isAlpha,
isDigit,
)
import Data.Chat.Utils
#if __GLASGOW_HASKELL__ >= 902
#else
import Data.Foldable
import Data.Foldable (asum)
#endif
import Data.Functor
import Data.List.NonEmpty qualified as NE
import Data.Map.Strict qualified as Map
import Data.Text qualified as T
import Data.Text (Text)
import Data.Text qualified as Text

--------------------------------------------------------------------------------
-- Utils

infixOp :: Parser a -> Parser b -> Parser T.Text -> Parser (a, b)
infixOp :: Parser a -> Parser b -> Parser Text -> Parser (a, b)
infixOp p1 p2 pop =
"("
|*| p1
Expand All @@ -42,7 +44,7 @@ infixOp p1 p2 pop =
--------------------------------------------------------------------------------
-- Parsing types

type VarName = T.Text
type VarName = Text

data Expr
= Var VarName
Expand All @@ -52,7 +54,7 @@ data Expr
| Neg Expr

data Statement
= Let T.Text Expr
= Let Text Expr
| StdOut Expr
deriving (Show)

Expand All @@ -63,7 +65,7 @@ type Program = NE.NonEmpty Statement

instance Show Expr where
showsPrec p = \case
Var x -> shows $ T.unpack x
Var x -> shows $ Text.unpack x
Val n -> shows n
x `Add` y ->
showParen (p >= 6) $ (showsPrec 6 x) . (" + " ++) . (showsPrec 6 y)
Expand All @@ -76,7 +78,7 @@ instance Show Expr where

varNameP :: Parser VarName
varNameP =
fmap (uncurry T.cons) $ letter |*| A.takeWhile (liftA2 (||) isAlpha isDigit)
fmap (uncurry Text.cons) $ letter |*| A.takeWhile (liftA2 (||) isAlpha isDigit)

exprP :: Parser Expr
exprP =
Expand Down Expand Up @@ -115,25 +117,25 @@ programP =
-- $> parseOnly programP "x := ((11 + 12) + 13)\nx + 1"

data ParseError = ParseError
{ parseInput :: T.Text,
parseError :: T.Text
{ parseInput :: Text,
parseError :: Text
}

parseStatement :: T.Text -> Either ParseError Statement
parseStatement txt = first (ParseError txt . T.pack) $ parseOnly statementP txt
parseStatement :: Text -> Either ParseError Statement
parseStatement txt = first (ParseError txt . Text.pack) $ parseOnly statementP txt

parseProgram :: T.Text -> Either ParseError Program
parseProgram txt = first (ParseError txt . T.pack) $ parseOnly programP txt
parseProgram :: Text -> Either ParseError Program
parseProgram txt = first (ParseError txt . Text.pack) $ parseOnly programP txt

--------------------------------------------------------------------------------
-- Evaluator

data CalcResp = Log Expr Int | Ack

data CalcError = LookupError T.Text
data CalcError = LookupError Text.Text
deriving (Show)

type CalcState = Map.Map T.Text Int
type CalcState = Map.Map Text.Text Int

-- | Evaluate an expression in our arithmetic language
eval :: Expr -> ExceptT CalcError (State CalcState) Int
Expand Down
Loading