-1

Hi so I have this main method which runs a parser,

main = do
  args <- getArgs
  let filename = head args
  contents <- readFile filename
  let c = parse parseProgram contents
  putStrLn "------------------------------------------------"
  putStrLn "THE PROGRAM WE HAVE PARSED"
  putStrLn "------------------------------------------------"
  putStrLn (show ((fst.head) c))
  return ()

when I run this program the first three calls to putStrLn are not printed to the terminal, it only shows the parsed program.

any help will be appreciated, how do I get all the calls to print?

Yusuf
  • 491
  • 2
  • 8
  • 1
    Is your command line buffered? – Rakete1111 Sep 09 '16 at 14:37
  • @Rakete1111 I am not sure, how do I figure out if it is, what does it mean for a command line to be buffered? – Yusuf Sep 09 '16 at 14:38
  • Well, some command lines flush the stream when they see a newline. Some don't (CMD). You'll have to flush the stream manually: http://stackoverflow.com/questions/12435794/putstrln-doesnt-print-to-console – Rakete1111 Sep 09 '16 at 14:40
  • Add this `hGetBuffering stdout >>= print` to your code and report back the what it prints. – redneb Sep 09 '16 at 14:44
  • it returns LineBuffering – Yusuf Sep 09 '16 at 14:48
  • 1
    Failing to flush the stream shouldn't discard unflushed output, though. – chepner Sep 09 '16 at 14:52
  • Comment out the `putStrLn (show ((fst.head) c))`. Does anything get printed? – Lynn Sep 09 '16 at 14:52
  • 3
    There's no way we can attempt to reproduce this, because we dno't know what `parse parseProgram` is. – chepner Sep 09 '16 at 14:55
  • @Lynn When I comment out the last putStrLn the first three do get printed – Yusuf Sep 09 '16 at 15:08
  • Are you sure the first three lines aren’t just scrolling off your screen? :) – Lynn Sep 09 '16 at 15:09
  • @chepner parseProgram returns a list of tuples of the form [(a, String)] where the first component of the tuple is the AST generated and the second component is the unconsumed input. I have created a bunch of show instances for the AST types to produce something more readable. – Yusuf Sep 09 '16 at 15:09
  • @Lynn I scrolled up to check, the weird thing is that it does not print those three lines but prior to those three lines I have calls to traceM in my parser and it prints the output of those and then it completely skips those 3 lines and prints out the AST – Yusuf Sep 09 '16 at 15:11
  • How strange. Try `hFlush stdout` after the three lines. Does that help? – Lynn Sep 09 '16 at 15:19
  • 1
    @Zubair Did you scroll all the way up to the prompt? Note that your trace messages wouldn't appear before the banner, but either directly before the parse result or intermingled with it. – sepp2k Sep 09 '16 at 15:21
  • What happens if you replace the last `putStrLn` with a hard-coded output like `putStrLn "parsed output"`? I'm wondering about the contents produce by parsing the file contents and ultimately the file content itself. – chepner Sep 09 '16 at 15:24
  • @Lynn adding hFlush stdout did not resolve the issue :( – Yusuf Sep 09 '16 at 15:28
  • @chepner When i replace it with hardcoded output, it does print, that is weird so is it do with the file, I extract the contents prior to any printing and run the contents through the parser first – Yusuf Sep 09 '16 at 15:28
  • And finally, what happens if you parse the contents *after* the first three `putStrLn`? – chepner Sep 09 '16 at 15:29
  • @chepner it prints everything, but the issue now is that it prints the three lines then runs through the parser printing all the trace messages and then it prints the AST – Yusuf Sep 09 '16 at 15:31
  • @sepp2k makes a very good point! Scroll up **past** the `traceM` lines. Things are not being printed in the order you think. – Lynn Sep 09 '16 at 15:33
  • The trace lines aren't being executed until you actually force `c` to be evaluated by calling `fst . head` on `c`. They are interfering with standard output somehow. – chepner Sep 09 '16 at 15:34
  • Ahh yes, you guys are right. With the original order of statements, the banner is being printed right at the top of the prompt before the traceM messages. I am guessing the parsing is actually only happening in the `(fst.head)` call when it is actually forced to return, so I am guessing having that `fst.head` call before the put statements should resolve my issues. – Yusuf Sep 09 '16 at 15:36
  • 2
    This is why a *reproducible* question is essential. The root problem was your definition of `parseProgram` (I assume that's where the traces appeared). – chepner Sep 09 '16 at 15:39
  • Actually no it doesn't, for some reason it's not actually parsing (evaluating) until I call show to get back the string rep of the AST – Yusuf Sep 09 '16 at 15:39
  • @Zubair If you need your messages to appear in a specific order, you should not use `trace` or `traceM` to print them. – sepp2k Sep 09 '16 at 15:40
  • @chepner ah yes, noted next time I will take that in to account before I post a question – Yusuf Sep 09 '16 at 15:40
  • @sepp2k the messages that are getting printed by trace & traceM are debugging messages which are created when parsing (i wish there was a way to turn trace of). Is there a way to get the messages to be printed in a specific order, I am trying to force the expression to evaluate but i cannot – Yusuf Sep 09 '16 at 15:43

1 Answers1

3

This doesn't appear possible. I created a more minimal example following as closely as possible to your code. I used Parsec because I am not sure what parsing library you are using.

Contents of parsec-trivial.hs:

#!/usr/bin/env stack
{- stack
    --resolver lts-6.15
    --install-ghc
    runghc
    --package parsec
-}

import System.Environment
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Char

ws = many space

nat :: Parser Integer
nat = read <$> many digit

parseProgram = ws *> nat <* ws <* eof

main = do
  args <- getArgs
  let filename = head args
  contents <- readFile filename
  let c = parse parseProgram filename contents
  putStrLn "------------------------------------------------"
  putStrLn "THE PROGRAM WE HAVE PARSED"
  putStrLn "------------------------------------------------"
  putStrLn $ show c

Contents of foo.b:

42

Executing this program goes like this:

$ ./parsec-trivial.hs foo.b
------------------------------------------------
THE PROGRAM WE HAVE PARSED
------------------------------------------------
Right 42
Steven Shaw
  • 6,063
  • 3
  • 33
  • 44