{ nicely format an algebraic expression
 usage: fmt$<expression>
 eg. fmt$(x\D(x^(x^-1)))
}


fmt=
  ( SP,up,low,max,convert-log,standard-function,plus-sign,minus-sign,file,mode
  . Atom,North,NorthEast,NorthWest,Parentheses,Seq,South,description,line,list
  . maal,opb,paren,plot,ln,string,invert,unary-minus-sign
  )
.   1:?SP
  & " + ":?plus-sign
  & " - ":?minus-sign
  & "- ":?unary-minus-sign
  &   (standard-function
      = sin
      | cos
      | tan
      | cot
      | log
      | sinh
      | cosh
      | arccos
      | arcsin
      | arctan
      | arccot
      | arcsinh
      | arccosh
      )
  & ( up
    =   a
      .     !arg:%?a*?arg
          &   (   !a:?^<0
                & 1
              |   !a:/
                & den$!a*!a
              | !a
              )
            * up$!arg
        | 1
    )
  & ( low
    =   a
      .     !arg:%?a*?arg
          &   (   !a:?^<0
                & !a
              |   !a:/
                & den$!a^-1
              | 1
              )
            * low$!arg
        | 1
    )
  & ( max
    =   a
      .     !arg:(%?a.?arg)
          & !a:>!arg
        | !arg
    )
  & ( paren
    =   a,b,c
      .     !arg:(?a.?b.?c)
          &   (     !a
                  : (   % %
                      | !standard-function
                    .   %
                      & !b:~(?.?)
                    )
                & "X Y"
              |   !a:(?,?)
                & X\LY
              |   !a:?_?
                & X_Y
              )
            : ?a
          &   (   !b:% %
                & !a " Z"
              |   !b:?_?
                & !a_Z
              )
            : ?b
          & den$(sim$(str$!b,)):>5
          & new$(Parentheses,!c)
        | !c
    )
  & (ln=.den$(sim$(str$!arg,)))
  & ( line
    =   loop
      .   ( loop
          =     !arg+-1:?arg:<0
              & 
            | "-" !loop
          )
        & str$!loop
    )
  & ( maal
    =   
      .     !arg:(#.?)
          & " "
        |     !arg
            : ((@.?)|?.%@*?)
          & " "
        | " "
    )
  & ( Atom
    =   (new=.!arg:?(its.value)
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (!y.!x.str$!(its.value))
        )
      . (prt=.!(its.value))
      . (value=)
      . (xsiz=.ln$!(its.value))
      . (ysiz=.1)
      . (usiz=.1)
      . (dsiz=.0)
    )

  & ( Parentheses
    =   ( new
        = .!arg:(=?(its.value))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (!y.!x."(")+(its.value.paint)$(!y.!x+1)+(!y.!x+1+(its.value.xsiz)$.")")
        )
      . (prt=.its.value.prt)
      . (value=)
      . (xsiz=.2+(its.value.xsiz)$)
      . (ysiz=.(its.value.ysiz)$)
      . (usiz=.(its.value.usiz)$)
      . (dsiz=.(its.value.dsiz)$)
    )
  & ( North
    =   ( new
        = .!arg:((=?(its.middle)).(=?(its.north)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (its.north.paint)$(!y+-1*((its.middle.usiz)$+(its.north.dsiz)$).!x+1/2*((its.middle.xsiz)$+-1*(its.north.xsiz)$))+(its.middle.paint)$(!y.!x)
        )
      . (prt=."middle(" (its.middle.prt)$() ") north(" (its.north.prt)$() ")")
      . (middle=)
      . (north=)
      . (xsiz=.max$((its.north.xsiz)$.(its.middle.xsiz)$))
      . (ysiz=.(its.north.ysiz)$+(its.middle.ysiz)$)
      . (usiz=.(its.north.ysiz)$+(its.middle.usiz)$)
      . (dsiz=.(its.middle.dsiz)$)
    )
  & ( NorthEast
    =   ( new
        =   
          .   !arg
            : ((=?(its.middle)).(=?(its.north-east)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (its.north-east.paint)$(!y+-1*((its.middle.usiz)$+(its.north-east.dsiz)$).!x+(its.middle.xsiz)$)+(its.middle.paint)$(!y.!x)
        )
      . (prt=."middle(" (its.middle.prt)$() ") north-east(" (its.north-east.prt)$() ")")
      . (middle=)
      . (north-east=)
      . (xsiz=.(its.north-east.xsiz)$+(its.middle.xsiz)$)
      . (ysiz=.(its.north-east.ysiz)$+(its.middle.ysiz)$)
      . (usiz=.(its.north-east.ysiz)$+(its.middle.usiz)$)
      . (dsiz=.(its.middle.dsiz)$)
    )
  & ( NorthWest
    =   ( new
        =   
          .   !arg
            : ((=?(its.middle)).(=?(its.north-west)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (its.north-west.paint)$(!y+-1*((its.middle.usiz)$+(its.north-west.dsiz)$).!x)+(its.middle.paint)$(!y.!x+(its.north-west.xsiz)$)
        )
      . (prt=."middle(" (its.middle.prt)$() ") north-west(" (its.north-west.prt)$() ")")
      . (middle=)
      . (north-west=)
      . (xsiz=.(its.north-west.xsiz)$+(its.middle.xsiz)$)
      . (ysiz=.(its.north-west.ysiz)$+(its.middle.ysiz)$)
      . (usiz=.(its.north-west.ysiz)$+(its.middle.usiz)$)
      . (dsiz=.(its.middle.dsiz)$)
    )
  & ( South
    =   ( new
        = .!arg:((=?(its.middle)).(=?(its.south)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)

            & (its.middle.paint)$(!y.!x)+(its.south.paint)$(!y+(its.middle.dsiz)$+(its.south.usiz)$.!x+1/2*((its.middle.xsiz)$+-1*(its.south.xsiz)$))
        )
      . (prt=."middle(" (its.middle.prt)$() ") south(" (its.south.prt)$() ")")
      . (middle=)
      . (south=)
      . (xsiz=.max$((its.south.xsiz)$.(its.middle.xsiz)$))
      . (ysiz=.(its.south.ysiz)$+(its.middle.ysiz)$)
      . (usiz=.(its.middle.usiz)$)
      . (dsiz=.(its.middle.dsiz)$+(its.south.ysiz)$)
    )
  & ( SouthEast
    =   ( new
        =   
          .   !arg
            : ((=?(its.middle)).(=?(its.south-east)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & (its.middle.paint)$(!y.!x)+(its.south-east.paint)$(!y+((its.middle.dsiz)$+(its.south-east.usiz)$).!x+(its.middle.xsiz)$)
        )
      . (prt=."middle(" (its.middle.prt)$() ") south-east(" (its.south-east.prt)$() ")")
      . (middle=)
      . (south-east=)
      . (xsiz=.(its.south-east.xsiz)$+(its.middle.xsiz)$)
      . (ysiz=.(its.south-east.ysiz)$+(its.middle.ysiz)$)
      . (usiz=.(its.middle.usiz)$)
      . (dsiz=.(its.middle.dsiz)$+(its.south-east.ysiz)$)
    )

  & ( Seq
    =   ( new
        = .!arg:((=?(its.first)).(=?(its.second)))
        )
      . ( paint
        =   x,y
          .   !arg:(?y.?x)
            & ((its.first.paint)$(!y.!x)+(its.second.paint)$(!y.!x+(its.first.xsiz)$))
        )
      . (prt=."first(" (its.first.prt)$() ") second(" (its.second.prt)$() ")")
      . (first=)
      . (second=)
      . (xsiz=.(its.first.xsiz)$+(its.second.xsiz)$)
      . (ysiz=.(its.usiz)$+(its.dsiz)$)
      . (usiz=.max$((its.first.usiz)$.(its.second.usiz)$))
      . (dsiz=.max$((its.first.dsiz)$.(its.second.dsiz)$))
    )

  & ( opb
    =   a,b,op
      .     !arg:(?arg.?op)
          & !arg:@
          & (   !arg:/
              & new$(Atom,den$!arg):?b
              & new$(Atom,str$(!arg*!(b..value))):?a
              & new$(South,(new$(North,(new$(Atom,line$(max$((a..xsiz)$.(b..xsiz)$))).!a)).!b))
            | new$(Atom,str$!arg)
            )
        |   !arg:?*?^<0*?
          & opb$(up$!arg.U P):?a
          & opb$(low$!arg^-1.L O W):?b
          & new$(South,(new$(North,(new$(Atom,line$(max$((a..xsiz)$.(b..xsiz)$))).!a)).!b))
        |   paren
          $ ( !arg
            . !op
            .     !arg:%?a+%?b
                &   new
                  $ ( Seq
                    , ( opb$(!a.!arg)
                      .     !b:(<0*?:?a)+?b
                          & new$(Seq,(new$(Atom,!minus-sign).opb$(-1*!a+!b.!arg)))
                        | new$(Seq,(new$(Atom,!plus-sign).opb$(!b.!arg)))
                      )
                    )
              |   !arg:%?a*%?b
                & (   !a:-1
                    & new$(Seq,(new$(Atom,!unary-minus-sign).opb$(!b.!arg)))
                  |   new
                    $ ( Seq
                      , (   new
                          $ ( Seq
                            , (     !a:<0
                                  & new$(Seq,(new$(Atom,!unary-minus-sign).opb$(-1*!a.!arg)))
                                | opb$(!a.!arg)
                              . new$(Atom,maal$(!a.!b))
                              )
                            )
                        . opb$(!b.!arg)
                        )
                      )
                  )
              |   !arg:?a^?b
                & (     !a
                      : (   !standard-function
                          : ?a
                        . ?c
                        )
                    & new$(Seq,(new$(NorthEast,(new$(Atom,!a).opb$(!b.Y Z))).opb$(!c.Y Z)))
                  | new$(NorthEast,(opb$(!a.!arg).opb$(!b.Y Z)))
                  )
              |   !arg:?a\L?b
                & new$(NorthWest
                      , ( new$( Seq
                              , ( new$(Atom,"log ")
                                . opb$(!b.!arg)
                                )
                              )
                        . opb$(!a.Y Z)
                        )
                      )
              |   !arg:(?a,?b)
               & (     !a
                      : (   !standard-function
                          : ?a
                        . ?c
                        )
                    & new$(Seq,(new$(SouthEast,(new$(Atom,!a).opb$(!b.Y Z))).opb$(!c.Y Z)))
                  | new$(SouthEast,(opb$(!a.!arg).opb$(!b.Y Z)))
                  )
              |   !arg:?b\D?a
                & opb$(d !b.U P):?b
                & opb$(d !a.L O W):?a
                & new$(South,(new$(North,(new$(Atom,line$(max$((a..xsiz)$.(b..xsiz)$))).!a)).!b))
              |   !arg:(?a.?b)
                & (     !a
                      : !standard-function
                    & new$(Seq,(new$(Atom,str$(!a " ")).opb$(!b.Y Z)))
                  | new$(Seq,(new$(Seq,(opb$(!a.!arg).new$(Atom,"."))).opb$(!b.!arg)))
                  )
              |   !arg:%?a %?b
                & new$(Seq,(opb$(!a.Y Z).opb$(!b.Y Z)))
            )
    )
  & ( plot
    =   loop1,loop2,loop3,a,b,y,x,txt,miny,curx,cnt
      .   ( loop1
          =   !arg:(?y.?x.?txt)+?arg
            & ( !y:~>!miny
              |   !y:?miny
                & out$" "
                & "\n" !string :?string
                & 0:?curx
              )
            & !x+-1*!curx:?cnt
            & ~!loop2
            & put$!txt
            & !txt !string :?string
            & ln$!txt+!x+-1*!cnt:?curx
            & !loop1
          )
        & ( loop2
          =   !cnt+-1:~<0:?cnt
            & put$" "
            & " " !string :?string
            & !loop2
          )
        & !arg:(?miny.?)+?
        & ~!loop1
        & out$" "
        & "\n" !string :?string
    )
  & (   !arg
      : (?.?.APP|NEW)
      : (?arg.?file.?mode)
    |   stdout:?file
      & APP:?mode
    )
  & ( convert-log
    =   a,b
      .     !arg:e\L?b
          & (log.!b)
        |   !arg:?a_?b
          & convert-log$(!a_convert-log$!b)
        | !arg
    )
  & ( invert
    = a,loop,b
    . (loop =
      !arg:%?a ?arg
      & !a !b:?b
      & !loop
      )
    & :?b
    & ~!loop
    & !b
    )
  & convert-log$!arg:?arg
  & opb$(!arg.A.B):?description
  & (description..paint)$((description..usiz)$+-1.0):?list
  & :?string
  & plot$!list
  &   out
    $ "****************************************************************************"
  & str$(\n invert$!string)
{  & !arg};

