
###############################################################################
#                                                                             #
#  Lout @HaskellSetup package for formatting Haskell programs                   #
#                                                                             #
#   Version 1.0                                                               #
#   Thorsten Seitz                                                            #
#   17 December 2001                                                          #
#                                                                             #
#  This package uses a filtered body parameter to convert program source      #
#  code into Lout source.  The filter program is prg2lout, which is           #
#  distributed with Lout and should be compiled and installed wherever        #
#  Lout itself is.                                                            #
#                                                                             #
###############################################################################

export @Haskell
def @HaskellSetup
    named pipe			{	}  # pipe through this first
    named numbered		{ No	}  # want lines numbered?
    named style
	named @OrIfPlain left x right y
	{ @BackEnd @Case { PlainText @Yield y else @Yield x } }
				{ symbol @OrIfPlain fixed }  # print style

    # the following options apply when style is "fixed"
    named fixedfont				{ Courier }# font family
    named fixedsize				{ -1.0p	}  # font size
    named fixedline				{ 1.0vx	}  # line-space
    named fixedtabin				{ 4	}  # tab interval
    named fixedtabout				{ 4s	}  # tab width

	named fixedbraces				{ Base  }  # braces face
    named fixedidentifiers			{ Base	}  # identifier face
    named fixedkeywords				{ Base	}  # keyword face
    named fixedoperators			{ Base	}  # operator face
    named fixednumbers				{ Base	}  # number face
    named fixedstrings				{ Base	}  # string face
    named fixedcomments				{ Base	}  # comment face
    named fixedlinenumbers			{ Base	}  # line numbers face

	named fixedleftbracesformat right @Body { @Body } # left braces format
	named fixedrightbracesformat right @Body { @Body } # right braces format
    named fixedidentifiersformat right @Body	{ @Body	}  # identifier format
    named fixedkeywordsformat right @Body	{ @Body	}  # keyword format
    named fixedoperatorsformat right @Body	{ @Body	}  # operators format
    named fixednumbersformat right @Body	{ @Body	}  # number format
    named fixedstringsformat right @Body	{ @Body	}  # string format
    named fixedcommentsformat right @Body	{ @Body	}  # comment format
    named fixedlinenumbersformat right @Body	{ @Body	}  # line nums format

    # the following options apply when style is "varying"
    named varyingfont				{	}  # font family
    named varyingsize				{ 1.0f	}  # font size
    named varyingline				{ 1.0vx	}  # line-space
    named varyingtabin				{ 4	}  # tab interval
    named varyingtabout				{ 1.5f	}  # tab width

	named varyingbraces				{ Base }   # braces face
    named varyingidentifiers		{ Slope	}  # identifier face
    named varyingkeywords			{ Bold	}  # keyword face
    named varyingoperators			{ Base	}  # operator face
    named varyingnumbers			{ Base	}  # number face
    named varyingstrings			{ Slope	}  # string face
    named varyingcomments			{ Base	}  # comment face
    named varyinglinenumbers			{ Base	}  # line numbers face

	named varyingleftbracesformat right @Body   { @Body }  # left braces format
	named varyingrightbracesformat right @Body   { @Body }  # right braces format
    named varyingidentifiersformat right @Body	{ @Body	}  # identifier format
    named varyingkeywordsformat right @Body	{ @Body	}  # keyword format
    named varyingoperatorsformat right @Body	{ @Body	}  # operators format
    named varyingnumbersformat right @Body	{ @Body	}  # number format
    named varyingstringsformat right @Body	{ @Body	}  # string format
    named varyingcommentsformat right @Body	{ @Body	}  # comment format
    named varyinglinenumbersformat right @Body	{ @Body	}  # line nums format

    # the following options apply when style is "symbol"
    named symbolfont				{	}  # font family
    named symbolsize				{ 1f	}  # font size
    named symbolline				{ 1.0vx	}  # line-space
    named symboltabin				{ 4	}  # tab interval
    named symboltabout				{ 1.7f	}  # tab width

	named symbolbraces  			{ Base  }  # braces face
    named symbolidentifiers			{ Slope	}  # identifier face
    named symbolkeywords			{ Bold	}  # keyword face
    named symboloperators			{ Symbol Base	}  # operator face
    named symbolnumbers				{ Base	}  # number face
    named symbolstrings				{ Slope	}  # string face
    named symbolcomments			{ Base	}  # comment face
    named symbollinenumbers			{ Base	}  # line numbers face

    named symbolidentifiersformat right @Body	{ 0.3s @Space {"" @Body} }  # identifier format (with italic correction)
    named symbolkeywordsformat right @Body	{ @Body	}  # keyword format
    named symboloperatorsformat right @Body	{ 0.5s @Space {"" @Body ""}}  # operators format
    named symbolnumbersformat right @Body	{ @Body	}  # number format
    named symbolstringsformat right @Body	{ @Body	}  # string format
    named symbolcommentsformat right @Body	{ @Body	}  # comment format
    named symbollinenumbersformat right @Body	{ @Body	}  # line nums format

