git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Create a Javascript AST type, and separate generation and pretty printing.
commit1afca17e969fb10aad28fb3ea7c2f273fd7e383d authorPhil Freeman <paf31@cantab.net> dateFri 1 Nov 2013, 17:14 (13 years ago) parent8443966
7 files changed+279−191
purescript.cabal+15−25 src/Language/PureScript/CodeGen/JS.hs+72−164 src/Language/PureScript/CodeGen/JS/AST.hs+45 src/Language/PureScript/Pretty.hs+1 src/Language/PureScript/Pretty/JS.hs+144 src/Language/PureScript/Pretty/Values.hs+1−1 src/Main.hs+1−1
purescript.cabal+15−25
@@ -1,5 +1,5 @@
11name: purescript
2−version: 0.1.0
2+version: 0.1.1
33cabal-version: >=1.8
44build-type: Simple
55license: MIT
@@ -9,37 +9,27 @@ maintainer: Phil Freeman <paf31@cantab.net>
99stability: experimental
1010synopsis: PureScript Programming Language Compiler
1111description: A small compile-to-JS language with extensible records and type-safe blocks
12+category: Language
1213author: Phil Freeman <paf31@cantab.net>
1314data-dir: ""
14−category: Language
1515
1616library
1717 build-depends: base >=4 && <5, syb -any, cmdtheline -any,
1818 containers -any, mtl -any, transformers -any, parsec -any,
1919 utf8-string -any
20− exposed-modules: Main
21− Language.PureScript
22− Language.PureScript.Declarations
23− Language.PureScript.Names
24− Language.PureScript.Types
25− Language.PureScript.Values
26− Language.PureScript.Kinds
27− Language.PureScript.Pretty
28− Language.PureScript.Pretty.Common
29− Language.PureScript.Pretty.Values
30− Language.PureScript.Pretty.Types
31− Language.PureScript.Pretty.Kinds
32− Language.PureScript.CodeGen
33− Language.PureScript.CodeGen.Externs
34− Language.PureScript.CodeGen.JS
35− Language.PureScript.CodeGen.Monad
36− Language.PureScript.Parser
37− Language.PureScript.Parser.Common
20+ exposed-modules: Language.PureScript.Pretty.JS
21+ Language.PureScript.CodeGen.JS.AST Main Language.PureScript
22+ Language.PureScript.Declarations Language.PureScript.Names
23+ Language.PureScript.Types Language.PureScript.Values
24+ Language.PureScript.Kinds Language.PureScript.Pretty
25+ Language.PureScript.Pretty.Common Language.PureScript.Pretty.Values
26+ Language.PureScript.Pretty.Types Language.PureScript.Pretty.Kinds
27+ Language.PureScript.CodeGen Language.PureScript.CodeGen.Externs
28+ Language.PureScript.CodeGen.JS Language.PureScript.CodeGen.Monad
29+ Language.PureScript.Parser Language.PureScript.Parser.Common
3830 Language.PureScript.Parser.Declarations
39− Language.PureScript.Parser.Types
40− Language.PureScript.Parser.Values
41− Language.PureScript.Parser.State
42− Language.PureScript.Parser.Kinds
31+ Language.PureScript.Parser.Types Language.PureScript.Parser.Values
32+ Language.PureScript.Parser.State Language.PureScript.Parser.Kinds
4333 Language.PureScript.TypeChecker
4434 Language.PureScript.TypeChecker.Kinds
4535 Language.PureScript.TypeChecker.Monad
@@ -48,7 +38,6 @@ library
4838 exposed: True
4939 buildable: True
5040 hs-source-dirs: src
51− other-modules:
5241
5342executable psc
5443 build-depends: base >=4 && <5, cmdtheline -any, containers -any,
@@ -57,6 +46,7 @@ executable psc
5746 main-is: Main.hs
5847 buildable: True
5948 hs-source-dirs: src
49+ other-modules:
6050
6151test-suite tests
6252 build-depends: base >=4 && <5, syb -any, directory -any,
src/Language/PureScript/CodeGen/JS.hs+72−164
@@ -13,6 +13,7 @@
1313-----------------------------------------------------------------------------
1414
1515module Language.PureScript.CodeGen.JS (
16+ module AST,
1617 declToJs
1718) where
1819
@@ -20,7 +21,7 @@ import Data.Char
2021import Data.Maybe (fromMaybe)
2122import Data.List (intercalate)
2223import qualified Control.Arrow as A
23−import Control.Arrow ((<+>))
24+import Control.Arrow ((<+>), second)
2425import Control.Monad (forM)
2526import Control.Applicative
2627
@@ -30,203 +31,110 @@ import Language.PureScript.Names
3031import Language.PureScript.Declarations
3132import Language.PureScript.Pretty.Common
3233import Language.PureScript.CodeGen.Monad
34+import Language.PureScript.CodeGen.JS.AST as AST
3335
34−declToJs :: Declaration -> Maybe String
35−declToJs (ValueDeclaration ident (Abs args ret)) = Just $ "function " ++ identToJs ident ++ "(" ++ intercalate "," (map identToJs args) ++ ") { return " ++ valueToJs ret ++ "; }"
36−declToJs (ValueDeclaration ident val) = Just $ "var " ++ identToJs ident ++ " = " ++ valueToJs val ++ ";"
36+declToJs :: Declaration -> Maybe [JS]
37+declToJs (ValueDeclaration ident (Abs args ret)) = Just [JSFunction (Just ident) args (JSBlock [JSReturn (valueToJs ret)])]
38+declToJs (ValueDeclaration ident val) = Just [JSVariableIntroduction ident (valueToJs val)]
3739declToJs (DataDeclaration _ _ ctors) =
38− Just $ flip concatMap ctors $ \(ctor, maybeTy) ->
40+ Just $ flip map ctors $ \(ctor, maybeTy) ->
3941 case maybeTy of
40− Nothing -> "var " ++ ctor ++ " = { ctor: '" ++ ctor ++ "' };"
41− Just _ -> "var " ++ ctor ++ " = function (value) { return { ctor: '" ++ ctor ++ "', value: value }; };"
42+ Nothing -> JSVariableIntroduction (Ident ctor) (JSObjectLiteral [ ("ctor", JSStringLiteral ctor) ])
43+ Just _ -> JSFunction (Just (Ident ctor)) [Ident "value"]
44+ (JSBlock [JSReturn
45+ (JSObjectLiteral [ ("ctor", JSStringLiteral ctor)
46+ , ("value", JSVar (Ident "value")) ])])
4247declToJs _ = Nothing
4348
44−literals :: Pattern Value String
45−literals = Pattern $ A.Kleisli match
46− where
47− match (NumericLiteral n) = Just $ either show show n
48− match (StringLiteral s) = Just $ show s
49− match (BooleanLiteral True) = Just "true"
50− match (BooleanLiteral False) = Just "false"
51− match (ArrayLiteral xs) = Just $ "[" ++ intercalate "," (map valueToJs xs) ++ "]"
52− match (ObjectLiteral ps) = Just $ "{" ++ intercalate "," (map objectPropertyToJs ps) ++ "}"
53− match (ObjectUpdate o ps) = Just $ "Object.extend("
54− ++ valueToJs o ++ ", { "
55− ++ intercalate ", " (map objectPropertyToJs ps) ++ " }"
56− match (Constructor name) = Just name
57− match (Block sts) = Just $ "(function () {" ++ intercalate ";" (map statementToJs sts) ++ "})()"
58− match (Case value binders) = Just $ "(" ++ runGen (bindersToJs binders) ++ ")(" ++ valueToJs value ++ ")"
59− where
60− bindersToJs :: [(Binder, Value)] -> Gen String
61− bindersToJs binders = do
62− valName <- fresh
63− jss <- forM binders $ \(binder, result) -> do
64− let js = valueToJs result
65− binderToJs valName ("return " ++ js ++ ";") binder
66− return $ "function (" ++ valName ++ ") {" ++ concat jss ++ "throw \"Failed pattern match\"; }"
67− match (Var ident) = Just (identToJs ident)
68− match _ = Nothing
69−
70−ifThenElse :: Pattern Value ((Value, Value), Value)
71−ifThenElse = Pattern $ A.Kleisli match
72− where
73− match (IfThenElse cond th el) = Just ((th, el), cond)
74− match _ = Nothing
75−
76−accessor :: Pattern Value (String, Value)
77−accessor = Pattern $ A.Kleisli match
78− where
79− match (Accessor prop val) = Just (prop, val)
80− match _ = Nothing
81−
82−indexer :: Pattern Value (String, Value)
83−indexer = Pattern $ A.Kleisli match
84− where
85− match (Indexer index val) = Just (valueToJs index, val)
86− match _ = Nothing
87−
88−app :: Pattern Value (String, Value)
89−app = Pattern $ A.Kleisli match
90− where
91− match (App val args) = Just (intercalate "," (map valueToJs args), val)
92− match _ = Nothing
93−
94−lam :: Pattern Value ([String], Value)
95−lam = Pattern $ A.Kleisli match
96− where
97− match (Abs args val) = Just (map identToJs args, val)
98− match _ = Nothing
99−
100−unary :: UnaryOperator -> String -> Operator Value String
101−unary op str = Wrap pattern (++)
102− where
103− pattern :: Pattern Value (String, Value)
104− pattern = Pattern $ A.Kleisli match
105− where
106− match (Unary op' val) | op' == op = Just (str, val)
107− match _ = Nothing
108−
109−binary :: BinaryOperator -> String -> Operator Value String
110−binary op str = AssocR pattern (\v1 v2 -> v1 ++ " " ++ str ++ " " ++ v2)
111− where
112− pattern :: Pattern Value (Value, Value)
113− pattern = Pattern $ A.Kleisli match
114− where
115− match (Binary op' v1 v2) | op' == op = Just (v1, v2)
116− match _ = Nothing
117−
118−valueToJs :: Value -> String
119−valueToJs = fromMaybe (error "Incomplete pattern") . pattern matchValue
120− where
121− matchValue :: Pattern Value String
122− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
123− operators :: OperatorTable Value String
124− operators =
125− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
126− , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
127− , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]
128− , [ Split lam $ \args val -> "function (" ++ intercalate "," args ++ ") { return " ++ valueToJs val ++ "; }" ]
129− , [ Wrap ifThenElse $ \(th, el) cond -> cond ++ " ? " ++ valueToJs th ++ " : " ++ valueToJs el ]
130− , [ binary LessThan "<" ]
131− , [ binary LessThanOrEqualTo "<=" ]
132− , [ binary GreaterThan ">" ]
133− , [ binary GreaterThanOrEqualTo ">=" ]
134− , [ unary Not "!" ]
135− , [ unary BitwiseNot "~" ]
136− , [ unary Negate "-" ]
137− , [ binary Multiply "*" ]
138− , [ binary Divide "/" ]
139− , [ binary Modulus "%" ]
140− , [ binary Concat "+" ]
141− , [ binary Add "+" ]
142− , [ binary Subtract "-" ]
143− , [ binary ShiftLeft "<<" ]
144− , [ binary ShiftRight ">>" ]
145− , [ binary ZeroFillShiftRight ">>>" ]
146− , [ binary EqualTo "===" ]
147− , [ binary NotEqualTo "!==" ]
148− , [ binary BitwiseAnd "&" ]
149− , [ binary BitwiseXor "^" ]
150− , [ binary BitwiseOr "|" ]
151− , [ binary And "&&" ]
152− , [ binary Or "||" ]
153− ]
154−
155−binderToJs :: String -> String -> Binder -> Gen String
49+valueToJs :: Value -> JS
50+valueToJs (NumericLiteral n) = JSNumericLiteral n
51+valueToJs (StringLiteral s) = JSStringLiteral s
52+valueToJs (BooleanLiteral b) = JSBooleanLiteral b
53+valueToJs (ArrayLiteral xs) = JSArrayLiteral (map valueToJs xs)
54+valueToJs (ObjectLiteral ps) = JSObjectLiteral (map (second valueToJs) ps)
55+valueToJs (ObjectUpdate o ps) = JSApp (JSAccessor "extend" (JSVar (Ident "Object"))) [ valueToJs o, JSObjectLiteral (map (second valueToJs) ps)]
56+valueToJs (Constructor name) = JSVar (Ident name)
57+valueToJs (Block sts) = JSApp (JSFunction Nothing [] (JSBlock (map statementToJs sts))) []
58+valueToJs (Case value binders) = runGen (bindersToJs binders (valueToJs value))
59+valueToJs (IfThenElse cond th el) = JSConditional (valueToJs cond) (valueToJs th) (valueToJs el)
60+valueToJs (Accessor prop val) = JSAccessor prop (valueToJs val)
61+valueToJs (Indexer index val) = JSIndexer (valueToJs index) (valueToJs val)
62+valueToJs (App val args) = JSApp (valueToJs val) (map valueToJs args)
63+valueToJs (Abs args val) = JSFunction Nothing args (JSBlock [JSReturn (valueToJs val)])
64+valueToJs (Unary op val) = JSUnary op (valueToJs val)
65+valueToJs (Binary op v1 v2) = JSBinary op (valueToJs v1) (valueToJs v2)
66+valueToJs (Var ident) = JSVar ident
67+valueToJs (TypedValue val _) = valueToJs val
68+
69+bindersToJs :: [(Binder, Value)] -> JS -> Gen JS
70+bindersToJs binders val = do
71+ valName <- fresh
72+ jss <- forM binders $ \(binder, result) -> binderToJs valName [JSReturn (valueToJs result)] binder
73+ return $ JSApp (JSFunction Nothing [Ident valName] (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
74+ [val]
75+
76+binderToJs :: String -> [JS] -> Binder -> Gen [JS]
15677binderToJs varName done NullBinder = return done
15778binderToJs varName done (StringBinder str) =
158− return $ "if (" ++ varName ++ " === \"" ++ str ++ "\") {" ++ done ++ " }"
79+ return [JSIfElse (JSBinary EqualTo (JSVar (Ident varName)) (JSStringLiteral str)) done Nothing]
15980binderToJs varName done (NumberBinder num) =
160− return $ "if (" ++ varName ++ " === " ++ either show show num ++ ") {" ++ done ++ " }"
81+ return [JSIfElse (JSBinary EqualTo (JSVar (Ident varName)) (JSNumericLiteral num)) done Nothing]
16182binderToJs varName done (BooleanBinder True) =
162− return $ "if (" ++ varName ++ ") {" ++ done ++ " }"
83+ return [JSIfElse (JSVar (Ident varName)) done Nothing]
16384binderToJs varName done (BooleanBinder False) =
164− return $ "if (!" ++ varName ++ ") {" ++ done ++ " }"
85+ return [JSIfElse (JSUnary Not (JSVar (Ident varName))) done Nothing]
16586binderToJs varName done (VarBinder ident) =
166− return $ "var " ++ identToJs ident ++ " = " ++ varName ++ "; " ++ done
87+ return (JSVariableIntroduction ident (JSVar (Ident varName)) : done)
16788binderToJs varName done (NullaryBinder ctor) =
168− return $ "if (" ++ varName ++ ".ctor === \"" ++ ctor ++ "\") { " ++ done ++ " }"
89+ return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar (Ident varName))) (JSStringLiteral ctor)) done Nothing]
16990binderToJs varName done (UnaryBinder ctor b) = do
17091 value <- fresh
17192 js <- binderToJs value done b
172− return $ "if (" ++ varName ++ ".ctor === \"" ++ ctor ++ "\") { " ++ "var " ++ value ++ " = " ++ varName ++ ".value; " ++ js ++ " }"
93+ return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar (Ident varName))) (JSStringLiteral ctor)) (JSVariableIntroduction (Ident value) (JSAccessor "value" (JSVar (Ident varName))) : js) Nothing]
17394binderToJs varName done (ObjectBinder bs) = go done bs
17495 where
96+ go :: [JS] -> [(String, Binder)] -> Gen [JS]
17597 go done [] = return done
17698 go done ((prop, binder):bs) = do
17799 propVar <- fresh
178100 done' <- go done bs
179101 js <- binderToJs propVar done' binder
180− return $ "var " ++ propVar ++ " = " ++ varName ++ "." ++ prop ++ ";" ++ js
102+ return (JSVariableIntroduction (Ident propVar) (JSAccessor prop (JSVar (Ident varName))) : js)
181103binderToJs varName done (ArrayBinder bs rest) = do
182104 js <- go done rest 0 bs
183− return $ "if (" ++ varName ++ ".length " ++ cmp ++ " " ++ show (length bs) ++ ") { " ++ js ++ " }"
105+ return [JSIfElse (JSBinary cmp (JSAccessor "length" (JSVar (Ident varName))) (JSNumericLiteral (Left (fromIntegral $ length bs)))) js Nothing]
184106 where
185− cmp = maybe "===" (const ">=") rest
107+ cmp :: BinaryOperator
108+ cmp = maybe EqualTo (const GreaterThanOrEqualTo) rest
109+ go :: [JS] -> Maybe Binder -> Integer -> [Binder] -> Gen [JS]
186110 go done Nothing _ [] = return done
187111 go done (Just binder) index [] = do
188112 restVar <- fresh
189113 js <- binderToJs restVar done binder
190− return $ "var " ++ restVar ++ " = " ++ varName ++ ".slice(" ++ show index ++ "); " ++ js
114+ return (JSVariableIntroduction (Ident restVar) (JSApp (JSAccessor "slice" (JSVar (Ident varName))) [JSNumericLiteral (Left index)]) : js)
191115 go done rest index (binder:bs) = do
192116 elVar <- fresh
193117 done' <- go done rest (index + 1) bs
194118 js <- binderToJs elVar done' binder
195− return $ "var " ++ elVar ++ " = " ++ varName ++ "[" ++ show index ++ "]; " ++ js
119+ return (JSVariableIntroduction (Ident elVar) (JSIndexer (JSNumericLiteral (Left index)) (JSVar (Ident varName))) : js)
196120binderToJs varName done (NamedBinder ident binder) = do
197121 js <- binderToJs varName done binder
198− return $ "var " ++ identToJs ident ++ " = " ++ varName ++ "; " ++ js
122+ return (JSVariableIntroduction ident (JSVar (Ident varName)) : js)
199123binderToJs varName done (GuardedBinder cond binder) = binderToJs varName done' binder
200124 where
201− done' = "if (" ++ valueToJs cond ++ ") { " ++ done ++ "}"
202−
203−objectPropertyToJs :: (String, Value) -> String
204−objectPropertyToJs (key, value) = key ++ ": " ++ valueToJs value
205−
206−statementToJs :: Statement -> String
207−statementToJs (VariableIntroduction ident value) = "var " ++ identToJs ident ++ " = " ++ valueToJs value
208−statementToJs (Assignment target value) = identToJs target ++ " = " ++ valueToJs value
209−statementToJs (While cond sts) = "while ("
210− ++ valueToJs cond ++ ") {"
211− ++ intercalate ";" (map statementToJs sts) ++ "}"
212−statementToJs (For ident start end sts) = "for (" ++
213− identToJs ident ++ " = " ++ valueToJs start ++ ";"
214− ++ identToJs ident ++ " < " ++ valueToJs end ++ ";"
215− ++ identToJs ident ++ "++) {"
216− ++ intercalate ";" (map statementToJs sts) ++ "}"
217−statementToJs (ForEach ident arr sts) = valueToJs arr
218− ++ ".forEach(function(" ++ identToJs ident ++ ") {"
219− ++ intercalate ";" (map statementToJs sts) ++ "})"
220−statementToJs (If ifst) = ifStatementToJs ifst
221−statementToJs (Return value) = "return " ++ valueToJs value
222−
223−ifStatementToJs :: IfStatement -> String
224−ifStatementToJs (IfStatement cond thens elst) =
225− "if ("
226− ++ valueToJs cond ++ ") {"
227− ++ intercalate ";" (map statementToJs thens) ++ "}"
228− ++ maybe "" elseStatementToJs elst
229−
230−elseStatementToJs :: ElseStatement -> String
231−elseStatementToJs (Else sts) = " else {" ++ intercalate ";" (map statementToJs sts) ++ "}"
232−elseStatementToJs (ElseIf ifst) = " else " ++ ifStatementToJs ifst
125+ done' = [JSIfElse (valueToJs cond) done Nothing]
126+
127+statementToJs :: Statement -> JS
128+statementToJs (VariableIntroduction ident value) = JSVariableIntroduction ident (valueToJs value)
129+statementToJs (Assignment target value) = JSAssignment target (valueToJs value)
130+statementToJs (While cond sts) = JSWhile (valueToJs cond) (map statementToJs sts)
131+statementToJs (For ident start end sts) = JSFor ident (valueToJs start) (valueToJs end) (map statementToJs sts)
132+statementToJs (ForEach ident arr sts) = JSApp (JSAccessor "forEach" (valueToJs arr)) [JSFunction Nothing [ident] (JSBlock (map statementToJs sts))]
133+statementToJs (If ifst) = ifToJs ifst
134+ where
135+ ifToJs :: IfStatement -> JS
136+ ifToJs (IfStatement cond thens elses) = JSIfElse (valueToJs cond) (map statementToJs thens) (fmap elseToJs elses)
137+ elseToJs :: ElseStatement -> JS
138+ elseToJs (Else sts) = JSBlock (map statementToJs sts)
139+ elseToJs (ElseIf ifst) = ifToJs ifst
140+statementToJs (Return value) = JSReturn (valueToJs value)
src/Language/PureScript/CodeGen/JS/AST.hsnew file+45
@@ -0,0 +1,45 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.CodeGen.JS.AST
4+-- Copyright : (c) Phil Freeman 2013
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- |
12+--
13+-----------------------------------------------------------------------------
14+
15+{-# LANGUAGE DeriveDataTypeable #-}
16+
17+module Language.PureScript.CodeGen.JS.AST where
18+
19+import Language.PureScript.Names
20+import Language.PureScript.Values
21+
22+import Data.Data
23+
24+data JS
25+ = JSNumericLiteral (Either Integer Double)
26+ | JSStringLiteral String
27+ | JSBooleanLiteral Bool
28+ | JSUnary UnaryOperator JS
29+ | JSBinary BinaryOperator JS JS
30+ | JSArrayLiteral [JS]
31+ | JSIndexer JS JS
32+ | JSObjectLiteral [(String, JS)]
33+ | JSAccessor String JS
34+ | JSFunction (Maybe Ident) [Ident] JS
35+ | JSApp JS [JS]
36+ | JSVar Ident
37+ | JSConditional JS JS JS
38+ | JSBlock [JS]
39+ | JSVariableIntroduction Ident JS
40+ | JSAssignment Ident JS
41+ | JSWhile JS [JS]
42+ | JSFor Ident JS JS [JS]
43+ | JSIfElse JS [JS] (Maybe JS)
44+ | JSReturn JS
45+ | JSThrow JS deriving (Show, Data, Typeable)
src/Language/PureScript/Pretty.hs+1
@@ -17,6 +17,7 @@ module Language.PureScript.Pretty (module P) where
1717import Language.PureScript.Pretty.Kinds as P
1818import Language.PureScript.Pretty.Values as P
1919import Language.PureScript.Pretty.Types as P
20+import Language.PureScript.Pretty.JS as P
2021
2122
2223
src/Language/PureScript/Pretty/JS.hsnew file+144
@@ -0,0 +1,144 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.Pretty.JS
4+-- Copyright : (c) Phil Freeman 2013
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- |
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.Pretty.JS (
16+ prettyPrintJS
17+) where
18+
19+import Language.PureScript.Names
20+import Language.PureScript.Values
21+import Language.PureScript.Pretty.Common
22+import Language.PureScript.CodeGen.JS.AST
23+
24+import Data.List
25+import Data.Maybe (fromMaybe)
26+import qualified Control.Arrow as A
27+import Control.Arrow ((***), (<+>), first, second)
28+
29+literals :: Pattern JS String
30+literals = Pattern $ A.Kleisli match
31+ where
32+ match (JSNumericLiteral n) = Just $ either show show n
33+ match (JSStringLiteral s) = Just $ show s
34+ match (JSBooleanLiteral True) = Just "true"
35+ match (JSBooleanLiteral False) = Just "false"
36+ match (JSArrayLiteral xs) = Just $ "[" ++ intercalate ", " (map prettyPrintJS xs) ++ "]"
37+ match (JSObjectLiteral ps) = Just $ "{ " ++ intercalate ", " (map (\(key, value) -> key ++ ": " ++ prettyPrintJS value) ps) ++ " }"
38+ match (JSBlock sts) = Just $ "{ " ++ intercalate "; " (map prettyPrintJS sts) ++ " }"
39+ match (JSVar ident) = Just (identToJs ident)
40+ match (JSVariableIntroduction ident value) = Just $ "var " ++ identToJs ident ++ " = " ++ prettyPrintJS value
41+ match (JSAssignment target value) = Just $ identToJs target ++ " = " ++ prettyPrintJS value
42+ match (JSWhile cond sts) = Just $ "while ("
43+ ++ prettyPrintJS cond ++ ") { "
44+ ++ intercalate "; " (map prettyPrintJS sts) ++ " }"
45+ match (JSFor ident start end sts) = Just $ "for ("
46+ ++ identToJs ident ++ " = " ++ prettyPrintJS start ++ "; "
47+ ++ identToJs ident ++ " < " ++ prettyPrintJS end ++ "; "
48+ ++ identToJs ident ++ "++) { "
49+ ++ intercalate "; " (map prettyPrintJS sts) ++ " }"
50+ match (JSIfElse cond thens elses) = Just $ "if ("
51+ ++ prettyPrintJS cond ++ ") { "
52+ ++ intercalate "; " (map prettyPrintJS thens) ++ " }"
53+ ++ maybe "" ((" else " ++) . prettyPrintJS) elses
54+ match (JSReturn value) = Just $ "return " ++ prettyPrintJS value
55+ match (JSThrow value) = Just $ "throw " ++ prettyPrintJS value
56+ match _ = Nothing
57+
58+conditional :: Pattern JS ((JS, JS), JS)
59+conditional = Pattern $ A.Kleisli match
60+ where
61+ match (JSConditional cond th el) = Just ((th, el), cond)
62+ match _ = Nothing
63+
64+accessor :: Pattern JS (String, JS)
65+accessor = Pattern $ A.Kleisli match
66+ where
67+ match (JSAccessor prop val) = Just (prop, val)
68+ match _ = Nothing
69+
70+indexer :: Pattern JS (String, JS)
71+indexer = Pattern $ A.Kleisli match
72+ where
73+ match (JSIndexer index val) = Just (prettyPrintJS index, val)
74+ match _ = Nothing
75+
76+lam :: Pattern JS ((Maybe Ident, [Ident]), JS)
77+lam = Pattern $ A.Kleisli match
78+ where
79+ match (JSFunction name args ret) = Just ((name, args), ret)
80+ match _ = Nothing
81+
82+app :: Pattern JS (String, JS)
83+app = Pattern $ A.Kleisli match
84+ where
85+ match (JSApp val args) = Just (intercalate "," (map prettyPrintJS args), val)
86+ match _ = Nothing
87+
88+unary :: UnaryOperator -> String -> Operator JS String
89+unary op str = Wrap pattern (++)
90+ where
91+ pattern :: Pattern JS (String, JS)
92+ pattern = Pattern $ A.Kleisli match
93+ where
94+ match (JSUnary op' val) | op' == op = Just (str, val)
95+ match _ = Nothing
96+
97+binary :: BinaryOperator -> String -> Operator JS String
98+binary op str = AssocR pattern (\v1 v2 -> v1 ++ " " ++ str ++ " " ++ v2)
99+ where
100+ pattern :: Pattern JS (JS, JS)
101+ pattern = Pattern $ A.Kleisli match
102+ where
103+ match (JSBinary op' v1 v2) | op' == op = Just (v1, v2)
104+ match _ = Nothing
105+
106+prettyPrintJS :: JS -> String
107+prettyPrintJS = fromMaybe (error "Incomplete pattern") . pattern matchValue
108+ where
109+ matchValue :: Pattern JS String
110+ matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
111+ operators :: OperatorTable JS String
112+ operators =
113+ OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
114+ , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
115+ , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]
116+ , [ Wrap lam $ \(name, args) ret -> "function "
117+ ++ maybe "" identToJs name
118+ ++ "(" ++ intercalate "," (map identToJs args) ++ ") "
119+ ++ ret ]
120+ , [ Wrap conditional $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintJS th ++ " : " ++ prettyPrintJS el ]
121+ , [ binary LessThan "<" ]
122+ , [ binary LessThanOrEqualTo "<=" ]
123+ , [ binary GreaterThan ">" ]
124+ , [ binary GreaterThanOrEqualTo ">=" ]
125+ , [ unary Not "!" ]
126+ , [ unary BitwiseNot "~" ]
127+ , [ unary Negate "-" ]
128+ , [ binary Multiply "*" ]
129+ , [ binary Divide "/" ]
130+ , [ binary Modulus "%" ]
131+ , [ binary Concat "+" ]
132+ , [ binary Add "+" ]
133+ , [ binary Subtract "-" ]
134+ , [ binary ShiftLeft "<<" ]
135+ , [ binary ShiftRight ">>" ]
136+ , [ binary ZeroFillShiftRight ">>>" ]
137+ , [ binary EqualTo "===" ]
138+ , [ binary NotEqualTo "!==" ]
139+ , [ binary BitwiseAnd "&" ]
140+ , [ binary BitwiseXor "^" ]
141+ , [ binary BitwiseOr "|" ]
142+ , [ binary And "&&" ]
143+ , [ binary Or "||" ]
144+ ]
src/Language/PureScript/Pretty/Values.hs+1−1
@@ -112,7 +112,7 @@ prettyPrintValue = fromMaybe (error "Incomplete pattern") . pattern matchValue
112112 , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
113113 , [ Wrap objectUpdate $ \ps val -> val ++ "{ " ++ intercalate ", " ps ++ " }" ]
114114 , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]
115− , [ Split lam $ \args val -> "function (" ++ intercalate "," args ++ ") { return " ++ prettyPrintValue val ++ "; }" ]
115+ , [ Split lam $ \args val -> "\\" ++ intercalate ", " args ++ " -> " ++ prettyPrintValue val ]
116116 , [ Wrap ifThenElse $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintValue th ++ " : " ++ prettyPrintValue el ]
117117 , [ binary LessThan "<" ]
118118 , [ binary LessThanOrEqualTo "<=" ]
src/Main.hs+1−1
@@ -40,7 +40,7 @@ compile inputFiles outputFile externsFile = do
4040 U.putStrLn typeError
4141 exitFailure
4242 Right (_, env) -> do
43− let js = intercalate "\n" $ mapMaybe declToJs decls
43+ let js = intercalate "; " . map prettyPrintJS . concat . mapMaybe (declToJs) $ decls
4444 case outputFile of
4545 Just path -> U.writeFile path js
4646 Nothing -> U.putStrLn js