@@ -5,38 +5,29 @@ import Control.Arrow (first, second, (***))
5import Control.Monad.State as State
5import Control.Monad.State as State
6import qualified Data.List as List
6import qualified Data.List as List
7import qualified Data.Map as Map
7import qualified Data.Map as Map
8−import qualified Data.Maybe as Maybe
9import Language.ECMAScript3.PrettyPrint as ES
8import Language.ECMAScript3.PrettyPrint as ES
10import Language.ECMAScript3.Syntax
9import Language.ECMAScript3.Syntax
11import qualified Text.PrettyPrint.Leijen as PP
10import qualified Text.PrettyPrint.Leijen as PP
13−import AST.Expression.General as Expr
12+import qualified AST.Expression.General as Expr
14−import qualified AST.Expression.Optimized as Opt
13+import AST.Expression.Optimized as Opt
15−import qualified AST.Helpers as Help
16import AST.Literal
14import AST.Literal
17import qualified AST.Module as Module
15import qualified AST.Module as Module
18import qualified AST.Module.Name as ModuleName
16import qualified AST.Module.Name as ModuleName
19−import qualified AST.Pattern as P
20import qualified AST.Variable as Var
17import qualified AST.Variable as Var
21import Generate.JavaScript.Helpers as Help
18import Generate.JavaScript.Helpers as Help
22import qualified Generate.JavaScript.BuiltIn as BuiltIn
19import qualified Generate.JavaScript.BuiltIn as BuiltIn
23−import qualified Generate.JavaScript.Crash as Crash
24import qualified Generate.JavaScript.Literal as Literal
20import qualified Generate.JavaScript.Literal as Literal
25import qualified Generate.JavaScript.Port as Port
21import qualified Generate.JavaScript.Port as Port
26import qualified Generate.JavaScript.Variable as Var
22import qualified Generate.JavaScript.Variable as Var
27−import qualified Optimize.Cases as Case
23+import qualified Optimize.Cases as PM
28−import qualified Reporting.Annotation as A
29−import qualified Reporting.Crash as Crash
32generate :: Module.Optimized -> String
26generate :: Module.Optimized -> String
33−generate module_ =
27+generate definitions =
36− flattenLets [] (Module.program (Module.body module_))
39− concat (State.evalState (mapM defToStatements definitions) 0)
30+ State.evalState (mapM generateDef definitions) 0
41 PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint stmts)) ""
32 PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint stmts)) ""
@@ -122,7 +113,7 @@ exprToJsExpr tcc canonicalExpr =
124exprToCode :: TailCallContext -> Opt.Expr -> State Int Code
115exprToCode :: TailCallContext -> Opt.Expr -> State Int Code
125−exprToCode tcc annotatedExpr@(A.A _ expr) =
116+exprToCode tcc expr =
126 case expr of
117 case expr of
127 Var var ->
118 Var var ->
128 jsExpr $ Var.canonical var
119 jsExpr $ Var.canonical var
@@ -172,11 +163,33 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
172 Binop op leftExpr rightExpr ->
163 Binop op leftExpr rightExpr ->
173 binop op leftExpr rightExpr
164 binop op leftExpr rightExpr
175− Lambda _ _ ->
166+ Function args body ->
176− generateFunction (Expr.collectLambdas annotatedExpr)
167+ generateFunction args body
178− App _ _ ->
169+ Call func args ->
179− generateApplication tcc annotatedExpr
170+ let
172+ aN = "A" ++ show arity
174+ do jsFunc <- toJsExpr func
175+ jsArgs <- mapM toJsExpr args
177+ if 2 <= arity && arity <= 9 then
178+ ref aN `call` (jsFunc:jsArgs)
180+ foldl1 (<|) (jsFunc:jsArgs)
182+ TailCall name argNames args ->
184+ reassign name tempName =
185+ ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
187+ do args' <- mapM toJsExpr args
188+ tempNames <- mapM (\_ -> Var.fresh) args
190+ VarDeclStmt () (zipWith varDecl tempNames args')
191+ : zipWith reassign argNames tempNames
192+ ++ [ContinueStmt () (Just (Id () name))]
181 Let defs body ->
194 Let defs body ->
182 generateLet tcc defs body
195 generateLet tcc defs body
@@ -184,8 +197,8 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
184 If branches finally ->
197 If branches finally ->
185 generateIf tcc branches finally
198 generateIf tcc branches finally
187− Case expr branches ->
200+ Case expr decisionTree branches ->
188− generateCase tcc expr branches
201+ generateCase tcc expr decisionTree branches
190 ExplicitList elements ->
203 ExplicitList elements ->
191 do jsElements <- mapM toJsExpr elements
204 do jsElements <- mapM toJsExpr elements
@@ -199,43 +212,45 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
200 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
213 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
215+ DataAccess dataExpr index ->
216+ do jsDataExpr <- toJsExpr dataExpr
217+ jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
202 GLShader _uid src _tipe ->
219 GLShader _uid src _tipe ->
203 jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
220 jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
205 Port impl ->
222 Port impl ->
206 case impl of
223 case impl of
207− In name portType ->
224+ Expr.In name portType ->
208 jsExpr (Port.inbound name portType)
225 jsExpr (Port.inbound name portType)
210− Out name expr portType ->
227+ Expr.Out name expr portType ->
211 do expr' <- toJsExpr expr
228 do expr' <- toJsExpr expr
212 jsExpr (Port.outbound name expr' portType)
229 jsExpr (Port.outbound name expr' portType)
214− Task name expr portType ->
231+ Expr.Task name expr portType ->
215 do expr' <- toJsExpr expr
232 do expr' <- toJsExpr expr
216 jsExpr (Port.task name expr' portType)
233 jsExpr (Port.task name expr' portType)
218− Crash details ->
235+ Crash ->
219− jsExpr $ Crash.crash details
236+ error "TODO"
222-- FUNCTIONS
239-- FUNCTIONS
224−generateFunction :: ([P.Optimized], Opt.Expr) -> State Int Code
241+generateFunction :: [String] -> Opt.Expr -> State Int Code
225−generateFunction (args, initialBody) =
242+generateFunction args body =
226− do (argVars, patternDefs) <- destructuredArgs args
243+ do code <- exprToCode Nothing body
227− code <- generateLet Nothing patternDefs initialBody
228− jsExpr (generateFunctionWithArity argVars code)
244+ jsExpr (generateFunctionWithArity args code)
231−generateTailFunction :: String -> ([P.Optimized], Opt.Expr) -> State Int (Expression ())
247+generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
232−generateTailFunction name (args, initialBody) =
248+generateTailFunction name args body =
233− do (argVars, patternDefs) <- destructuredArgs args
249+ do code <- exprToCode Nothing body
234− label <- Id () <$> Var.fresh
250+ return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
235− code <- generateLet (Just (name, argVars, label)) patternDefs initialBody
251+ LabelledStmt ()
236− let whileLoop =
252+ (Id () name)
237− JsBlock [ LabelledStmt () label (WhileStmt () (BoolLit () True) (toStatement code)) ]
253+ (WhileStmt () (BoolLit () True) (toStatement code))
238− return (generateFunctionWithArity argVars whileLoop)
241generateFunctionWithArity :: [String] -> Code -> Expression ()
256generateFunctionWithArity :: [String] -> Code -> Expression ()
@@ -256,81 +271,6 @@ generateFunctionWithArity args code =
256 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
271 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
259−destructuredArgs :: [P.Optimized] -> State Int ([String], [Opt.Def])
260−destructuredArgs args =
261− do (argVars, maybePatternDefs) <- unzip <$> mapM destructPattern args
262− return (argVars, Maybe.catMaybes maybePatternDefs)
265−destructPattern :: P.Optimized -> State Int (String, Maybe Opt.Def)
266−destructPattern pattern@(A.A ann pat) =
269− return (Var.safe x, Nothing)
275− , Just $ Opt.Definition Opt.dummyFacts pattern (A.A ann (localVar arg))
281−generateApplication :: TailCallContext -> Opt.Expr -> State Int Code
282−generateApplication tcc expr =
285− Expr.collectApps expr
290− reassign name tempName =
291− ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
296− case isTailCall tcc func arity of
297− Just (argNames, label) ->
298− do args' <- mapM toJsExpr args
299− tempNames <- mapM (\_ -> Var.fresh) args
301− VarDeclStmt () (zipWith varDecl tempNames args')
302− : zipWith reassign argNames tempNames
303− ++ [ContinueStmt () (Just label)]
306− do func' <- toJsExpr func
307− args' <- mapM toJsExpr args
309− if 2 <= arity && arity <= 9 then
310− ref aN `call` (func':args')
312− foldl1 (<|) (func':args')
315−isTailCall :: TailCallContext -> Opt.Expr -> Int -> Maybe ([String], Label)
316−isTailCall tcc (A.A _ func) arity =
318− (Var (Var.Canonical Var.Local name), Just (tcName, tcArgs, tcLabel)) ->
319− if name == tcName && length tcArgs == arity then
320− Just (tcArgs, tcLabel)
324− (Var (Var.Canonical (Var.TopLevel _) name), Just (tcName, tcArgs, tcLabel)) ->
325− if name == tcName && length tcArgs == arity then
326− Just (tcArgs, tcLabel)
334-- LET EXPRESSIONS
274-- LET EXPRESSIONS
336generateLet
276generateLet
@@ -338,20 +278,12 @@ generateLet
338 -> [Opt.Def]
278 -> [Opt.Def]
339 -> Opt.Expr
279 -> Opt.Expr
340 -> State Int Code
280 -> State Int Code
341−generateLet tcc givenDefs givenBody =
281+generateLet tcc defs body =
342− do let (defs, body) = flattenLets givenDefs givenBody
343− stmts <- concat <$> mapM defToStatements defs
282+ do stmts <- mapM generateDef defs
344 code <- exprToCode tcc body
283 code <- exprToCode tcc body
345 jsBlock (stmts ++ toStatementList code)
284 jsBlock (stmts ++ toStatementList code)
348−flattenLets :: [Opt.Def] -> Opt.Expr -> ([Opt.Def], Opt.Expr)
349−flattenLets defs lexpr@(A.A _ expr) =
351− Let ds body -> flattenLets (defs ++ ds) body
355-- GENERATE IFS
287-- GENERATE IFS
357generateIf :: TailCallContext -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
289generateIf :: TailCallContext -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
@@ -396,13 +328,13 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
396 case unvisitedBranches of
328 case unvisitedBranches of
398 case finally of
330 case finally of
399− A.A _ (If subBranches subFinally) ->
331+ If subBranches subFinally ->
400 crushIfsHelp visitedBranches subBranches subFinally
332 crushIfsHelp visitedBranches subBranches subFinally
403 (reverse visitedBranches, finally)
335 (reverse visitedBranches, finally)
405− (A.A _ (Literal (Boolean True)), branch) : _ ->
337+ (Literal (Boolean True), branch) : _ ->
406 crushIfsHelp visitedBranches [] branch
338 crushIfsHelp visitedBranches [] branch
408 visiting : unvisited ->
340 visiting : unvisited ->
@@ -412,84 +344,29 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
413-- DEFINITIONS
345-- DEFINITIONS
415−defToStatements :: Opt.Def -> State Int [Statement ()]
347+generateDef :: Opt.Def -> State Int (Statement ())
416−defToStatements (Opt.Definition facts pattern expr) =
348+generateDef def =
417− case Opt.tailRecursionDetails facts of
349+ do (home, name, jsBody) <-
418− Just name ->
350+ case def of
351+ Opt.TailDef (Opt.Facts home _) name argNames body ->
419− do func <- generateTailFunction name (Expr.collectLambdas expr)
352+ (,,) home name <$> generateTailFunction name argNames body
420− return [ VarDeclStmt () [ varDecl name func ] ]
423− defToStatementsHelp facts pattern =<< toJsExpr expr
354+ Opt.Def (Opt.Facts home _) name body ->
355+ (,,) home name <$> toJsExpr body
426−defToStatementsHelp
357+ return (VarDeclStmt () [ varDecl (Var.defName home name) jsBody ])
430− -> State Int [Statement ()]
431−defToStatementsHelp facts annPattern@(A.A _ pattern) jsExpr =
440− op = LBracket () (ref "_op") (string x)
442− return [ ExprStmt () $ AssignExpr () OpAssign op jsExpr ]
444− return [ VarDeclStmt () [ define (Var.safe x) ] ]
449− varDecl name (obj ["$",name])
451− return [ VarDeclStmt () (define "$" : map setField fields) ]
453− P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
454− return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
456− vars = getVars patterns
459− A.A _ (P.Var x) : rest ->
460− (Var.safe x :) `fmap` getVars rest
466− decl x n = varDecl x (obj ["$","_" ++ show n])
468− | Help.isTuple name = define "$" : vars
469− | otherwise = define "_raw" : safeAssign : vars
471− safeAssign = varDecl "$" (CondExpr () if' (ref "_raw") exception)
472− if' = InfixExpr () OpStrictEq (obj ["_raw","ctor"]) (string name)
473− exception = Crash.crash (Crash.IncompletePatternMatch (error "TODO"))
476− do defs' <- concat <$> mapM toDef vars
477− return (VarDeclStmt () [define "_"] : defs')
479− vars = P.boundVarList annPattern
480− mkVar = A.A () . localVar
482− let expr = A.A () $ Case (mkVar "_") [(annPattern, mkVar y)]
483− pat = A.A () (P.Var y)
485− defToStatements (Opt.Definition facts pat expr)
488-- CASE EXPRESSIONS
360-- CASE EXPRESSIONS
490−generateCase :: TailCallContext -> Opt.Expr -> [(P.Optimized, Opt.Expr)] -> State Int Code
362+generateCase
365+ -> PM.DecisionTree Int
366+ -> Map.Map Int Opt.Expr
491−generateCase tcc expr branches =
368+generateCase tcc expr decisionTree branches =
492− error "TODO" tcc expr branches
369+ error "TODO" tcc expr decisionTree branches
495-- BINARY OPERATORS
372-- BINARY OPERATORS
@@ -501,7 +378,7 @@ binop
501 -> State Int Code
378 -> State Int Code
502binop func left right
379binop func left right
503 | func == Var.Canonical Var.BuiltIn "::" =
380 | func == Var.Canonical Var.BuiltIn "::" =
504− toCode (A.A () (Data "::" [left,right]))
381+ toCode (Data "::" [left,right])
506 | func == forwardCompose =
383 | func == forwardCompose =
507 compose (collectLeftAssoc forwardCompose left right)
384 compose (collectLeftAssoc forwardCompose left right)
@@ -629,7 +506,7 @@ collectRightAssoc desiredOp left right =
629collectRightAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
506collectRightAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
630collectRightAssocHelp desiredOp exprList expr =
507collectRightAssocHelp desiredOp exprList expr =
631 case expr of
508 case expr of
632− A.A _ (Binop op left right) | op == desiredOp ->
509+ Binop op left right | op == desiredOp ->
633 collectRightAssocHelp desiredOp (left : exprList) right
510 collectRightAssocHelp desiredOp (left : exprList) right
@@ -645,7 +522,7 @@ collectLeftAssoc desiredOp left right =
645collectLeftAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
522collectLeftAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
646collectLeftAssocHelp desiredOp exprList expr =
523collectLeftAssocHelp desiredOp exprList expr =
647 case expr of
524 case expr of
648− A.A _ (Binop op left right) | op == desiredOp ->
525+ Binop op left right | op == desiredOp ->
649 collectLeftAssocHelp desiredOp (right : exprList) left
526 collectLeftAssocHelp desiredOp (right : exprList) left