madlang 2.0.0.1 → 2.0.1.0
raw patch · 15 files changed
+150/−145 lines, 15 filesdep +tibetan-utilsdep ~madlang
Dependencies added: tibetan-utils
Dependency ranges changed: madlang
Files
- README.md +23/−17
- bash/mkCompletions +4/−0
- madlang.cabal +9/−5
- src/Text/Madlibs.hs +0/−1
- src/Text/Madlibs/Ana/Parse.hs +19/−14
- src/Text/Madlibs/Ana/ParseUtils.hs +5/−4
- src/Text/Madlibs/Cata/SemErr.hs +34/−23
- src/Text/Madlibs/Exec/Main.hs +12/−9
- src/Text/Madlibs/Internal/Types.hs +4/−18
- src/Text/Madlibs/Internal/Utils.hs +1/−0
- stack.yaml +4/−1
- test/Spec.hs +33/−43
- test/templates/err/bad-sum.mad +0/−5
- test/templates/err/sem-err.mad +1/−1
- test/templates/fortune-teller.mad +1/−4
README.md view
@@ -1,17 +1,18 @@-## Madlibs DSL for generating random text+# Madlang DSL for generating random text+[](https://travis-ci.org/vmchale/madlibs) -This is the Madlibs DSL for generating random text. There is also a vim plugin for highlighting `.mad` files. +This is the Madlang DSL for generating random text. There is also a vim plugin, available [here](https://github.com/vmchale/madlang-vim). -It enables you to generate random, templated text with very little effort or expertise. +It enables you to generate random templated text with very little effort or expertise. -It can be used for twitter bots and more productive things.+It can be used for twitter bots and provides human-readable syntax for Markov+chains often used in natural language processing. -### Exmaples+## Exmaples -An exmaple is worth a thousand words (?), so suppose you wanted to generate a mediocre fortune telling bot. You could write the following code:+An exmaple is worth a thousand words, so suppose you wanted to generate a mediocre fortune telling bot. You could write the following code: ```- :define person 0.7 "A close friend will " 0.3 "You will "@@ -26,23 +27,28 @@ 0.2 goodfortune ``` -There are two "statements" in madlang, `:define` and `:return`. `:return` is the main string we'll be spitting back, so you're only allowed one of them per file. `:define` on the other hand can be used to make as many templates as you want. These templates are combinations of strings (enclosed in quotes) and names of other templates.+There are two "statements" in madlang, `:define` and `:return`. `:return` is the main string we'll be spitting back, so there can be only one per file. `:define` on the other hand can be used to make multiple templates. These templates are combinations of strings (enclosed in quotes) and names of other templates. -Of course, you can't have a circular reference with names - if `goodfortune` depends on `fortune` while `fortune` depends on `goodfortune`, you'll end up with either no fortune or an infinite fortune. So instead we just throw an error. +Of course, you can't have a circular reference with names - if `goodfortune` depends on `fortune` while `fortune` depends on `goodfortune`, we end up with either no fortune or an infinite fortune. So we throw an error. -### Using the libary+## Using the libary The main function you'll want to use is probably `runFile`; it reads a file and generates randomized text: ```- λ> runFile "test/templates/gambling.mad"+ λ:> runFile [] "test/templates/gambling.mad" "heads" ``` -Haddock documentation of all available functionality is located [here](https://hackage.haskell.org/package/madlang-0.1.0.0#readme). +Haddock documentation of all available functionality is located [here](https://hackage.haskell.org/package/madlang#readme). ## Installation +### Releases++If you're on windows or linux, grabbing release binaries is probably the+easiest. Find them [here](https://github.com/vmchale/madlibs/releases).+ ### Stack Download `stack` with@@ -51,18 +57,18 @@ curl -sSL http://haskellstack.org | sh ``` -Then run `stack install` and you'll get the `madlang` executable installed on your path. You can even do `stack install madlang` if you'd like. +Then run `stack install madlang` and you'll get the `madlang` executable installed on your path. ### Use -To use it, just try+To use it, try ```- $ madlang --input fortune-teller.mad+ $ madlang run fortune-teller.mad ``` You can do `madlang --help` if you want a couple other options for debugging. -### Syntax Highlighting+## Syntax Highlighting -Syntax highlighting for the DSL is provided in the vim plugin [here](http://github.com/vmchale/madlang-vim). You'll have to do `:set syntax=madlang` the first time you run it but everything else should work out of the box.:+Syntax highlighting for the DSL is provided in the vim plugin [here](http://github.com/vmchale/madlang-vim). It includes integration with [syntastic](https://github.com/vim-syntastic/syntastic).
+ bash/mkCompletions view
@@ -0,0 +1,4 @@+#!/bin/bash+madlang --bash-completion-script `which madlang` > tmp+sudo cp tmp /etc/bash_completion.d/madlang+rm tmp
madlang.cabal view
@@ -1,5 +1,5 @@ name: madlang-version: 2.0.0.1+version: 2.0.1.0 cabal-version: >=1.10 build-type: Simple license: BSD3@@ -15,9 +15,12 @@ author: Vanessa McHale extra-source-files: README.md- test/templates/*.mad+ test/templates/fortune-teller.mad+ test/templates/gambling.mad+ test/templates/var.mad test/templates/err/*.mad stack.yaml+ bash/mkCompletions source-repository head type: git@@ -40,7 +43,8 @@ lens >=4.15.1 && <4.16, mtl >=2.2.1 && <2.3, ansi-wl-pprint >=0.6.7.3 && <0.7,- containers >=0.5.7.1 && <0.6+ containers >=0.5.7.1 && <0.6,+ tibetan-utils >=0.1.1.2 && <0.2 default-language: Haskell2010 default-extensions: OverloadedStrings DeriveGeneric DeriveFunctor DeriveAnyClass@@ -63,7 +67,7 @@ main-is: Main.hs build-depends: base >=4.9.1.0 && <4.10,- madlang >=2.0.0.1 && <2.1+ madlang >=2.0.1.0 && <2.1 default-language: Haskell2010 hs-source-dirs: app @@ -72,7 +76,7 @@ main-is: Spec.hs build-depends: base >=4.9.1.0 && <4.10,- madlang >=2.0.0.1 && <2.1,+ madlang >=2.0.1.0 && <2.1, hspec >=2.4.2 && <2.5, megaparsec >=5.2.0 && <5.3, text >=1.2.2.1 && <1.3,
src/Text/Madlibs.hs view
@@ -1,4 +1,3 @@- -- | Main module exporting the relevant functions module Text.Madlibs ( -- * Parsers for `.mad` files
src/Text/Madlibs/Ana/Parse.hs view
@@ -13,6 +13,8 @@ import Data.Monoid import Control.Monad import Control.Monad.State+import Text.Megaparsec.Lexer.Tibetan+import Control.Exception hiding (try) -- | Parse a lexeme, aka deal with whitespace nicely. lexeme :: Parser a -> Parser a@@ -28,11 +30,11 @@ -- | Parse a number/probability float :: Parser Prob-float = lexeme L.float+float = lexeme L.float <|> (fromIntegral <$> integer) <?> "Float" -- | Parse an integer integer :: Parser Integer-integer = lexeme L.integer+integer = lexeme (L.integer <|> parseNumber) <?> "Integer" -- | Make sure definition blocks start un-indented nonIndented = L.nonIndented spaceConsumer@@ -42,11 +44,11 @@ -- | Parse between quotes quote :: Parser a -> Parser a-quote = between .$ (char '"') --also CAN'T have any \n AFTER+quote = between (char '"') (char '"') -- .$ (char '"') --also CAN'T have any \n AFTER -- | Parse a keyword keyword :: String -> Parser String-keyword str = (pure <$> char ':') <> (symbol str) <?> "keyword"+keyword str = (char ':') >> (symbol str) <?> "keyword" -- | Parse a var var :: Parser Int@@ -56,12 +58,12 @@ -- | Parse the `define` keyword. define :: Parser ()-define = (void $ nonIndented (keyword "define"))+define = void (nonIndented (keyword "define")) <?> "define block" -- | Parse the `:return` keyword. main :: Parser ()-main = (void $ nonIndented (keyword "return"))+main = void (nonIndented (keyword "return")) <?> "return block" -- | Parse a template name (what follows a `:define` or `return` block)@@ -76,7 +78,7 @@ pure . PreTok $ ins `access` (v-1) -- ins !! (v - 1) } <|> do {- s <- quote (many $ noneOf ("\"" :: String)) ;+ s <- quote (many $ noneOf ("\n\"" :: String)) ; spaceConsumer ; pure $ PreTok . T.pack $ s } @@ -87,7 +89,7 @@ pair ins = do indentGuard p <- float- str <- some $ (preStr ins)+ str <- some (preStr ins) pure (p, str) <?> "Probability/text pair" -- | Parse a `define` block@@ -107,17 +109,19 @@ -- | Parse the program in terms of `PreTok` and the `Key`s to link them. program :: [T.Text] -> Parser [(Key, [(Prob, [PreTok])])]-program ins = sortKeys . checkSemantics <$> do- p <- many (try (definition ins) <|> ((,) "Template" <$> final ins))- pure p--parseTreeM :: [T.Text] -> Parser (Context RandTok)-parseTreeM ins = buildTree <$> program ins+program ins = sortKeys <$> (checkSemantics =<< do+ p <- many (try (definition ins) <|> ((,) "Template" <$> final ins)) -- FIXME: parse multiple `returns`? why isn't indentation working @ all?+ lexeme eof+ pure p) -- | Parse text as a token + context (aka a reader monad with all the other functions) parseTokM :: [T.Text] -> Parser (Context RandTok) parseTokM ins = build <$> program ins +-- | Parse text as token + context+parseTreeM :: [T.Text] -> Parser (Context RandTok)+parseTreeM ins = buildTree <$> program ins+ -- | Parse text as a token -- -- > f <- readFile "template.mad"@@ -125,5 +129,6 @@ parseTok :: FilePath -> [T.Text] -> T.Text -> Either (ParseError Char Dec) RandTok parseTok filename ins f = snd . head . (filter (\(i,j) -> i == "Template")) . (flip execState []) <$> runParser (parseTokM ins) filename f +-- | Parse text as a token, suitable for printing as a tree.. parseTree :: FilePath -> [T.Text] -> T.Text -> Either (ParseError Char Dec) RandTok parseTree filename ins f = snd . head . (filter (\(i,j) -> i == "Template")) . (flip execState []) <$> runParser (parseTreeM ins) filename f
src/Text/Madlibs/Ana/ParseUtils.hs view
@@ -11,17 +11,18 @@ import Control.Exception import Control.Arrow ---consider moving Ana.ParseUtils to Cata.Sorting+--TODO consider moving Ana.ParseUtils to Cata.Sorting -- | Convert the stuff after the number to a `RandTok` concatTok :: T.Text -> Context [PreTok] -> Context RandTok concatTok param pretoks = do ctx <- get let unList (List a) = a- let toRand (Name str) = List . snd . (head' str param) . (filter ((== str) . fst)) . (map (second unList)) $ ctx+ let toRand (Name str) = List . snd . (head' str param) . (filter ((== str) . fst)) . (map (second unList)) $ ctx -- TODO move the shared functions to utils toRand (PreTok txt) = Value txt fold . (map toRand) <$> pretoks +-- | Build token in tree structure, without concatenating. buildTok :: T.Text -> Context [PreTok] -> Context RandTok buildTok param pretoks = do ctx <- get@@ -30,6 +31,8 @@ toRand (PreTok txt) = Value txt List . zip ([1..]) . (map toRand) <$> pretoks +-- | Build the token without concatenating, yielding a `RandTok` suitable to be+-- printed as a tree. buildTree :: [(Key, [(Prob, [PreTok])])] -> Context RandTok buildTree list@[(key,pairs)] = do toks <- mapM (\(i,j) -> buildTok key (pure j)) pairs@@ -40,8 +43,6 @@ y <- buildTree [x] ys <- pure <$> buildTree xs pure . List . zip ([1..]) $ (y:ys)---- basically just substitute? -- | Given keys naming the tokens, and lists of `PreTok`, build our `RandTok` build :: [(Key, [(Prob, [PreTok])])] -> Context RandTok
src/Text/Madlibs/Cata/SemErr.hs view
@@ -6,20 +6,41 @@ import Text.PrettyPrint.ANSI.Leijen import Control.Exception import qualified Data.Text as T+import Control.Monad+import qualified Data.Set as S+import Text.Megaparsec.Text+import Text.Megaparsec.Prim+import Text.Megaparsec.Error -- | Datatype for a semantic error-data SemanticError = OverloadedReturns | CircularFunctionCalls T.Text T.Text | ProbSum T.Text | InsufficientArgs Int Int+data SemanticError = OverloadedReturns | CircularFunctionCalls T.Text T.Text | InsufficientArgs Int Int deriving (Typeable) ---also consider overloading parseError tbqh -- | display a `SemanticError` nicely with coloration & whatnot instance Show SemanticError where show OverloadedReturns = show $ semErrStart <> text "File contains multiple declarations of :return" show (CircularFunctionCalls f1 f2) = show $ semErrStart <> text "Circular function declaration between:" <> indent 4 (yellow $ (text' f1) <> (text ", ") <> (text' f2)) show (InsufficientArgs i j) = show $ semErrStart <> text "Insufficent arguments from the command line, given " <> (text . show $ i) <> ", expected at least " <> (text . show $ j)- show (ProbSum f) = show $ semErrStart <> text "Function's options do not sum to 1:\n" <> indent 4 (yellow (text' f))- --we probably want to do our instance of `Show` for `ParseError` since that will let us color the position nicely @ least +-- | Derived via our show instance;+instance Exception SemanticError where++-- | Throw custom error given by string, within the parser+customError :: String -> Parser a+customError = failure S.empty S.empty . S.singleton . representFail++-- | Throw `OverloadedReturns` error within parser+overloadedReturns :: Parser a+overloadedReturns = customError . show $ OverloadedReturns++-- | Throws argument for circular function calls+circularFunctionCalls :: T.Text -> T.Text -> Parser a+circularFunctionCalls f1 f2 = customError . show $ CircularFunctionCalls f1 f2++-- | Throws error for insufficient arguments+insufficientArgs :: Int -> Int -> Parser a+insufficientArgs i j = customError . show $ InsufficientArgs i j+ -- | Constant to start `SemanticError`s semErrStart :: Doc semErrStart = dullred (text "\n Semantic Error: ")@@ -28,22 +49,10 @@ text' :: T.Text -> Doc text' = text . T.unpack --- | derived exception instance-instance Exception SemanticError- -- | big semantics checker that sequences stuff-checkSemantics :: [(Key, [(Prob, [PreTok])])] -> [(Key, [(Prob, [PreTok])])]-checkSemantics = foldr (.) id [ checkProb- , checkReturn ]---- checker to verify we have the right number of command-line args--- checkArgs :: [(Key, [(Prob, [PreTok])])] -> [(Key, [(Prob, [PreTok])])]---- | checker to verify probabilities sum to 1-checkProb :: [(Key, [(Prob, [PreTok])])] -> [(Key, [(Prob, [PreTok])])]-checkProb = map (\(i,j) -> if sumProb j then (i,j) else throw (ProbSum i))---potentially consider throwing mult. errors at once obvi-+checkSemantics :: [(Key, [(Prob, [PreTok])])] -> Parser [(Key, [(Prob, [PreTok])])]+checkSemantics = foldr (<=<) pure [ checkReturn+ ] -- | helper to filter out stuff that doesn't sumProb :: [(Prob, [PreTok])] -> Bool sumProb = ((==1) . sum . (map fst))@@ -54,16 +63,18 @@ head' _ _ (x:xs) = x head' f1 f2 _ = throw (CircularFunctionCalls f1 f2) +-- | Access argument, or throw error if the list is too short. access :: [a] -> Int -> a access xs i = if (i >= length xs) then throw (InsufficientArgs (length xs) (i+1)) else xs !! i -- | checker to verify there is at most one `:return` statement-checkReturn :: [(Key, [(Prob, [PreTok])])] -> [(Key, [(Prob, [PreTok])])]+checkReturn :: [(Key, [(Prob, [PreTok])])] -> Parser [(Key, [(Prob, [PreTok])])] checkReturn keys- | singleReturn keys = keys- | otherwise = throw OverloadedReturns+ | singleReturn keys = pure keys+ | otherwise = overloadedReturns -- | Checks that we have at most one `:return` template in the file singleReturn :: [(Key, [(Prob, [PreTok])])] -> Bool singleReturn = singleton . (filter ((=="Template") . fst))- where singleton = not . null+ where singleton [a] = True+ singleton _ = False
src/Text/Madlibs/Exec/Main.hs view
@@ -19,11 +19,12 @@ , input :: FilePath } +-- | datatype for the subcommands data Subcommand = Debug { version :: Bool } | Run { rep :: Maybe Int , clInputs :: [String] } | Lint { clInputs :: [String] }- -- Repeat { rep :: Maybe Int } +-- | Parser for command-line options for the program orders :: Parser Program orders = Program <$> (hsubparser@@ -34,6 +35,7 @@ (metavar "FILEPATH" <> help "File path to madlang template")) +-- | Parser for debug subcommand debug :: Parser Subcommand debug = Debug <$> switch@@ -41,6 +43,7 @@ <> short 'v' <> help "Show version information") +-- | Parser for the run subcommand temp :: Parser Subcommand temp = Run <$> (optional $ read <$> strOption@@ -53,6 +56,7 @@ <> metavar "VAR" <> help "command-line inputs to the template.")) +-- | Parser for the lint subcommand lint :: Parser Subcommand lint = Lint <$> (many $ strOption@@ -63,10 +67,8 @@ -- | Main program action runMadlang :: IO () runMadlang = execParser wrapper >>= template - --case rep . sub $ x of- -- (Just n) -> replicateM_ n $ template x- -- Nothing -> template x +-- | Wraps parser with help parser wrapper = info (helper <*> orders) (fullDesc <> progDesc "Madlang templating language"@@ -77,15 +79,15 @@ template rec = do let filepath = input $ rec let ins = map T.pack $ (clInputs . sub $ rec)- parsed <- parseFile ins filepath case sub rec of (Run reps _) -> do- replicateM_ (maybe 1 id reps) $ runFile ins filepath >>= TIO.putStrLn -- fix so it parses once!! either show run $ parsed + parsed <- parseFile ins filepath+ replicateM_ (maybe 1 id reps) $ runFile ins filepath >>= TIO.putStrLn (Debug _) -> do- putStrLn . (either show (drawTree . tokToTree 1.0)) =<< makeTree ins filepath -- parsed- --print parsed+ putStr . (either show (drawTree . tokToTree 1.0)) =<< makeTree ins filepath -- parsed (Lint _) -> do- putStrLn $ either show (const "No errors found.") parsed+ parsed <- parseFile ins filepath+ putStrLn $ either parseErrorPretty (const "No syntax errors found.") parsed -- | Generate randomized text from a template templateGen :: FilePath -> [T.Text] -> T.Text -> Either (ParseError Char Dec) (IO T.Text)@@ -104,6 +106,7 @@ let val = parseTok filepath ins txt pure val +-- | Parse a template into a RandTok suitable to be displayed as a tree makeTree :: [T.Text] -> FilePath -> IO (Either (ParseError Char Dec) RandTok) makeTree ins filepath = do txt <- readFile' filepath
src/Text/Madlibs/Internal/Types.hs view
@@ -27,28 +27,14 @@ data RandTok = List [(Prob, RandTok)] | Value T.Text deriving (Show, Eq) +-- | Function to transform a `RandTok` into a `Tree String` so that it can be pretty-printed. +--+-- > tokToTree 1.0 tok tokToTree :: Prob -> RandTok -> Tree String tokToTree p (Value a) = Node ((take 4 . show . min 1.0) p ++ " " ++ show a) [] tokToTree p (List [(_,Value a)]) = Node ((take 4 . show . min 1.0) p ++ " " ++ show a) []-tokToTree p (List xs) = Node (take 4 . show . min 1.0 $ p) (map (\(prob, val) -> tokToTree prob val) xs) -- (on (tokToTree .* fst -.* snd) (flip ($))) xs)---- | Neat 2-dimensional drawing of a parsed tree.-{---drawTree :: Tree String -> String-drawTree = unlines . draw---draw :: Tree String -> [String]-draw (Node x ts0) = lines x ++ drawSubTrees ts0- where- drawSubTrees [] = []- drawSubTrees [t] =- "|" : shift "`- " " " (draw t)- drawSubTrees (t:ts) =- "|" : shift "+- " "| " (draw t) ++ drawSubTrees ts+tokToTree p (List xs) = Node (take 4 . show . min 1.0 $ p) (map (uncurry tokToTree) xs) - shift first other = zipWith (++) (first : repeat other)---} -- | Make `RandTok` a monoid so we can append them together nicely (since they do generate text). -- -- > (Value "Hello") <> (List [(0.5," you"), (0.5, " me")])
src/Text/Madlibs/Internal/Utils.hs view
@@ -23,6 +23,7 @@ mempty = pure mempty mappend x y = mappend <$> x <*> y +-- | Normalize pre-tokens/corresponding probabilities normalize :: [(Prob, [PreTok])] -> [(Prob, [PreTok])] normalize list = map (over _1 (/total)) list where total = sum . map fst $ list
stack.yaml view
@@ -4,6 +4,8 @@ # For advanced use and comprehensive documentation of the format, please see: # http://docs.haskellstack.org/en/stable/yaml_configuration/ +# A warning or info to be displayed to the user on config load.+ # 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:@@ -39,7 +41,8 @@ - '.' # Dependency packages to be pulled from upstream that are not in the resolver # (e.g., acme-missiles-0.3)-extra-deps: []+extra-deps:+- tibetan-utils-0.1.1.2 # Override default flag values for local packages and extra-deps flags: {}
test/Spec.hs view
@@ -9,70 +9,60 @@ import Data.Function import Control.Exception import qualified Data.Text as T+import qualified Data.Text.IO as TIO import System.IO.Unsafe main :: IO () main = hspec $ do describe "parseTok" $ do parallel $ it "parses a .mad string" $ do- parseTok "" [] madFile `shouldParse` (List [(1.0,List [(0.5,Value "heads"),(0.5,Value "tails")])])+ file <- madFile+ parseTok "" [] file `shouldParse` (List [(1.0,List [(0.5,Value "heads"),(0.5,Value "tails")])])+ parallel $ it "parses tibetan numerals" $ do+ file <- madFileTibetan+ parseTok "" [] file `shouldParse` (List [(1.0,List [(0.5,Value "heads"),(0.5,Value "tails")])]) parallel $ it "fails when quotes aren't closed" $ do- parseTok "" [] `shouldFailOn` madFileFailure+ file <- madFileFailure+ parseTok "" [] `shouldFailOn` file parallel $ it "parses when functions are out of order" $ do- parseTok "" [] `shouldSucceedOn` madComplexFile+ file <- madComplexFile+ parseTok "" [] `shouldSucceedOn` file parallel $ it "returns a correct string from the template when evaluating a token" $ do- (testIO . run) exampleTok `shouldSatisfy` (\a -> on (||) (a ==) "heads" "tails")+ (run) exampleTok >>= (`shouldSatisfy` (\a -> on (||) (a ==) "heads" "tails")) parallel $ it "throws exception when two `:return`s are declared" $ do- (parseTok "" [] `shouldFailOn` semErrFile) `shouldThrow` semErr+ file <- semErrFile+ (parseTok "" [] `shouldFailOn` file) parallel $ it "substitutes a variable correctly" $ do- parseTok "" ["maxine"] `shouldSucceedOn` madVar+ file <- madVar+ parseTok "" ["maxine"] `shouldSucceedOn` file parallel $ it "fails when variables are not passed in" $ do- (parseTok "" [] `shouldFailOn` madVar) `shouldThrow` anyException+ file <- madVar+ (parseTok "" [] `shouldFailOn` file) `shouldThrow` anyException semErr :: Selector SemanticError semErr = const True +-- | Read a file in as a `Text`+readFile' :: FilePath -> IO T.Text+readFile' = (fmap T.pack) . readFile+ exampleTok :: RandTok exampleTok = List [(1.0,List [(0.5,Value "heads"),(0.5,Value "tails")])] -madFile :: T.Text-madFile = ":define something\n 0.5 \"heads\"\n 0.5 \"tails\"\n:return\n 1.0 something"+madFile :: IO T.Text+madFile = readFile' "test/templates/gambling.mad" -madFileFailure :: T.Text-madFileFailure = ":define something\-\ 0.5 \"heads\"\-\ 0.5 \"tails\-\:return\-\ 1.0 something"+madFileTibetan :: IO T.Text+madFileTibetan = readFile' "test/templates/ཤོ.mad" -madComplexFile :: T.Text-madComplexFile = ":define person\-\ 0.7 \"I will \"\-\ 0.3 \"You will \"\-\:define goodfortune\-\ 0.1 person \"make nice things happen today\"\-\ 0.9 \"nice things will happen today\"\-\:define fortune\-\ 0.5 \"drink a boatload of milk\"\-\ 0.5 \"get heckin angry\"\-\:return\-\ 0.8 person fortune\-\ 0.2 goodfortune"+madFileFailure :: IO T.Text+madFileFailure = readFile' "test/templates/err/bad.mad" -semErrFile :: T.Text-semErrFile = ":define something\-\ 0.5 \"heads\"\-\ 0.5 \"tails\"\-\:return\-\ 1.0 something\-\:return\-\ 0.5 something\-\ 0.5 \"parallel$ it doesn't matter b/c this is gonna blow up in our faces anyways\""+madComplexFile :: IO T.Text+madComplexFile = readFile' "test/templates/gambling.mad" -madVar :: T.Text-madVar = ":return\-\ 1.0 $1 \" is a good doggo.\""+semErrFile :: IO T.Text+semErrFile = readFile' "test/templates/err/sem-err.mad" --- | for the testing framework; to -testIO :: IO a -> a-testIO = unsafePerformIO+madVar :: IO T.Text+madVar = readFile' "test/templates/var.mad"
− test/templates/err/bad-sum.mad
@@ -1,5 +0,0 @@-:define something- 0.5 "heads"- 0.7 "tails"-:return- 1.0 something
test/templates/err/sem-err.mad view
@@ -1,6 +1,6 @@ :define something 0.5 "heads"- 0.5 "tails+ 0.5 "tails" :return 1.0 something :return
test/templates/fortune-teller.mad view
@@ -11,8 +11,5 @@ 0.8 person fortune 0.2 goodfortune {#-:define copies- :replicate person- (1) 0.3- (2) 0.7+block comment #}