packages feed

uu-cco-examples-0.1.0.1: src/CCO/ArithBool/AG/Printing.ag

imports
{
import CCO.Printing
}

-------------------------------------------------------------------------------
-- Pretty printing
-------------------------------------------------------------------------------

attr Tm Tm_
  syn pp :: Doc

sem Tm_
  | Num     lhs.pp = showable @n
  | False_  lhs.pp = text "false"
  | True_   lhs.pp = text "true"

sem Tm_
  | If  lhs.pp = ppIf @t1.pp @t2.pp @t3.pp

{
-- | Pretty prints a conditional.
ppIf :: Doc -> Doc -> Doc -> Doc
ppIf guard then_ else_ = singleLine >//< multiLine >//< indented
  where
    singleLine = ppIf_ >#< guard >#<
                 ppThen >#< then_ >#<
                 ppElse >#< else_ >#<
                 ppFi
    multiLine  = ppIf_ >|< text "   " >|< guard >-<
                 ppThen >#< then_ >-<
                 ppElse >#< else_ >-<
                 ppFi
    indented   = ppIf_ >-< indent 2 guard >-<
                 ppThen >-< indent 2 then_ >-<
                 ppElse >-< indent 2 else_ >-<
                 ppFi
    ppIf_      = text "if"
    ppThen     = text "then"
    ppElse     = text "else"
    ppFi       = text "fi"
}

sem Tm_
  | Add  lhs.pp = ppInfix @lhs.prec ("+" , 6) @t1.pp @t2.pp
  | Sub  lhs.pp = ppInfix @lhs.prec ("-" , 6) @t1.pp @t2.pp
  | Mul  lhs.pp = ppInfix @lhs.prec ("*" , 7) @t1.pp @t2.pp
  | Div  lhs.pp = ppInfix @lhs.prec ("/" , 7) @t1.pp @t2.pp
  | Lt   lhs.pp = ppInfix @lhs.prec ("<" , 4) @t1.pp @t2.pp  
  | Eq   lhs.pp = ppInfix @lhs.prec ("==", 4) @t1.pp @t2.pp
  | Gt   lhs.pp = ppInfix @lhs.prec (">" , 4) @t1.pp @t2.pp  

-------------------------------------------------------------------------------
-- Precedence levels
-------------------------------------------------------------------------------

{
-- | Type of precedence levels.
type Prec = Int
}

attr Tm Tm_
  inh prec :: Int

sem Tm_
  | If       t1.prec = 0
             t2.prec = 0
             t3.prec = 0
  | Add Sub  t1.prec = 6
             t2.prec = 7
  | Mul Div  t1.prec = 7
             t2.prec = 8
  | Lt Eq Gt t1.prec = 4
             t2.prec = 4 

{
-- | Pretty prints, given the precedence level of its immediate context, a term
-- constructed from a binary operator of a specified precedence level.
-- 
-- A term is enclosed in parentheses if the precedence level of its operator 
-- is less than the precedence level of the enclosing context.

ppInfix :: Prec -> (String, Prec) -> Doc -> Doc -> Doc
ppInfix ctx (op, prec) l r = modifier $ l >#< ppOp >#< r
  where
    modifier = if prec < ctx then parens else id
    ppOp     = text op
}