1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Generate.JavaScript.Builder (stmtsToText) where
5import qualified Data.List as List
6import Data.Monoid ((<>))
7import qualified Data.Text.Lazy as LazyText
8import Data.Text.Lazy.Builder
9import Data.Text.Lazy.Builder.Int (decimal)
10import Data.Text.Lazy.Builder.RealFloat (realFloat)
11import Language.ECMAScript3.Syntax
12import Prelude hiding (lines)
16-- CONVERT TO LAZY TEXT
19stmtsToText :: [Statement a] -> LazyText.Text
21 toLazyText (fromStmtBlock "" stmts)
28deeper :: Builder -> Builder
33commaSep :: [Builder] -> Builder
35 mconcat (List.intersperse ", " builders)
38commaNewlineSep :: Builder -> [Builder] -> Builder
39commaNewlineSep indent builders =
40 mconcat (List.intersperse (",\n" <> deeper indent) builders)
47fromStmtBlock :: Builder -> [Statement a] -> Builder
48fromStmtBlock indent stmts =
49 mconcat (map (fromStmt indent) stmts)
52fromStmt :: Builder -> Statement a -> Builder
53fromStmt indent statement =
56 fromStmtBlock indent stmts
62 indent <> snd (fromExpr indent Whatever expr) <> ";\n"
64 IfStmt _ condition thenStmt elseStmt ->
66 [ indent, "if (", snd (fromExpr indent Whatever condition), ") {\n"
67 , fromStmt (deeper indent) thenStmt
68 , indent, "} else {\n"
69 , fromStmt (deeper indent) elseStmt
73 IfSingleStmt _ condition thenStmt ->
75 [ indent, "if (", snd (fromExpr indent Whatever condition), ") {\n"
76 , fromStmt (deeper indent) thenStmt
80 SwitchStmt _ expr clauses ->
82 [ indent, "switch (", snd (fromExpr indent Whatever expr), ") {\n"
83 , mconcat (map (fromClause (deeper indent)) clauses)
87 WhileStmt _ expr stmt ->
89 [ indent, "while (", snd (fromExpr indent Whatever expr), ") {\n"
90 , fromStmt (deeper indent) stmt
94 DoWhileStmt _ stmt expr ->
97 , fromStmt (deeper indent) stmt
98 , indent, "} while(", snd (fromExpr indent Whatever expr), ");\n"
101 BreakStmt _ Nothing ->
104 BreakStmt _ (Just label) ->
105 indent <> "break " <> fromId label <> ";\n"
107 ContinueStmt _ Nothing ->
108 indent <> "continue;\n"
110 ContinueStmt _ (Just label) ->
111 indent <> "continue " <> fromId label <> ";\n"
113 LabelledStmt _ label stmt ->
115 [ indent, fromId label, ":\n"
116 , fromStmt indent stmt
129 indent <> "throw " <> snd (fromExpr indent Whatever expr) <> ";\n"
131 ReturnStmt _ Nothing ->
132 indent <> "return;\n"
134 ReturnStmt _ (Just expr) ->
135 indent <> "return " <> snd (fromExpr indent Whatever expr) <> ";\n"
143 VarDeclStmt _ decls ->
144 indent <> "var " <> commaNewlineSep indent (map (fromVarDecl indent) decls) <> ";\n"
146 FunctionStmt _ name args stmts ->
147 indent <> "function " <> fromId name <> "(" <> commaSep (map fromId args) <> ") {\n"
149 fromStmtBlock (deeper indent) stmts
158fromClause :: Builder -> CaseClause a -> Builder
159fromClause indent clause =
161 CaseClause _ expr stmts ->
162 indent <> "case " <> snd (fromExpr indent Whatever expr) <> ":\n"
163 <> fromStmtBlock (deeper indent) stmts
165 CaseDefault _ stmts ->
166 indent <> "default:\n"
167 <> fromStmtBlock (deeper indent) stmts
174fromId :: Id a -> Builder
183fromVarDecl :: Builder -> VarDecl a -> Builder
184fromVarDecl indent (VarDecl _ (Id _ name) maybeExpr) =
190 fromString name <> " = " <> snd (fromExpr indent Whatever expr)
197data Lines = One | Many deriving (Eq)
200merge :: Lines -> Lines -> Lines
202 if a == Many || b == Many then Many else One
205linesMap :: (a -> (Lines, b)) -> [a] -> (Bool, [b])
211 ( any ((==) Many . fst) pairs
216data Grouping = Atomic | Whatever
219parensFor :: Grouping -> Builder -> Builder
220parensFor grouping builder =
223 "(" <> builder <> ")"
229fromExpr :: Builder -> Grouping -> Expression a -> (Lines, Builder)
230fromExpr indent grouping expression =
232 StringLit _ string ->
256 (anyMany, builders) =
257 linesMap (fromExpr indent Whatever) exprs
262 <> commaNewlineSep indent builders
263 <> "\n" <> indent <> "]"
266 "[" <> commaSep builders <> "]"
268 ObjectLit _ fields ->
274 (anyMany, builders) =
275 linesMap (fromField deeperIndent) fields
280 <> commaNewlineSep indent builders
281 <> "\n" <> indent <> "}"
284 "{" <> commaSep builders <> "}"
292 DotRef _ expr (Id _ name) ->
293 makeDot indent expr name
295 BracketRef _ expr bracketedExpr ->
296 makeBracketed indent expr bracketedExpr
301 PrefixExpr _ op expr ->
304 fromExpr indent Atomic expr
307 , parensFor grouping (fromPrefix op <> builder)
310 UnaryAssignExpr _ _ _ ->
313 InfixExpr _ op leftExpr rightExpr ->
316 fromExpr indent Atomic leftExpr
318 (rightLines, right) =
319 fromExpr indent Atomic rightExpr
321 ( merge leftLines rightLines
322 , parensFor grouping (left <> fromInfix op <> right)
325 CondExpr _ condExpr thenExpr elseExpr ->
327 condB = snd (fromExpr indent Atomic condExpr)
328 thenB = snd (fromExpr indent Atomic thenExpr)
329 elseB = snd (fromExpr indent Atomic elseExpr)
332 , parensFor grouping (condB <> " ? " <> thenB <> " : " <> elseB)
335 AssignExpr _ op lValue expr ->
338 fromLValue indent lValue
340 (rightLines, right) =
341 fromExpr indent Whatever expr
343 ( merge leftLines rightLines
344 , parensFor grouping (left <> fromAssign op <> right)
350 CallExpr _ function args ->
357 snd (fromExpr indent Atomic function)
360 linesMap (fromExpr deeperIndent Whatever) args
363 funcB <> "(\n" <> deeperIndent <> commaNewlineSep indent argsB <> ")"
366 funcB <> "(" <> commaSep argsB <> ")"
368 FuncExpr _ maybeName args stmts ->
370 "function " <> maybe mempty fromId maybeName <> "(" <> commaSep (map fromId args) <> ") {\n"
372 fromStmtBlock (deeper indent) stmts
381fromField :: Builder -> (Prop a, Expression a) -> (Lines, Builder)
382fromField indent (prop, expr) =
385 fromExpr indent Whatever expr
388 , fromProp prop <> ": " <> builder
392fromProp :: Prop a -> Builder
398 PropString _ string ->
409quoted :: String -> Builder
411 fromString ('\'' : foldr escapeCons "'" string)
414-- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#String_literals
415escapeCons :: Char -> String -> String
416escapeCons char rest =
418 '\b' -> '\\' : 'b' : rest
419 '\f' -> '\\' : 'f' : rest
420 '\n' -> '\\' : 'n' : rest
421 '\r' -> '\\' : 'r' : rest
422 '\t' -> '\\' : 't' : rest
423 '\v' -> '\\' : 'v' : rest
424 '\"' -> '\\' : '"' : rest
425 '\'' -> '\\' : '\'' : rest
426 '\\' -> '\\' : '\\' : rest
434fromLValue :: Builder -> LValue a -> (Lines, Builder)
435fromLValue indent lValue =
438 (One, fromString name)
441 makeDot indent expr field
443 LBracket _ expr bracketedExpr ->
444 makeBracketed indent expr bracketedExpr
447makeDot :: Builder -> Expression a -> String -> (Lines, Builder)
448makeDot indent expr field =
451 fromExpr indent Atomic expr
453 (lines, builder <> "." <> fromString field)
456makeBracketed :: Builder -> Expression a -> Expression a -> (Lines, Builder)
457makeBracketed indent expr bracketedExpr =
460 fromExpr indent Atomic expr
462 (bracketedLines, bracketedBuilder) =
463 fromExpr indent Whatever bracketedExpr
465 ( merge lines bracketedLines
466 , builder <> "[" <> bracketedBuilder <> "]"
474fromPrefix :: PrefixOp -> Builder
481 PrefixTypeof -> "typeof "
482 PrefixVoid -> "void "
483 PrefixDelete -> "delete "
486fromAssign :: AssignOp -> Builder
490 OpAssignAdd -> " += "
491 OpAssignSub -> " -= "
492 OpAssignMul -> " *= "
493 OpAssignDiv -> " /= "
494 OpAssignMod -> " %= "
495 OpAssignLShift -> " <<= "
496 OpAssignSpRShift -> " >>= "
497 OpAssignZfRShift -> " >>>= "
498 OpAssignBAnd -> " &= "
499 OpAssignBXor -> " ^= "
500 OpAssignBOr -> " |= "
503fromInfix :: InfixOp -> Builder
511 OpInstanceof -> " instanceof "
514 OpStrictEq -> " === "
515 OpStrictNEq -> " !=== "
524 OpZfRShift -> " >>> "
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list