@@ -5,7 +5,7 @@ module Generate.JavaScript.Expression
7import Control.Arrow (second)
7import Control.Arrow (second)
8−import Control.Monad.State (State, foldM)
8+import Control.Monad (foldM)
9import qualified Data.List as List
9import qualified Data.List as List
10import qualified Data.Map as Map
10import qualified Data.Map as Map
11import Data.Monoid ((<>))
11import Data.Monoid ((<>))
@@ -23,6 +23,7 @@ import qualified Generate.JavaScript.BuiltIn as BuiltIn
23import qualified Generate.JavaScript.Foreign as Foreign
23import qualified Generate.JavaScript.Foreign as Foreign
24import qualified Generate.JavaScript.Literal as Literal
24import qualified Generate.JavaScript.Literal as Literal
25import qualified Generate.JavaScript.Variable as Var
25import qualified Generate.JavaScript.Variable as Var
26+import Generate.JavaScript.Variable (Generator)
26import qualified Optimize.DecisionTree as DT
27import qualified Optimize.DecisionTree as DT
@@ -30,9 +31,11 @@ import qualified Optimize.DecisionTree as DT
30-- GENERATE DECLARATION
31-- GENERATE DECLARATION
33−generateDecl :: ModuleName.Canonical -> Text -> Opt.Def -> State Int [JS.Stmt]
34+generateDecl :: ModuleName.Canonical -> Text -> Opt.Def -> Generator JS.Stmt
34generateDecl home name def =
35generateDecl home name def =
36+ do jsName <- Var.getGlobalName (V.Global home name)
35− Var.defineGlobal home name <$> generateDef name def
37+ jsBody <- generateDef name def
38+ return $ JS.VarDeclStmt [ Help.varDecl jsName jsBody ]
@@ -44,12 +47,12 @@ data Code
44 | JsBlock [JS.Stmt]
47 | JsBlock [JS.Stmt]
47−jsExpr :: JS.Expr -> State Int Code
50+jsExpr :: JS.Expr -> Generator Code
48jsExpr exp =
51jsExpr exp =
49 return (JsExpr exp)
52 return (JsExpr exp)
52−jsBlock :: [JS.Stmt] -> State Int Code
55+jsBlock :: [JS.Stmt] -> Generator Code
53jsBlock exp =
56jsBlock exp =
54 return (JsBlock exp)
57 return (JsBlock exp)
@@ -98,22 +101,22 @@ toExpr code =
98-- EXPRESSIONS
101-- EXPRESSIONS
101−generateJsExpr :: Opt.Expr -> State Int JS.Expr
104+generateJsExpr :: Opt.Expr -> Generator JS.Expr
102generateJsExpr optExpr =
105generateJsExpr optExpr =
103 toExpr <$> generateCode optExpr
106 toExpr <$> generateCode optExpr
106−generateCode :: Opt.Expr -> State Int Code
109+generateCode :: Opt.Expr -> Generator Code
107generateCode expr =
110generateCode expr =
108 case expr of
111 case expr of
109 VarLocal name ->
112 VarLocal name ->
110 jsExpr $ Var.local name
113 jsExpr $ Var.local name
112 VarGlobal name ->
115 VarGlobal name ->
113− jsExpr $ Var.global name
116+ JsExpr <$> Var.global name
115 Literal lit ->
118 Literal lit ->
116− jsExpr (Literal.literal lit)
119+ JsExpr <$> Literal.literal lit
118 Access record field ->
121 Access record field ->
119 do jsRecord <- generateJsExpr record
122 do jsRecord <- generateJsExpr record
@@ -127,7 +130,7 @@ generateCode expr =
128 do jsRecord <- generateJsExpr record
131 do jsRecord <- generateJsExpr record
129 jsFields <- mapM fieldToJs fields
132 jsFields <- mapM fieldToJs fields
130− jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
133+ JsExpr <$> BuiltIn.recordUpdate jsRecord jsFields
132 Record fields ->
135 Record fields ->
@@ -173,7 +176,7 @@ generateCode expr =
174 List elements ->
177 List elements ->
175 do jsElements <- mapM generateJsExpr elements
178 do jsElements <- mapM generateJsExpr elements
176− jsExpr $ BuiltIn.list jsElements
179+ JsExpr <$> BuiltIn.list jsElements
178 Ctor tag members ->
181 Ctor tag members ->
@@ -191,39 +194,41 @@ generateCode expr =
191 jsExpr $ JS.DotRef jsDataExpr (JS.Id ("_" <> Text.pack (show index)))
194 jsExpr $ JS.DotRef jsDataExpr (JS.Id ("_" <> Text.pack (show index)))
193 Cmd moduleName _ ->
196 Cmd moduleName _ ->
194− jsExpr $ BuiltIn.effect moduleName
197+ JsExpr <$> BuiltIn.effect moduleName
196 Sub moduleName _ ->
199 Sub moduleName _ ->
197− jsExpr $ BuiltIn.effect moduleName
200+ JsExpr <$> BuiltIn.effect moduleName
199 OutgoingPort name tipe ->
202 OutgoingPort name tipe ->
200− jsExpr $ BuiltIn.outgoingPort name (Foreign.encode tipe)
203+ JsExpr <$> BuiltIn.outgoingPort name (Foreign.encode tipe)
202 IncomingPort name tipe ->
205 IncomingPort name tipe ->
203 do jsDecoder <- generateJsExpr (Foreign.decode tipe)
206 do jsDecoder <- generateJsExpr (Foreign.decode tipe)
204− jsExpr $ BuiltIn.incomingPort name jsDecoder
207+ JsExpr <$> BuiltIn.incomingPort name jsDecoder
206 Program kind body ->
209 Program kind body ->
207 generateProgram kind body
210 generateProgram kind body
209 GLShader src ->
212 GLShader src ->
213+ do string <- Literal.literal (L.Str src)
210− jsExpr $ JS.Object [(JS.StringProp "src", Literal.literal (L.Str src))]
214+ jsExpr $ JS.Object [(JS.StringProp "src", string)]
212 Crash home region maybeBranchProblem ->
216 Crash home region maybeBranchProblem ->
213 do maybeOptBranchProblem <- traverse generateJsExpr maybeBranchProblem
217 do maybeOptBranchProblem <- traverse generateJsExpr maybeBranchProblem
214− jsExpr $ BuiltIn.crash home region maybeOptBranchProblem
218+ JsExpr <$> BuiltIn.crash home region maybeOptBranchProblem
218-- PROGRAMS
222-- PROGRAMS
221−generateProgram :: Can.Main -> Opt.Expr -> State Int Code
225+generateProgram :: Can.Main -> Opt.Expr -> Generator Code
222generateProgram kind body =
226generateProgram kind body =
223 case kind of
227 case kind of
224 Can.VDom ->
228 Can.VDom ->
225 do html <- generateJsExpr body
229 do html <- generateJsExpr body
226− jsExpr (Var.staticProgram <| html)
230+ func <- BuiltIn.staticProgram
231+ jsExpr (func <| html)
228 Can.NoFlags ->
233 Can.NoFlags ->
229 do almostProgram <- generateJsExpr body
234 do almostProgram <- generateJsExpr body
@@ -239,13 +244,13 @@ generateProgram kind body =
239-- DEFINITIONS
244-- DEFINITIONS
242−generateLetDef :: (Text, Opt.Def) -> State Int JS.Stmt
247+generateLetDef :: (Text, Opt.Def) -> Generator JS.Stmt
243generateLetDef (name, def) =
248generateLetDef (name, def) =
244 do jsBody <- generateDef name def
249 do jsBody <- generateDef name def
245 return $ JS.VarDeclStmt [ Help.varDecl name jsBody ]
250 return $ JS.VarDeclStmt [ Help.varDecl name jsBody ]
248−generateDef :: Text -> Opt.Def -> State Int JS.Expr
253+generateDef :: Text -> Opt.Def -> Generator JS.Expr
249generateDef name def =
254generateDef name def =
250 case def of
255 case def of
251 Opt.TailDef argNames body ->
256 Opt.TailDef argNames body ->
@@ -255,7 +260,7 @@ generateDef name def =
255 generateJsExpr body
260 generateJsExpr body
258−generateTailFunction :: Text -> [Text] -> Opt.Expr -> State Int JS.Expr
263+generateTailFunction :: Text -> [Text] -> Opt.Expr -> Generator JS.Expr
259generateTailFunction name args body =
264generateTailFunction name args body =
260 do code <- generateCode body
265 do code <- generateCode body
261 return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
266 return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
@@ -268,7 +273,7 @@ generateTailFunction name args body =
268-- FUNCTIONS
273-- FUNCTIONS
271−generateFunction :: [Text] -> Opt.Expr -> State Int Code
276+generateFunction :: [Text] -> Opt.Expr -> Generator Code
272generateFunction args body =
277generateFunction args body =
273 do code <- generateCode body
278 do code <- generateCode body
274 jsExpr (generateFunctionWithArity args code)
279 jsExpr (generateFunctionWithArity args code)
@@ -297,7 +302,7 @@ generateFunctionWithArity rawArgs code =
297-- GENERATE CALL
302-- GENERATE CALL
300−generateCall :: Opt.Expr -> [Opt.Expr] -> State Int Code
305+generateCall :: Opt.Expr -> [Opt.Expr] -> Generator Code
301generateCall func args =
306generateCall func args =
302 case (func, args) of
307 case (func, args) of
303 (Opt.VarGlobal (V.Global home name), [arg]) ->
308 (Opt.VarGlobal (V.Global home name), [arg]) ->
@@ -320,13 +325,13 @@ generateCall func args =
320 generateCallHelp func args
325 generateCallHelp func args
323−genPrefix :: JS.PrefixOp -> Opt.Expr -> State Int Code
328+genPrefix :: JS.PrefixOp -> Opt.Expr -> Generator Code
324genPrefix op arg =
329genPrefix op arg =
325 do jsArg <- generateJsExpr arg
330 do jsArg <- generateJsExpr arg
326 jsExpr (JS.Prefix op jsArg)
331 jsExpr (JS.Prefix op jsArg)
329−genInfix :: JS.InfixOp -> Opt.Expr -> Opt.Expr -> State Int Code
334+genInfix :: JS.InfixOp -> Opt.Expr -> Opt.Expr -> Generator Code
330genInfix op left right =
335genInfix op left right =
331 do jsLeft <- generateJsExpr left
336 do jsLeft <- generateJsExpr left
332 jsRight <- generateJsExpr right
337 jsRight <- generateJsExpr right
@@ -343,7 +348,7 @@ bitwise =
343 ModuleName.inCore "Bitwise"
348 ModuleName.inCore "Bitwise"
346−generateCallHelp :: Opt.Expr -> [Opt.Expr] -> State Int Code
351+generateCallHelp :: Opt.Expr -> [Opt.Expr] -> Generator Code
347generateCallHelp func args =
352generateCallHelp func args =
349 arity = length args
354 arity = length args
@@ -362,7 +367,7 @@ generateCallHelp func args =
362-- GENERATE IFS
367-- GENERATE IFS
365−generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
370+generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> Generator Code
366generateIf givenBranches givenFinally =
371generateIf givenBranches givenFinally =
368 (branches, finally) =
373 (branches, finally) =
@@ -421,7 +426,7 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
421-- CASE EXPRESSIONS
426-- CASE EXPRESSIONS
424−generateCase :: Text -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> State Int [JS.Stmt]
429+generateCase :: Text -> Opt.Decider Opt.Choice -> [(Int, Opt.Expr)] -> Generator [JS.Stmt]
425generateCase exprName decider jumps =
430generateCase exprName decider jumps =
426 do labelRoot <- Var.fresh
431 do labelRoot <- Var.fresh
427 decider <- generateDecider exprName labelRoot decider
432 decider <- generateDecider exprName labelRoot decider
@@ -432,7 +437,7 @@ generateCase exprName decider jumps =
432-- handle any jumps
437-- handle any jumps
435−goto :: Text -> [JS.Stmt] -> (Int, Opt.Expr) -> State Int [JS.Stmt]
440+goto :: Text -> [JS.Stmt] -> (Int, Opt.Expr) -> Generator [JS.Stmt]
436goto labelRoot deciderStmts (target, branch) =
441goto labelRoot deciderStmts (target, branch) =
438 labeledDeciderStmt =
443 labeledDeciderStmt =
@@ -453,7 +458,7 @@ toLabel root target =
453-- turn deciders into ifs and switches
458-- turn deciders into ifs and switches
456−generateDecider :: Text -> Text -> Opt.Decider Opt.Choice -> State Int [JS.Stmt]
461+generateDecider :: Text -> Text -> Opt.Decider Opt.Choice -> Generator [JS.Stmt]
457generateDecider exprName labelRoot decisionTree =
462generateDecider exprName labelRoot decisionTree =
458 case decisionTree of
463 case decisionTree of
459 Opt.Leaf (Opt.Inline branch) ->
464 Opt.Leaf (Opt.Inline branch) ->
@@ -466,7 +471,7 @@ generateDecider exprName labelRoot decisionTree =
467 makeTest (path, test) =
472 makeTest (path, test) =
468 do testExpr <- pathToTestableExpr exprName path test
473 do testExpr <- pathToTestableExpr exprName path test
469− return (JS.Infix JS.OpStrictEq testExpr (testToExpr test))
474+ JS.Infix JS.OpStrictEq testExpr <$> testToExpr test
471 do testExprs <- mapM makeTest testChain
476 do testExprs <- mapM makeTest testChain
472 let cond = List.foldl1' (JS.Infix JS.OpLAnd) testExprs
477 let cond = List.foldl1' (JS.Infix JS.OpLAnd) testExprs
@@ -481,29 +486,31 @@ generateDecider exprName labelRoot decisionTree =
481 return [ JS.Switch testExpr (caseClauses ++ [caseDefault]) ]
486 return [ JS.Switch testExpr (caseClauses ++ [caseDefault]) ]
484−edgeToCase :: Text -> Text -> (DT.Test, Opt.Decider Opt.Choice) -> State Int JS.Case
489+edgeToCase :: Text -> Text -> (DT.Test, Opt.Decider Opt.Choice) -> Generator JS.Case
485edgeToCase exprName labelRoot (test, subTree) =
490edgeToCase exprName labelRoot (test, subTree) =
486− JS.Case (testToExpr test) <$> generateDecider exprName labelRoot subTree
493+ <*> generateDecider exprName labelRoot subTree
489−testToExpr :: DT.Test -> JS.Expr
496+testToExpr :: DT.Test -> Generator JS.Expr
490testToExpr test =
497testToExpr test =
491 case test of
498 case test of
492 DT.Constructor (V.Canonical _ tag) ->
499 DT.Constructor (V.Canonical _ tag) ->
493− JS.String tag
500+ return $ JS.String tag
495 DT.Literal (L.Chr char) ->
502 DT.Literal (L.Chr char) ->
496− JS.String char
503+ return $ JS.String char
498 DT.Literal lit ->
505 DT.Literal lit ->
499− Literal.literal lit
506+ Literal.literal lit
503-- work with paths
510-- work with paths
506−pathToTestableExpr :: Text -> DT.Path -> DT.Test -> State Int JS.Expr
513+pathToTestableExpr :: Text -> DT.Path -> DT.Test -> Generator JS.Expr
507pathToTestableExpr root path exampleTest =
514pathToTestableExpr root path exampleTest =
508 do accessExpr <- generateJsExpr (pathToExpr root path)
515 do accessExpr <- generateJsExpr (pathToExpr root path)
509 case exampleTest of
516 case exampleTest of
@@ -540,31 +547,32 @@ pathToExpr root fullPath =
540-- BINARY OPERATORS
547-- BINARY OPERATORS
543−generateBinop :: V.Global -> Opt.Expr -> Opt.Expr -> State Int Code
550+generateBinop :: V.Global -> Opt.Expr -> Opt.Expr -> Generator Code
544generateBinop op left right =
551generateBinop op left right =
545 do jsLeft <- generateJsExpr left
552 do jsLeft <- generateJsExpr left
546 jsRight <- generateJsExpr right
553 jsRight <- generateJsExpr right
547− jsExpr (generateBinopHelp op jsLeft jsRight)
554+ JsExpr <$> generateBinopHelp op jsLeft jsRight
551-- BINARY OPERATOR HELPERS
558-- BINARY OPERATOR HELPERS
554−generateBinopHelp :: V.Global -> JS.Expr -> JS.Expr -> JS.Expr
561+generateBinopHelp :: V.Global -> JS.Expr -> JS.Expr -> Generator JS.Expr
555−generateBinopHelp var@(V.Global home op) leftExpr rightExpr =
562+generateBinopHelp var@(V.Global home op) jsLeft jsRight =
557 simpleMake left right =
564 simpleMake left right =
565+ do func <- Var.global var
558− JS.Call (ref "A2") [ Var.global var, left, right ]
566+ return $ JS.Call (ref "A2") [ func, left, right ]
560 if home == basics then
568 if home == basics then
561− (Map.findWithDefault simpleMake op basicOps) leftExpr rightExpr
569+ (Map.findWithDefault simpleMake op basicsOps) jsLeft jsRight
563 else if op == "::" && home == list then
571 else if op == "::" && home == list then
564− BuiltIn.cons leftExpr rightExpr
572+ BuiltIn.cons jsLeft jsRight
567− simpleMake leftExpr rightExpr
575+ simpleMake jsLeft jsRight
570list :: ModuleName.Canonical
578list :: ModuleName.Canonical
@@ -572,39 +580,43 @@ list =
572 ModuleName.inCore "List"
580 ModuleName.inCore "List"
575−basicOps :: Map.Map Text (JS.Expr -> JS.Expr -> JS.Expr)
583+basicsOps :: Map.Map Text (JS.Expr -> JS.Expr -> Generator JS.Expr)
576−basicOps =
584+basicsOps =
577− Map.fromList (infixOps ++ specialOps)
585+ Map.fromList (basicsOpsNormal ++ basicsOpsSpecial)
580−infixOps :: [(Text, JS.Expr -> JS.Expr -> JS.Expr)]
588+basicsOpsNormal :: [(Text, JS.Expr -> JS.Expr -> Generator JS.Expr)]
581−infixOps =
589+basicsOpsNormal =
583− infixOp str op =
591+ (=*>) str op =
584− (str, JS.Infix op)
592+ ( str, \left right -> return (JS.Infix op left right) )
586− [ infixOp "+" JS.OpAdd
594+ [ "+" =*> JS.OpAdd
587− , infixOp "-" JS.OpSub
595+ , "-" =*> JS.OpSub
588− , infixOp "*" JS.OpMul
596+ , "*" =*> JS.OpMul
589− , infixOp "/" JS.OpDiv
597+ , "/" =*> JS.OpDiv
590− , infixOp "&&" JS.OpLAnd
598+ , "&&" =*> JS.OpLAnd
591− , infixOp "||" JS.OpLOr
599+ , "||" =*> JS.OpLOr
595−specialOps :: [(Text, JS.Expr -> JS.Expr -> JS.Expr)]
603+basicsOpsSpecial :: [(Text, JS.Expr -> JS.Expr -> Generator JS.Expr)]
596−specialOps =
604+basicsOpsSpecial =
597− [ (,) "^" $ \a b -> JS.Call (obj ["Math","pow"]) [a,b]
608+ [ "^" =*> \a b -> return $ JS.Call (obj ["Math","pow"]) [a,b]
598− , (,) "==" $ \a b -> BuiltIn.eq a b
609+ , "==" =*> BuiltIn.eq
599− , (,) "/=" $ \a b -> JS.Prefix JS.PrefixLNot (BuiltIn.eq a b)
610+ , "/=" =*> \a b -> JS.Prefix JS.PrefixLNot <$> BuiltIn.eq a b
600− , (,) "<" $ cmp JS.OpLT 0
611+ , "<" =*> cmp JS.OpLT 0
601− , (,) ">" $ cmp JS.OpGT 0
612+ , ">" =*> cmp JS.OpGT 0
602− , (,) "<=" $ cmp JS.OpLT 1
613+ , "<=" =*> cmp JS.OpLT 1
603− , (,) ">=" $ cmp JS.OpGT (-1)
614+ , ">=" =*> cmp JS.OpGT (-1)
604− , (,) "//" $ \a b -> JS.Infix JS.OpBOr (JS.Infix JS.OpDiv a b) (JS.Int 0)
615+ , "//" =*> \a b -> return $ JS.Infix JS.OpBOr (JS.Infix JS.OpDiv a b) (JS.Int 0)
608−cmp :: JS.InfixOp -> Int -> JS.Expr -> JS.Expr -> JS.Expr
619+cmp :: JS.InfixOp -> Int -> JS.Expr -> JS.Expr -> Generator JS.Expr
609cmp op n a b =
620cmp op n a b =
610− JS.Infix op (BuiltIn.cmp a b) (JS.Int n)
621+ do ordering <- BuiltIn.cmp a b
622+ return $ JS.Infix op ordering (JS.Int n)