module Hydra.Util.Codetree.Script where
import Hydra.Util.Codetree.Ast
import qualified Data.List as L
angleBraces :: Brackets
angleBraces :: Brackets
angleBraces = Symbol -> Symbol -> Brackets
Brackets (String -> Symbol
sym String
"<") (String -> Symbol
sym String
">")
angleBracesList :: BlockStyle -> [Expr] -> Expr
angleBracesList :: BlockStyle -> [Expr] -> Expr
angleBracesList BlockStyle
style [Expr]
els = case [Expr]
els of
[] -> String -> Expr
cst String
"<>"
[Expr]
_ -> Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
angleBraces BlockStyle
style forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
els
bracketList :: BlockStyle -> [Expr] -> Expr
bracketList :: BlockStyle -> [Expr] -> Expr
bracketList BlockStyle
style [Expr]
els = case [Expr]
els of
[] -> String -> Expr
cst String
"[]"
[Expr]
_ -> Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
squareBrackets BlockStyle
style forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
els
brackets :: Brackets -> BlockStyle -> Expr -> Expr
brackets :: Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
br BlockStyle
style Expr
e = BracketExpr -> Expr
ExprBrackets forall a b. (a -> b) -> a -> b
$ Brackets -> Expr -> BlockStyle -> BracketExpr
BracketExpr Brackets
br Expr
e BlockStyle
style
commaSep :: BlockStyle -> [Expr] -> Expr
commaSep :: BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
l = case [Expr]
l of
[] -> String -> Expr
cst String
""
[Expr
x] -> Expr
x
(Expr
h:[Expr]
r) -> Op -> Expr -> Expr -> Expr
ifx Op
commaOp Expr
h forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
r
where
break :: Ws
break = case forall (t :: * -> *) a. Foldable t => t a -> Int
L.length forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
L.filter forall a. a -> a
id [BlockStyle -> Bool
blockStyleNewlineBeforeContent BlockStyle
style, BlockStyle -> Bool
blockStyleNewlineAfterContent BlockStyle
style] of
Int
0 -> Ws
WsSpace
Int
1 -> Ws
WsBreak
Int
2 -> Ws
WsDoubleBreak
commaOp :: Op
commaOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
",") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
break) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
curlyBlock :: BlockStyle -> Expr -> Expr
curlyBlock :: BlockStyle -> Expr -> Expr
curlyBlock BlockStyle
style Expr
e = BlockStyle -> [Expr] -> Expr
curlyBracesList BlockStyle
style [Expr
e]
curlyBraces :: Brackets
curlyBraces :: Brackets
curlyBraces = Symbol -> Symbol -> Brackets
Brackets (String -> Symbol
sym String
"{") (String -> Symbol
sym String
"}")
curlyBracesList :: BlockStyle -> [Expr] -> Expr
curlyBracesList :: BlockStyle -> [Expr] -> Expr
curlyBracesList BlockStyle
style [Expr]
els = case [Expr]
els of
[] -> String -> Expr
cst String
"{}"
[Expr]
_ -> Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
curlyBraces BlockStyle
style forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
els
cst :: String -> Expr
cst :: String -> Expr
cst = Symbol -> Expr
ExprConst forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Symbol
Symbol
dotSep :: [Expr] -> Expr
dotSep :: [Expr] -> Expr
dotSep = Op -> [Expr] -> Expr
sep forall a b. (a -> b) -> a -> b
$ Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
".") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsNone) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
doubleNewlineSep :: [Expr] -> Expr
doubleNewlineSep :: [Expr] -> Expr
doubleNewlineSep = Op -> [Expr] -> Expr
sep forall a b. (a -> b) -> a -> b
$ Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsBreak Ws
WsBreak) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
fullBlockStyle :: BlockStyle
fullBlockStyle :: BlockStyle
fullBlockStyle = Bool -> Bool -> Bool -> BlockStyle
BlockStyle Bool
True Bool
True Bool
True
halfBlockStyle :: BlockStyle
halfBlockStyle :: BlockStyle
halfBlockStyle = Bool -> Bool -> Bool -> BlockStyle
BlockStyle Bool
True Bool
True Bool
False
ifx :: Op -> Expr -> Expr -> Expr
ifx :: Op -> Expr -> Expr -> Expr
ifx Op
op Expr
lhs Expr
rhs = OpExpr -> Expr
ExprOp forall a b. (a -> b) -> a -> b
$ Op -> Expr -> Expr -> OpExpr
OpExpr Op
op Expr
lhs Expr
rhs
indent :: String -> String
indent :: String -> String
indent String
s = forall a. [a] -> [[a]] -> [a]
L.intercalate String
"\n" forall a b. (a -> b) -> a -> b
$ (String
" " forall a. [a] -> [a] -> [a]
++) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> [String]
lines String
s
indentBlock :: Expr -> [Expr] -> Expr
indentBlock :: Expr -> [Expr] -> Expr
indentBlock Expr
head [Expr]
els = Op -> Expr -> Expr -> Expr
ifx Op
idtOp Expr
head forall a b. (a -> b) -> a -> b
$ [Expr] -> Expr
newlineSep [Expr]
els
where
idtOp :: Op
idtOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsSpace Ws
WsBreakAndIndent) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
indentLines :: [Expr] -> Expr
indentLines :: [Expr] -> Expr
indentLines [Expr]
els = Op -> Expr -> Expr -> Expr
ifx Op
topOp (String -> Expr
cst String
"") ([Expr] -> Expr
newlineSep [Expr]
els)
where
topOp :: Op
topOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsBreakAndIndent) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
infixWs :: String -> Expr -> Expr -> Expr
infixWs :: String -> Expr -> Expr -> Expr
infixWs String
op Expr
l Expr
r = [Expr] -> Expr
spaceSep [Expr
l, String -> Expr
cst String
op, Expr
r]
infixWsList :: String -> [Expr] -> Expr
infixWsList :: String -> [Expr] -> Expr
infixWsList String
op [Expr]
opers = [Expr] -> Expr
spaceSep forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl (\[Expr]
e Expr
r -> if forall (t :: * -> *) a. Foldable t => t a -> Bool
L.null [Expr]
e then [Expr
r] else Expr
rforall a. a -> [a] -> [a]
:Expr
opExprforall a. a -> [a] -> [a]
:[Expr]
e) [] forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
L.reverse [Expr]
opers
where
opExpr :: Expr
opExpr = String -> Expr
cst String
op
inlineStyle :: BlockStyle
inlineStyle :: BlockStyle
inlineStyle = Bool -> Bool -> Bool -> BlockStyle
BlockStyle Bool
False Bool
False Bool
False
newlineSep :: [Expr] -> Expr
newlineSep :: [Expr] -> Expr
newlineSep = Op -> [Expr] -> Expr
sep forall a b. (a -> b) -> a -> b
$ Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsBreak) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
noPadding :: Padding
noPadding :: Padding
noPadding = Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsNone
noSep :: [Expr] -> Expr
noSep :: [Expr] -> Expr
noSep = Op -> [Expr] -> Expr
sep forall a b. (a -> b) -> a -> b
$ Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsNone) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
num :: Int -> Expr
num :: Int -> Expr
num = String -> Expr
cst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show
op :: String -> Int -> Associativity -> Op
op :: String -> Int -> Associativity -> Op
op String
s Int
p = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
Symbol String
s) (Ws -> Ws -> Padding
Padding Ws
WsSpace Ws
WsSpace) (Int -> Precedence
Precedence Int
p)
orOp :: Bool -> Op
orOp :: Bool -> Op
orOp Bool
newlines = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"|") (Ws -> Ws -> Padding
Padding Ws
WsSpace (if Bool
newlines then Ws
WsBreak else Ws
WsSpace)) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
orSep :: BlockStyle -> [Expr] -> Expr
orSep :: BlockStyle -> [Expr] -> Expr
orSep BlockStyle
style [Expr]
l = case [Expr]
l of
[] -> String -> Expr
cst String
""
[Expr
x] -> Expr
x
(Expr
h:[Expr]
r) -> Op -> Expr -> Expr -> Expr
ifx (Bool -> Op
orOp Bool
newlines) Expr
h forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
orSep BlockStyle
style [Expr]
r
where
newlines :: Bool
newlines = BlockStyle -> Bool
blockStyleNewlineBeforeContent BlockStyle
style
parenList :: Bool -> [Expr] -> Expr
parenList :: Bool -> [Expr] -> Expr
parenList Bool
newlines [Expr]
els = case [Expr]
els of
[] -> String -> Expr
cst String
"()"
[Expr]
_ -> Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
parentheses BlockStyle
style forall a b. (a -> b) -> a -> b
$ BlockStyle -> [Expr] -> Expr
commaSep BlockStyle
style [Expr]
els
where
style :: BlockStyle
style = if Bool
newlines Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Int
L.length [Expr]
els forall a. Ord a => a -> a -> Bool
> Int
1 then BlockStyle
halfBlockStyle else BlockStyle
inlineStyle
parens :: Expr -> Expr
parens :: Expr -> Expr
parens = Brackets -> BlockStyle -> Expr -> Expr
brackets Brackets
parentheses BlockStyle
inlineStyle
parentheses :: Brackets
parentheses :: Brackets
parentheses = Symbol -> Symbol -> Brackets
Brackets (String -> Symbol
sym String
"(") (String -> Symbol
sym String
")")
parenthesize :: Expr -> Expr
parenthesize :: Expr -> Expr
parenthesize Expr
exp = case Expr
exp of
ExprOp (OpExpr op :: Op
op@(Op Symbol
_ Padding
_ Precedence
prec Associativity
assoc) Expr
lhs Expr
rhs) -> OpExpr -> Expr
ExprOp (Op -> Expr -> Expr -> OpExpr
OpExpr Op
op Expr
lhs2 Expr
rhs2)
where
lhs' :: Expr
lhs' = Expr -> Expr
parenthesize Expr
lhs
rhs' :: Expr
rhs' = Expr -> Expr
parenthesize Expr
rhs
lhs2 :: Expr
lhs2 = case Expr
lhs' of
ExprOp (OpExpr (Op Symbol
_ Padding
_ Precedence
lprec Associativity
lassoc) Expr
_ Expr
_) -> case Precedence
prec forall a. Ord a => a -> a -> Ordering
`compare` Precedence
lprec of
Ordering
LT -> Expr
lhs'
Ordering
GT -> Expr -> Expr
parens Expr
lhs'
Ordering
EQ -> if Associativity -> Bool
assocLeft Associativity
assoc Bool -> Bool -> Bool
&& Associativity -> Bool
assocLeft Associativity
lassoc
then Expr
lhs'
else Expr -> Expr
parens Expr
lhs'
Expr
_ -> Expr
lhs'
rhs2 :: Expr
rhs2 = case Expr
rhs' of
ExprOp (OpExpr (Op Symbol
_ Padding
_ Precedence
rprec Associativity
rassoc) Expr
_ Expr
_) -> case Precedence
prec forall a. Ord a => a -> a -> Ordering
`compare` Precedence
rprec of
Ordering
LT -> Expr
rhs'
Ordering
GT -> Expr -> Expr
parens Expr
rhs'
Ordering
EQ -> if Associativity -> Bool
assocRight Associativity
assoc Bool -> Bool -> Bool
&& Associativity -> Bool
assocRight Associativity
rassoc
then Expr
rhs'
else Expr -> Expr
parens Expr
rhs'
Expr
_ -> Expr
rhs'
assocLeft :: Associativity -> Bool
assocLeft Associativity
a = Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityLeft Bool -> Bool -> Bool
|| Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityNone Bool -> Bool -> Bool
|| Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityBoth
assocRight :: Associativity -> Bool
assocRight Associativity
a = Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityRight Bool -> Bool -> Bool
|| Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityNone Bool -> Bool -> Bool
|| Associativity
a forall a. Eq a => a -> a -> Bool
== Associativity
AssociativityBoth
ExprBrackets (BracketExpr Brackets
br Expr
e BlockStyle
newlines) -> BracketExpr -> Expr
ExprBrackets (Brackets -> Expr -> BlockStyle -> BracketExpr
BracketExpr Brackets
br (Expr -> Expr
parenthesize Expr
e) BlockStyle
newlines)
Expr
_ -> Expr
exp
prefix :: String -> Expr -> Expr
prefix :: String -> Expr -> Expr
prefix String
p = Op -> Expr -> Expr -> Expr
ifx Op
preOp (String -> Expr
cst String
"")
where
preOp :: Op
preOp = Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
p) (Ws -> Ws -> Padding
Padding Ws
WsNone Ws
WsNone) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
printExpr :: Expr -> String
printExpr :: Expr -> String
printExpr Expr
e = case Expr
e of
ExprConst (Symbol String
s) -> String
s
ExprOp (OpExpr (Op (Symbol String
sym) (Padding Ws
padl Ws
padr) Precedence
_ Associativity
_) Expr
l Expr
r) -> String
lhs forall a. [a] -> [a] -> [a]
++ Ws -> String
pad Ws
padl forall a. [a] -> [a] -> [a]
++ String
sym forall a. [a] -> [a] -> [a]
++ Ws -> String
pad Ws
padr forall a. [a] -> [a] -> [a]
++ String
rhs
where
lhs :: String
lhs = Ws -> String -> String
idt Ws
padl forall a b. (a -> b) -> a -> b
$ Expr -> String
printExpr Expr
l
rhs :: String
rhs = Ws -> String -> String
idt Ws
padr forall a b. (a -> b) -> a -> b
$ Expr -> String
printExpr Expr
r
idt :: Ws -> String -> String
idt Ws
ws String
s = if Ws
ws forall a. Eq a => a -> a -> Bool
== Ws
WsBreakAndIndent then String -> String
indent String
s else String
s
pad :: Ws -> String
pad Ws
ws = case Ws
ws of
Ws
WsNone -> String
""
Ws
WsSpace -> String
" "
Ws
WsBreak -> String
"\n"
Ws
WsBreakAndIndent -> String
"\n"
Ws
WsDoubleBreak -> String
"\n\n"
ExprBrackets (BracketExpr (Brackets (Symbol String
l) (Symbol String
r)) Expr
e BlockStyle
style) ->
String
l forall a. [a] -> [a] -> [a]
++ String
pre forall a. [a] -> [a] -> [a]
++ String
ibody forall a. [a] -> [a] -> [a]
++ String
suf forall a. [a] -> [a] -> [a]
++ String
r
where
body :: String
body = Expr -> String
printExpr Expr
e
ibody :: String
ibody = if Bool
doIndent then String -> String
indent String
body else String
body
pre :: String
pre = if Bool
nlBefore then String
"\n" else String
""
suf :: String
suf = if Bool
nlAfter then String
"\n" else String
""
BlockStyle Bool
doIndent Bool
nlBefore Bool
nlAfter = BlockStyle
style
printExprAsTree :: Expr -> String
printExprAsTree :: Expr -> String
printExprAsTree Expr
expr = case Expr
expr of
ExprConst (Symbol String
s) -> String
s
ExprBrackets (BracketExpr (Brackets (Symbol String
l) (Symbol String
r)) Expr
e BlockStyle
_) -> String
l forall a. [a] -> [a] -> [a]
++ String
r forall a. [a] -> [a] -> [a]
++ String
":\n" forall a. [a] -> [a] -> [a]
++ String -> String
indent (Expr -> String
printExprAsTree Expr
e)
ExprOp (OpExpr Op
op Expr
l Expr
r) -> Symbol -> String
h (Op -> Symbol
opSymbol Op
op) forall a. [a] -> [a] -> [a]
++ String
":\n" forall a. [a] -> [a] -> [a]
++ String -> String
indent (Expr -> String
printExprAsTree Expr
l) forall a. [a] -> [a] -> [a]
++ String
"\n" forall a. [a] -> [a] -> [a]
++ String -> String
indent (Expr -> String
printExprAsTree Expr
r)
where
h :: Symbol -> String
h (Symbol String
s) = String
s
sep :: Op -> [Expr] -> Expr
sep :: Op -> [Expr] -> Expr
sep Op
op [Expr]
els = case [Expr]
els of
[] -> String -> Expr
cst String
""
[Expr
x] -> Expr
x
(Expr
h:[Expr]
r) -> Op -> Expr -> Expr -> Expr
ifx Op
op Expr
h forall a b. (a -> b) -> a -> b
$ Op -> [Expr] -> Expr
sep Op
op [Expr]
r
spaceSep :: [Expr] -> Expr
spaceSep :: [Expr] -> Expr
spaceSep = Op -> [Expr] -> Expr
sep forall a b. (a -> b) -> a -> b
$ Symbol -> Padding -> Precedence -> Associativity -> Op
Op (String -> Symbol
sym String
"") (Ws -> Ws -> Padding
Padding Ws
WsSpace Ws
WsNone) (Int -> Precedence
Precedence Int
0) Associativity
AssociativityNone
squareBrackets :: Brackets
squareBrackets :: Brackets
squareBrackets = Symbol -> Symbol -> Brackets
Brackets (String -> Symbol
sym String
"[") (String -> Symbol
sym String
"]")
sym :: String -> Symbol
sym :: String -> Symbol
sym = String -> Symbol
Symbol