@Begin

    export
    
	@PI @PK @PO @PN @PS @PC @PCL @PL @PA @PM @PD 
	@PLAMBDA @PCIRC @PPLUSPLUS @PCOLON @PDOUBLECOLON

	@A "$>"

    def @Haskell
	named style        { style         }  # style
	named numbered	   { numbered	   }  # want numbered lines?
	named pipe         { pipe          }  # pipe through this first
	named font         { dft           }  # font family
	named size         { dft           }  # font size
	named line         { dft           }  # line-space
	named tabin        { dft           }  # tab interval
	named tabout       { dft           }  # tab width
	named braces       { dft           }  # braces font
	named identifiers  { dft           }  # ident. font
	named keywords     { dft           }  # keyword font
	named operators    { dft           }  # operator font
	named numbers      { dft           }  # number font
	named strings      { dft           }  # string font
	named comments     { dft           }  # comment font
	named linenumbers  { dft           }  # line numbers font
	body @Body			      # filtered, see below
    @Begin

	def @Test	# returns x unless x is dft
	    left x
	    named iffixed {}
	    named ifvarying {}
	    named ifsymbol {}
	{
	    x @Case {
		dft @Yield {
		    style @Case {
			fixed   @Yield { iffixed   }
			varying @Yield { ifvarying }
			symbol  @Yield { ifsymbol  }
		    }
		}
		else @Yield x
	    }
	}


	def @Else	# returns x, or y if x is dft
	    left x
	    right y
	{
	    x @Case {
		dft  @Yield y
		else @Yield x
	    }
	}


	def @InitTab
	{
	  tabin @Test
	      iffixed   { fixedtabin   }
	      ifvarying { varyingtabin }
	      ifsymbol  { symboltabin  }
	}


	def @InitTabWidth
	{
	  tabout @Test
	      iffixed   { fixedtabout   }
	      ifvarying { varyingtabout }
	      ifsymbol  { symboltabout  }
	}


	def @Filter
	{
	    def wantnumbered
	    {
		numbered @Case {
		  { No no }	@Yield ""
		  { Yes yes }	@Yield "-L"
		  else          @Yield { "-L"numbered }
		}
	    }

	    pipe @Case {
		"" @Yield {
	    	    "prg2lout -r -lHaskell" wantnumbered -i{@FilterIn}
		    -o{@FilterOut} -e{@FilterErr}
		    -t{@InitTab} -T{@InitTabWidth}
		}
		else @Yield {
	    	    "cat" @FilterIn "|" pipe "|"
		    "prg2lout -r -lHaskell" wantnumbered -o{@FilterOut}
		    -e{@FilterErr} -t{@InitTab} -T{@InitTabWidth}
		}
	    }
	}


	def @InitFontFamily
	{
	  font @Test
	      iffixed   { fixedfont   }
	      ifvarying { varyingfont }
	      ifsymbol  { symbolfont  }
	}


	def @InitSize
	{
	  size @Test
	      iffixed   { fixedsize   }
	      ifvarying { varyingsize }
	      ifsymbol  { symbolsize  }
	}


	def @InitLine
	{
	  line @Test
	      iffixed   { fixedline   }
	      ifvarying { varyingline }
	      ifsymbol  { symbolline  }
	}


	def @PO		# for formatting operators
	    right x
	{
	    style @Case {
		fixed @Yield fixedoperatorsformat {
		    { operators @Else fixedoperators } @Font x
		}
		varying @Yield varyingoperatorsformat {
		    { operators @Else varyingoperators } @Font x
		}
		symbol @Yield symboloperatorsformat {
		    { operators @Else symboloperators } @Font x
		}
	    }
	}


	def @A		# get characters from the Adobe Symbol font
	    left sym
	    right x
	{
	    style @Case {
		symbol	@Yield { { Symbol Base } @Font @Char sym }
		else	@Yield { x			}
	    }
	}

	# deleted by JeffK here and in prg2lout.c, who could not see the point
	#def @APO
	#	left sym
	#	right x
	#{
	#	@PO sym @A x
	#}



	def @PI		# for formatting identifiers
	    right x
	{
	    style @Case {
		fixed @Yield fixedidentifiersformat {
		    { identifiers @Else fixedidentifiers } @Font x
		}
		varying @Yield varyingidentifiersformat {
		    { identifiers @Else varyingidentifiers } @Font x
		}
		symbol @Yield symbolidentifiersformat {
		    { identifiers @Else symbolidentifiers } @Font x
		}
	    }
	}


	def @PK		# for formatting keywords
	    right x
	{
	    style @Case {
		fixed @Yield fixedkeywordsformat {
		    { keywords @Else fixedkeywords } @Font x
		}
		varying @Yield varyingkeywordsformat {
		    { keywords @Else varyingkeywords } @Font x
		}
		symbol @Yield symbolkeywordsformat {
		    { keywords @Else symbolkeywords } @Font x
		}
	    }
	}


	def @PN		# for formatting numbers
	    right x
	{
	    style @Case {
		fixed @Yield fixednumbersformat {
		    { numbers @Else fixednumbers } @Font x
		}
		varying @Yield varyingnumbersformat {
		    { numbers @Else varyingnumbers } @Font x
		}
		symbol @Yield symbolnumbersformat {
		    { numbers @Else symbolnumbers } @Font x
		}
	    }
	}


	def @PS		# for formatting strings
	    right x
	{
	    style @Case {
		fixed @Yield fixedstringsformat {
		    { strings @Else fixedstrings } @Font x
		}
		varying @Yield varyingstringsformat {
		    { strings @Else varyingstrings } @Font x
		}
		symbol @Yield symbolstringsformat {
		    { strings @Else symbolstrings } @Font x
		}
	    }
	}


	def @PCnoDelim
		right x
	{
	    style @Case {
		fixed @Yield fixedcommentsformat {
		    { comments @Else fixedcomments } @Font x
		}
		varying @Yield varyingcommentsformat {
		    { comments @Else varyingcomments } @Font x
		}
		symbol @Yield symbolcommentsformat {
		    { comments @Else symbolcomments } @Font x
		}
	    }
	}


	def @Symb right x { { Symbol Base } @Font @Char x }


	def @PC		# for formatting comments
	    right x
	{
		@PCnoDelim { "{"@Symb minus{x}@Symb minus"}" }
	}


	def @PCL	# for formatting line comments
		right x
	{
		@PCnoDelim { {@Symb minus} &0.5s {@Symb minus}{x} }
	}
	

	def @PL		# for formatting line numbers
	    right x
	{
	    style @Case {
		fixed @Yield fixedlinenumbersformat {
		    { linenumbers @Else fixedlinenumbers } @Font x
		}
		varying @Yield varyinglinenumbersformat {
		    { linenumbers @Else varyinglinenumbers } @Font x
		}
		symbol @Yield symbollinenumbersformat {
		    { linenumbers @Else symbollinenumbers } @Font x
		}
	    }
	}


	def @PA		# for formatting asterisks
	{
	    @PO @BackEnd @Case {
		PlainText @Yield "*"
		else @Yield { @Symb asteriskmath }
	    }
	}


	def @PM		# for formatting minus signs
	{
	    @PO @BackEnd @Case {
		PlainText @Yield "-"
		else @Yield style @Case {
		    fixed   @Yield "-"
		    else    @Yield { { Symbol Base } @Font @Char "minus" }
		}
	    }
	}


	def @PD		# for formatting dots, if wanted larger
	{
	    @PO @BackEnd @Case {
		PlainText @Yield "."
		else @Yield { "1.4f" @Font "." &"0.05f" }
	    }
	}


	def @PLAMBDA
		right x
	{
	    style @Case {
		symbol	@Yield { { Symbol Base } @Font @Char lambda |0.5s }
		else	@Yield { x			}
	    }
	}

	def @PCIRC
		right x
	{
	    style @Case {
		symbol	@Yield { @PO {/0.3fo 0i @Space {"" @Symb degree } } }
		else	@Yield { @PO x			}
	    }
	}

	def @PPLUSPLUS
		right x
	{
	    style @Case {
		symbol	@Yield { @PO {@Symb plus |0.3fo @Symb plus} }
		else	@Yield { @PO x			}
	    }
	}

	def @PCOLON
	{
		@PO ":"	
	}

	def @PDOUBLECOLON
		right x
	{
	    style @Case {
		symbol	@Yield { @PO {: |0.8s :} }
		else	@Yield { @PO x			}
	    }
	}
		
	macro "$>" { {} & }


	{ @InitFontFamily Base @InitSize } @Font
	{ @InitLine lines nohyphen } @Break @Body

    @End @Haskell

@End @HaskellSetup
