@@ -5,38 +5,29 @@ import Control.Arrow (first, second, (***))
55import Control.Monad.State as State
66import qualified Data.List as List
77import qualified Data.Map as Map
8−import qualified Data.Maybe as Maybe
98import Language.ECMAScript3.PrettyPrint as ES
109import Language.ECMAScript3.Syntax
1110import qualified Text.PrettyPrint.Leijen as PP
1211
13−import AST.Expression.General as Expr
14−import qualified AST.Expression.Optimized as Opt
15−import qualified AST.Helpers as Help
12+import qualified AST.Expression.General as Expr
13+import AST.Expression.Optimized as Opt
1614import AST.Literal
1715import qualified AST.Module as Module
1816import qualified AST.Module.Name as ModuleName
19−import qualified AST.Pattern as P
2017import qualified AST.Variable as Var
2118import Generate.JavaScript.Helpers as Help
2219import qualified Generate.JavaScript.BuiltIn as BuiltIn
23−import qualified Generate.JavaScript.Crash as Crash
2420import qualified Generate.JavaScript.Literal as Literal
2521import qualified Generate.JavaScript.Port as Port
2622import qualified Generate.JavaScript.Variable as Var
27−import qualified Optimize.Cases as Case
28−import qualified Reporting.Annotation as A
29−import qualified Reporting.Crash as Crash
23+import qualified Optimize.Cases as PM
3024
3125
3226generate :: Module.Optimized -> String
33−generate module_ =
27+generate definitions =
3428 let
35− (definitions, _) =
36− flattenLets [] (Module.program (Module.body module_))
37−
3829 stmts =
39− concat (State.evalState (mapM defToStatements definitions) 0)
30+ State.evalState (mapM generateDef definitions) 0
4031 in
4132 PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint stmts)) ""
4233
@@ -122,7 +113,7 @@ exprToJsExpr tcc canonicalExpr =
122113
123114
124115exprToCode :: TailCallContext -> Opt.Expr -> State Int Code
125−exprToCode tcc annotatedExpr@(A.A _ expr) =
116+exprToCode tcc expr =
126117 case expr of
127118 Var var ->
128119 jsExpr $ Var.canonical var
@@ -172,11 +163,33 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
172163 Binop op leftExpr rightExpr ->
173164 binop op leftExpr rightExpr
174165
175− Lambda _ _ ->
176− generateFunction (Expr.collectLambdas annotatedExpr)
166+ Function args body ->
167+ generateFunction args body
177168
178− App _ _ ->
179− generateApplication tcc annotatedExpr
169+ Call func args ->
170+ let
171+ arity = length args
172+ aN = "A" ++ show arity
173+ in
174+ do jsFunc <- toJsExpr func
175+ jsArgs <- mapM toJsExpr args
176+ jsExpr $
177+ if 2 <= arity && arity <= 9 then
178+ ref aN `call` (jsFunc:jsArgs)
179+ else
180+ foldl1 (<|) (jsFunc:jsArgs)
181+
182+ TailCall name argNames args ->
183+ let
184+ reassign name tempName =
185+ ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
186+ in
187+ do args' <- mapM toJsExpr args
188+ tempNames <- mapM (\_ -> Var.fresh) args
189+ jsBlock $
190+ VarDeclStmt () (zipWith varDecl tempNames args')
191+ : zipWith reassign argNames tempNames
192+ ++ [ContinueStmt () (Just (Id () name))]
180193
181194 Let defs body ->
182195 generateLet tcc defs body
@@ -184,8 +197,8 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
184197 If branches finally ->
185198 generateIf tcc branches finally
186199
187− Case expr branches ->
188− generateCase tcc expr branches
200+ Case expr decisionTree branches ->
201+ generateCase tcc expr decisionTree branches
189202
190203 ExplicitList elements ->
191204 do jsElements <- mapM toJsExpr elements
@@ -199,43 +212,45 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
199212 fields =
200213 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
201214
215+ DataAccess dataExpr index ->
216+ do jsDataExpr <- toJsExpr dataExpr
217+ jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
218+
202219 GLShader _uid src _tipe ->
203220 jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
204221
205222 Port impl ->
206223 case impl of
207− In name portType ->
224+ Expr.In name portType ->
208225 jsExpr (Port.inbound name portType)
209226
210− Out name expr portType ->
227+ Expr.Out name expr portType ->
211228 do expr' <- toJsExpr expr
212229 jsExpr (Port.outbound name expr' portType)
213230
214− Task name expr portType ->
231+ Expr.Task name expr portType ->
215232 do expr' <- toJsExpr expr
216233 jsExpr (Port.task name expr' portType)
217234
218− Crash details ->
219− jsExpr $ Crash.crash details
235+ Crash ->
236+ error "TODO"
220237
221238
222239-- FUNCTIONS
223240
224−generateFunction :: ([P.Optimized], Opt.Expr) -> State Int Code
225−generateFunction (args, initialBody) =
226− do (argVars, patternDefs) <- destructuredArgs args
227− code <- generateLet Nothing patternDefs initialBody
228− jsExpr (generateFunctionWithArity argVars code)
241+generateFunction :: [String] -> Opt.Expr -> State Int Code
242+generateFunction args body =
243+ do code <- exprToCode Nothing body
244+ jsExpr (generateFunctionWithArity args code)
229245
230246
231−generateTailFunction :: String -> ([P.Optimized], Opt.Expr) -> State Int (Expression ())
232−generateTailFunction name (args, initialBody) =
233− do (argVars, patternDefs) <- destructuredArgs args
234− label <- Id () <$> Var.fresh
235− code <- generateLet (Just (name, argVars, label)) patternDefs initialBody
236− let whileLoop =
237− JsBlock [ LabelledStmt () label (WhileStmt () (BoolLit () True) (toStatement code)) ]
238− return (generateFunctionWithArity argVars whileLoop)
247+generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
248+generateTailFunction name args body =
249+ do code <- exprToCode Nothing body
250+ return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
251+ LabelledStmt ()
252+ (Id () name)
253+ (WhileStmt () (BoolLit () True) (toStatement code))
239254
240255
241256generateFunctionWithArity :: [String] -> Code -> Expression ()
@@ -256,81 +271,6 @@ generateFunctionWithArity args code =
256271 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
257272
258273
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)
263−
264−
265−destructPattern :: P.Optimized -> State Int (String, Maybe Opt.Def)
266−destructPattern pattern@(A.A ann pat) =
267− case pat of
268− P.Var x ->
269− return (Var.safe x, Nothing)
270−
271− _ ->
272− do arg <- Var.fresh
273− return
274− ( arg
275− , Just $ Opt.Definition Opt.dummyFacts pattern (A.A ann (localVar arg))
276− )
277−
278−
279−-- APPLICATIONS
280−
281−generateApplication :: TailCallContext -> Opt.Expr -> State Int Code
282−generateApplication tcc expr =
283− let
284− (func:args) =
285− Expr.collectApps expr
286−
287− arity =
288− length args
289−
290− reassign name tempName =
291− ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
292−
293− aN =
294− "A" ++ show arity
295− in
296− case isTailCall tcc func arity of
297− Just (argNames, label) ->
298− do args' <- mapM toJsExpr args
299− tempNames <- mapM (\_ -> Var.fresh) args
300− jsBlock $
301− VarDeclStmt () (zipWith varDecl tempNames args')
302− : zipWith reassign argNames tempNames
303− ++ [ContinueStmt () (Just label)]
304−
305− _ ->
306− do func' <- toJsExpr func
307− args' <- mapM toJsExpr args
308− jsExpr $
309− if 2 <= arity && arity <= 9 then
310− ref aN `call` (func':args')
311− else
312− foldl1 (<|) (func':args')
313−
314−
315−isTailCall :: TailCallContext -> Opt.Expr -> Int -> Maybe ([String], Label)
316−isTailCall tcc (A.A _ func) arity =
317− case (func, tcc) of
318− (Var (Var.Canonical Var.Local name), Just (tcName, tcArgs, tcLabel)) ->
319− if name == tcName && length tcArgs == arity then
320− Just (tcArgs, tcLabel)
321− else
322− Nothing
323−
324− (Var (Var.Canonical (Var.TopLevel _) name), Just (tcName, tcArgs, tcLabel)) ->
325− if name == tcName && length tcArgs == arity then
326− Just (tcArgs, tcLabel)
327− else
328− Nothing
329−
330− _ ->
331− Nothing
332−
333−
334274-- LET EXPRESSIONS
335275
336276generateLet
@@ -338,20 +278,12 @@ generateLet
338278 -> [Opt.Def]
339279 -> Opt.Expr
340280 -> State Int Code
341−generateLet tcc givenDefs givenBody =
342− do let (defs, body) = flattenLets givenDefs givenBody
343− stmts <- concat <$> mapM defToStatements defs
281+generateLet tcc defs body =
282+ do stmts <- mapM generateDef defs
344283 code <- exprToCode tcc body
345284 jsBlock (stmts ++ toStatementList code)
346285
347286
348−flattenLets :: [Opt.Def] -> Opt.Expr -> ([Opt.Def], Opt.Expr)
349−flattenLets defs lexpr@(A.A _ expr) =
350− case expr of
351− Let ds body -> flattenLets (defs ++ ds) body
352− _ -> (defs, lexpr)
353−
354−
355287-- GENERATE IFS
356288
357289generateIf :: TailCallContext -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
@@ -396,13 +328,13 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
396328 case unvisitedBranches of
397329 [] ->
398330 case finally of
399− A.A _ (If subBranches subFinally) ->
331+ If subBranches subFinally ->
400332 crushIfsHelp visitedBranches subBranches subFinally
401333
402334 _ ->
403335 (reverse visitedBranches, finally)
404336
405− (A.A _ (Literal (Boolean True)), branch) : _ ->
337+ (Literal (Boolean True), branch) : _ ->
406338 crushIfsHelp visitedBranches [] branch
407339
408340 visiting : unvisited ->
@@ -412,84 +344,29 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
412344
413345-- DEFINITIONS
414346
415−defToStatements :: Opt.Def -> State Int [Statement ()]
416−defToStatements (Opt.Definition facts pattern expr) =
417− case Opt.tailRecursionDetails facts of
418− Just name ->
419− do func <- generateTailFunction name (Expr.collectLambdas expr)
420− return [ VarDeclStmt () [ varDecl name func ] ]
421−
422− Nothing ->
423− defToStatementsHelp facts pattern =<< toJsExpr expr
347+generateDef :: Opt.Def -> State Int (Statement ())
348+generateDef def =
349+ do (home, name, jsBody) <-
350+ case def of
351+ Opt.TailDef (Opt.Facts home _) name argNames body ->
352+ (,,) home name <$> generateTailFunction name argNames body
424353
354+ Opt.Def (Opt.Facts home _) name body ->
355+ (,,) home name <$> toJsExpr body
425356
426−defToStatementsHelp
427− :: Opt.Facts
428− -> P.Optimized
429− -> Expression ()
430− -> State Int [Statement ()]
431−defToStatementsHelp facts annPattern@(A.A _ pattern) jsExpr =
432− let
433− define x =
434− varDecl x jsExpr
435− in
436− case pattern of
437− P.Var x ->
438− if Help.isOp x then
439− let
440− op = LBracket () (ref "_op") (string x)
441− in
442− return [ ExprStmt () $ AssignExpr () OpAssign op jsExpr ]
443− else
444− return [ VarDeclStmt () [ define (Var.safe x) ] ]
445−
446− P.Record fields ->
447− let
448− setField name =
449− varDecl name (obj ["$",name])
450− in
451− return [ VarDeclStmt () (define "$" : map setField fields) ]
452−
453− P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
454− return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
455− where
456− vars = getVars patterns
457− getVars patterns =
458− case patterns of
459− A.A _ (P.Var x) : rest ->
460− (Var.safe x :) `fmap` getVars rest
461− [] ->
462− Just []
463− _ ->
464− Nothing
465−
466− decl x n = varDecl x (obj ["$","_" ++ show n])
467− setup vars
468− | Help.isTuple name = define "$" : vars
469− | otherwise = define "_raw" : safeAssign : vars
470−
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"))
474−
475− _ ->
476− do defs' <- concat <$> mapM toDef vars
477− return (VarDeclStmt () [define "_"] : defs')
478− where
479− vars = P.boundVarList annPattern
480− mkVar = A.A () . localVar
481− toDef y =
482− let expr = A.A () $ Case (mkVar "_") [(annPattern, mkVar y)]
483− pat = A.A () (P.Var y)
484− in
485− defToStatements (Opt.Definition facts pat expr)
357+ return (VarDeclStmt () [ varDecl (Var.defName home name) jsBody ])
486358
487359
488360-- CASE EXPRESSIONS
489361
490−generateCase :: TailCallContext -> Opt.Expr -> [(P.Optimized, Opt.Expr)] -> State Int Code
491−generateCase tcc expr branches =
492− error "TODO" tcc expr branches
362+generateCase
363+ :: TailCallContext
364+ -> Opt.Expr
365+ -> PM.DecisionTree Int
366+ -> Map.Map Int Opt.Expr
367+ -> State Int Code
368+generateCase tcc expr decisionTree branches =
369+ error "TODO" tcc expr decisionTree branches
493370
494371
495372-- BINARY OPERATORS
@@ -501,7 +378,7 @@ binop
501378 -> State Int Code
502379binop func left right
503380 | func == Var.Canonical Var.BuiltIn "::" =
504− toCode (A.A () (Data "::" [left,right]))
381+ toCode (Data "::" [left,right])
505382
506383 | func == forwardCompose =
507384 compose (collectLeftAssoc forwardCompose left right)
@@ -629,7 +506,7 @@ collectRightAssoc desiredOp left right =
629506collectRightAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
630507collectRightAssocHelp desiredOp exprList expr =
631508 case expr of
632− A.A _ (Binop op left right) | op == desiredOp ->
509+ Binop op left right | op == desiredOp ->
633510 collectRightAssocHelp desiredOp (left : exprList) right
634511
635512 _ ->
@@ -645,7 +522,7 @@ collectLeftAssoc desiredOp left right =
645522collectLeftAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
646523collectLeftAssocHelp desiredOp exprList expr =
647524 case expr of
648− A.A _ (Binop op left right) | op == desiredOp ->
525+ Binop op left right | op == desiredOp ->
649526 collectLeftAssocHelp desiredOp (right : exprList) left
650527
651528 _ ->