@@ -16,6 +16,7 @@ module Generate.JavaScript.Builder
1616
1717import Prelude hiding (lines)
1818import qualified Data.List as List
19+import qualified Data.ByteString as BS
1920import Data.ByteString.Builder as B
2021import Data.Monoid ((<>))
2122import qualified Generate.JavaScript.Name as Name
@@ -118,21 +119,40 @@ data PrefixOp
118119
119120stmtToBuilder :: Stmt -> Builder
120121stmtToBuilder stmts =
121− fromStmt "" stmts
122+ fromStmt levelZero stmts
122123
123124
124125exprToBuilder :: Expr -> Builder
125126exprToBuilder expr =
126− snd $ fromExpr "" Whatever expr
127+ snd $ fromExpr levelZero Whatever expr
127128
128129
129130
130−-- HELPERS
131+-- INDENT LEVEL
132+
133+
134+data Level =
135+ Level Builder Level
136+
131137
138+levelZero :: Level
139+levelZero =
140+ Level mempty (makeLevel 1 (BS.replicate 16 0x09 {-\t-}))
132141
133−deeper :: Builder -> Builder
134−deeper indent =
135− "\t" <> indent
142+
143+makeLevel :: Int -> BS.ByteString -> Level
144+makeLevel level oldTabs =
145+ let
146+ tabs =
147+ if level <= BS.length oldTabs
148+ then oldTabs
149+ else BS.replicate (BS.length oldTabs * 2) 0x09 {-\t-}
150+ in
151+ Level (B.byteString (BS.take level tabs)) (makeLevel (level + 1) tabs)
152+
153+
154+
155+-- HELPERS
136156
137157
138158commaSep :: [Builder] -> Builder
@@ -140,52 +160,52 @@ commaSep builders =
140160 mconcat (List.intersperse ", " builders)
141161
142162
143−commaNewlineSep :: Builder -> [Builder] -> Builder
144−commaNewlineSep indent builders =
145− mconcat (List.intersperse (",\n" <> deeper indent) builders)
163+commaNewlineSep :: Level -> [Builder] -> Builder
164+commaNewlineSep (Level _ (Level deeperIndent _)) builders =
165+ mconcat (List.intersperse (",\n" <> deeperIndent) builders)
146166
147167
148168
149169-- STATEMENTS
150170
151171
152−fromStmtBlock :: Builder -> [Stmt] -> Builder
153−fromStmtBlock indent stmts =
154− mconcat (map (fromStmt indent) stmts)
172+fromStmtBlock :: Level -> [Stmt] -> Builder
173+fromStmtBlock level stmts =
174+ mconcat (map (fromStmt level) stmts)
155175
156176
157−fromStmt :: Builder -> Stmt -> Builder
158−fromStmt indent statement =
177+fromStmt :: Level -> Stmt -> Builder
178+fromStmt level@(Level indent nextLevel) statement =
159179 case statement of
160180 Block stmts ->
161− fromStmtBlock indent stmts
181+ fromStmtBlock level stmts
162182
163183 EmptyStmt ->
164184 mempty
165185
166186 ExprStmt expr ->
167− indent <> snd (fromExpr indent Whatever expr) <> ";\n"
187+ indent <> snd (fromExpr level Whatever expr) <> ";\n"
168188
169189 IfStmt condition thenStmt elseStmt ->
170190 mconcat
171− [ indent, "if (", snd (fromExpr indent Whatever condition), ") {\n"
172− , fromStmt (deeper indent) thenStmt
191+ [ indent, "if (", snd (fromExpr level Whatever condition), ") {\n"
192+ , fromStmt nextLevel thenStmt
173193 , indent, "} else {\n"
174− , fromStmt (deeper indent) elseStmt
194+ , fromStmt nextLevel elseStmt
175195 , indent, "}\n"
176196 ]
177197
178198 Switch expr clauses ->
179199 mconcat
180− [ indent, "switch (", snd (fromExpr indent Whatever expr), ") {\n"
181− , mconcat (map (fromClause (deeper indent)) clauses)
200+ [ indent, "switch (", snd (fromExpr level Whatever expr), ") {\n"
201+ , mconcat (map (fromClause nextLevel) clauses)
182202 , indent, "}\n"
183203 ]
184204
185205 While expr stmt ->
186206 mconcat
187− [ indent, "while (", snd (fromExpr indent Whatever expr), ") {\n"
188− , fromStmt (deeper indent) stmt
207+ [ indent, "while (", snd (fromExpr level Whatever expr), ") {\n"
208+ , fromStmt nextLevel stmt
189209 , indent, "}\n"
190210 ]
191211
@@ -204,37 +224,37 @@ fromStmt indent statement =
204224 Labelled label stmt ->
205225 mconcat
206226 [ indent, Name.toBuilder label, ":\n"
207− , fromStmt indent stmt
227+ , fromStmt level stmt
208228 ]
209229
210230 Try tryStmt errorName catchStmt ->
211231 mconcat
212232 [ indent, "try {\n"
213− , fromStmt (deeper indent) tryStmt
233+ , fromStmt nextLevel tryStmt
214234 , indent, "} catch (", Name.toBuilder errorName, ") {\n"
215− , fromStmt (deeper indent) catchStmt
235+ , fromStmt nextLevel catchStmt
216236 , indent, "}\n"
217237 ]
218238
219239 Throw expr ->
220− indent <> "throw " <> snd (fromExpr indent Whatever expr) <> ";"
240+ indent <> "throw " <> snd (fromExpr level Whatever expr) <> ";"
221241
222242 Return expr ->
223− indent <> "return " <> snd (fromExpr indent Whatever expr) <> ";\n"
243+ indent <> "return " <> snd (fromExpr level Whatever expr) <> ";\n"
224244
225245 Var name expr ->
226− indent <> "var " <> Name.toBuilder name <> " = " <> snd (fromExpr indent Whatever expr) <> ";\n"
246+ indent <> "var " <> Name.toBuilder name <> " = " <> snd (fromExpr level Whatever expr) <> ";\n"
227247
228248 Vars [] ->
229249 mempty
230250
231251 Vars vars ->
232− indent <> "var " <> commaNewlineSep indent (map (varToBuilder indent) vars) <> ";\n"
252+ indent <> "var " <> commaNewlineSep level (map (varToBuilder level) vars) <> ";\n"
233253
234254 FunctionStmt name args stmts ->
235255 indent <> "function " <> Name.toBuilder name <> "(" <> commaSep (map Name.toBuilder args) <> ") {\n"
236256 <>
237− fromStmtBlock (deeper indent) stmts
257+ fromStmtBlock nextLevel stmts
238258 <>
239259 indent <> "}\n"
240260
@@ -243,25 +263,25 @@ fromStmt indent statement =
243263-- SWITCH CLAUSES
244264
245265
246−fromClause :: Builder -> Case -> Builder
247−fromClause indent clause =
266+fromClause :: Level -> Case -> Builder
267+fromClause level@(Level indent nextLevel) clause =
248268 case clause of
249269 Case expr stmts ->
250− indent <> "case " <> snd (fromExpr indent Whatever expr) <> ":\n"
251− <> fromStmtBlock (deeper indent) stmts
270+ indent <> "case " <> snd (fromExpr level Whatever expr) <> ":\n"
271+ <> fromStmtBlock nextLevel stmts
252272
253273 Default stmts ->
254274 indent <> "default:\n"
255− <> fromStmtBlock (deeper indent) stmts
275+ <> fromStmtBlock nextLevel stmts
256276
257277
258278
259279-- VAR DECLS
260280
261281
262−varToBuilder :: Builder -> (Name, Expr) -> Builder
263−varToBuilder indent (name, expr) =
264− Name.toBuilder name <> " = " <> snd (fromExpr indent Whatever expr)
282+varToBuilder :: Level -> (Name, Expr) -> Builder
283+varToBuilder level (name, expr) =
284+ Name.toBuilder name <> " = " <> snd (fromExpr level Whatever expr)
265285
266286
267287
@@ -299,23 +319,23 @@ parensFor grouping builder =
299319 builder
300320
301321
302−fromExpr :: Builder -> Grouping -> Expr -> (Lines, Builder)
303−fromExpr indent grouping expression =
322+fromExpr :: Level -> Grouping -> Expr -> (Lines, Builder)
323+fromExpr level@(Level indent nextLevel@(Level deeperIndent _)) grouping expression =
304324 case expression of
305325 String string ->
306− (One, "'" <> string <> "'")
326+ ( One, "'" <> string <> "'" )
307327
308328 Float float ->
309− (One, float)
329+ ( One, float )
310330
311331 Int n ->
312− (One, B.intDec n)
332+ ( One, B.intDec n )
313333
314334 Bool bool ->
315− (One, if bool then "true" else "false")
335+ ( One, if bool then "true" else "false" )
316336
317337 Null ->
318− (One, "null")
338+ ( One, "null" )
319339
320340 Json json ->
321341 ( One, Json.encodeUgly json )
@@ -323,12 +343,12 @@ fromExpr indent grouping expression =
323343 Array exprs ->
324344 (,) Many $
325345 let
326− (anyMany, builders) = linesMap (fromExpr indent Whatever) exprs
346+ (anyMany, builders) = linesMap (fromExpr level Whatever) exprs
327347 in
328348 if anyMany then
329349 "[\n"
330− <> deeper indent
331− <> commaNewlineSep indent builders
350+ <> deeperIndent
351+ <> commaNewlineSep level builders
332352 <> "\n" <> indent <> "]"
333353 else
334354 "[" <> commaSep builders <> "]"
@@ -336,29 +356,28 @@ fromExpr indent grouping expression =
336356 Object fields ->
337357 (,) Many $
338358 let
339− deeperIndent = deeper indent
340− (anyMany, builders) = linesMap (fromField deeperIndent) fields
359+ (anyMany, builders) = linesMap (fromField nextLevel) fields
341360 in
342361 if anyMany then
343362 "{\n"
344363 <> deeperIndent
345− <> commaNewlineSep indent builders
364+ <> commaNewlineSep level builders
346365 <> "\n" <> indent <> "}"
347366 else
348367 "{" <> commaSep builders <> "}"
349368
350369 Ref name ->
351− (One, Name.toBuilder name)
370+ ( One, Name.toBuilder name )
352371
353372 Access expr field ->
354− makeDot indent expr field
373+ makeDot level expr field
355374
356375 Index expr bracketedExpr ->
357− makeBracketed indent expr bracketedExpr
376+ makeBracketed level expr bracketedExpr
358377
359378 Prefix op expr ->
360379 let
361− (lines, builder) = fromExpr indent Atomic expr
380+ (lines, builder) = fromExpr level Atomic expr
362381 in
363382 ( lines
364383 , parensFor grouping (fromPrefix op <> builder)
@@ -366,8 +385,8 @@ fromExpr indent grouping expression =
366385
367386 Infix op leftExpr rightExpr ->
368387 let
369− (leftLines , left ) = fromExpr indent Atomic leftExpr
370− (rightLines, right) = fromExpr indent Atomic rightExpr
388+ (leftLines , left ) = fromExpr level Atomic leftExpr
389+ (rightLines, right) = fromExpr level Atomic rightExpr
371390 in
372391 ( merge leftLines rightLines
373392 , parensFor grouping (left <> fromInfix op <> right)
@@ -375,9 +394,9 @@ fromExpr indent grouping expression =
375394
376395 If condExpr thenExpr elseExpr ->
377396 let
378− condB = snd (fromExpr indent Atomic condExpr)
379− thenB = snd (fromExpr indent Atomic thenExpr)
380− elseB = snd (fromExpr indent Atomic elseExpr)
397+ condB = snd (fromExpr level Atomic condExpr)
398+ thenB = snd (fromExpr level Atomic thenExpr)
399+ elseB = snd (fromExpr level Atomic elseExpr)
381400 in
382401 ( Many
383402 , parensFor grouping (condB <> " ? " <> thenB <> " : " <> elseB)
@@ -385,8 +404,8 @@ fromExpr indent grouping expression =
385404
386405 Assign lValue expr ->
387406 let
388− (leftLines , left ) = fromLValue indent lValue
389− (rightLines, right) = fromExpr indent Whatever expr
407+ (leftLines , left ) = fromLValue level lValue
408+ (rightLines, right) = fromExpr level Whatever expr
390409 in
391410 ( merge leftLines rightLines
392411 , parensFor grouping (left <> " = " <> right)
@@ -395,12 +414,11 @@ fromExpr indent grouping expression =
395414 Call function args ->
396415 (,) Many $
397416 let
398− deeperIndent = deeper indent
399− funcB = snd (fromExpr indent Atomic function)
400− (anyMany, argsB) = linesMap (fromExpr deeperIndent Whatever) args
417+ (_ , funcB) = fromExpr level Atomic function
418+ (anyMany, argsB) = linesMap (fromExpr nextLevel Whatever) args
401419 in
402420 if anyMany then
403− funcB <> "(\n" <> deeperIndent <> commaNewlineSep indent argsB <> ")"
421+ funcB <> "(\n" <> deeperIndent <> commaNewlineSep level argsB <> ")"
404422 else
405423 funcB <> "(" <> commaSep argsB <> ")"
406424
@@ -408,7 +426,7 @@ fromExpr indent grouping expression =
408426 (,) Many $
409427 "function " <> maybe mempty Name.toBuilder maybeName <> "(" <> commaSep (map Name.toBuilder args) <> ") {\n"
410428 <>
411− fromStmtBlock (deeper indent) stmts
429+ fromStmtBlock nextLevel stmts
412430 <>
413431 indent <> "}"
414432
@@ -417,10 +435,10 @@ fromExpr indent grouping expression =
417435-- FIELDS
418436
419437
420−fromField :: Builder -> (Name, Expr) -> (Lines, Builder)
421−fromField indent (field, expr) =
438+fromField :: Level -> (Name, Expr) -> (Lines, Builder)
439+fromField level (field, expr) =
422440 let
423− (lines, builder) = fromExpr indent Whatever expr
441+ (lines, builder) = fromExpr level Whatever expr
424442 in
425443 ( lines
426444 , Name.toBuilder field <> ": " <> builder
@@ -431,32 +449,32 @@ fromField indent (field, expr) =
431449-- VALUES
432450
433451
434−fromLValue :: Builder -> LValue -> (Lines, Builder)
435−fromLValue indent lValue =
452+fromLValue :: Level -> LValue -> (Lines, Builder)
453+fromLValue level lValue =
436454 case lValue of
437455 LRef name ->
438456 (One, Name.toBuilder name)
439457
440458 LDot expr field ->
441− makeDot indent expr field
459+ makeDot level expr field
442460
443461 LBracket expr bracketedExpr ->
444− makeBracketed indent expr bracketedExpr
462+ makeBracketed level expr bracketedExpr
445463
446464
447−makeDot :: Builder -> Expr -> Name -> (Lines, Builder)
448−makeDot indent expr field =
465+makeDot :: Level -> Expr -> Name -> (Lines, Builder)
466+makeDot level expr field =
449467 let
450− (lines, builder) = fromExpr indent Atomic expr
468+ (lines, builder) = fromExpr level Atomic expr
451469 in
452470 (lines, builder <> "." <> Name.toBuilder field)
453471
454472
455−makeBracketed :: Builder -> Expr -> Expr -> (Lines, Builder)
456−makeBracketed indent expr bracketedExpr =
473+makeBracketed :: Level -> Expr -> Expr -> (Lines, Builder)
474+makeBracketed level expr bracketedExpr =
457475 let
458− (lines , builder ) = fromExpr indent Atomic expr
459− (bracketedLines, bracketedBuilder) = fromExpr indent Whatever bracketedExpr
476+ (lines , builder ) = fromExpr level Atomic expr
477+ (bracketedLines, bracketedBuilder) = fromExpr level Whatever bracketedExpr
460478 in
461479 ( merge lines bracketedLines
462480 , builder <> "[" <> bracketedBuilder <> "]"