@@ -2,34 +2,34 @@ module Generate.JavaScript (generate) where
3import Control.Applicative ((<$>),(<*>))
3import Control.Applicative ((<$>),(<*>))
4import Control.Arrow (first, second, (***))
4import Control.Arrow (first, second, (***))
5−import Control.Monad.State
5+import 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
8+import Language.ECMAScript3.PrettyPrint as ES
9import Language.ECMAScript3.Syntax
9import Language.ECMAScript3.Syntax
10+import qualified Text.PrettyPrint.Leijen as PP
11−import AST.Expression.General as Expr
12+import qualified AST.Expression.General as Expr
12−import qualified AST.Expression.Optimized as Opt
13+import AST.Expression.Optimized as Opt
13−import qualified AST.Helpers as Help
14+import qualified AST.Literal as L
15import qualified AST.Module as Module
15import qualified AST.Module as Module
16import qualified AST.Module.Name as ModuleName
16import qualified AST.Module.Name as ModuleName
17−import qualified AST.Pattern as P
18import qualified AST.Variable as Var
17import qualified AST.Variable as Var
19import Generate.JavaScript.Helpers as Help
18import Generate.JavaScript.Helpers as Help
20import qualified Generate.JavaScript.BuiltIn as BuiltIn
19import qualified Generate.JavaScript.BuiltIn as BuiltIn
21−import qualified Generate.JavaScript.Crash as Crash
22import qualified Generate.JavaScript.Literal as Literal
20import qualified Generate.JavaScript.Literal as Literal
23import qualified Generate.JavaScript.Port as Port
21import qualified Generate.JavaScript.Port as Port
24import qualified Generate.JavaScript.Variable as Var
22import qualified Generate.JavaScript.Variable as Var
25−import qualified Optimize.Cases as Case
23+import qualified Optimize.Patterns.DecisionTree as DT
26−import qualified Reporting.Annotation as A
27−import qualified Reporting.Crash as Crash
30generate :: Module.Optimized -> String
26generate :: Module.Optimized -> String
31−generate modul =
27+generate definitions =
32− error "TODO" modul exprToCode
28+ let
30+ State.evalState (mapM generateDef definitions) 0
32+ PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint stmts)) ""
35-- CODE CHUNKS
35-- CODE CHUNKS
@@ -81,39 +81,35 @@ toExpr code =
81 case code of
81 case code of
82 JsExpr expr ->
82 JsExpr expr ->
84 JsBlock stmts ->
85 JsBlock stmts ->
85 function [] stmts `call` []
86 function [] stmts `call` []
88−-- TAIL CALL CONTEXT
89+-- DEFINITIONS
90−type TailCallContext =
91+generateDef :: Opt.Def -> State Int (Statement ())
91− Maybe (String, [String], Label)
92+generateDef def =
93+ do (home, name, jsBody) <-
95+ Opt.TailDef (Opt.Facts home _) name argNames body ->
96+ (,,) home name <$> generateTailFunction name argNames body
98+ Opt.Def (Opt.Facts home _) name body ->
99+ (,,) home name <$> generateJsExpr body
94−type Label =
101+ return (VarDeclStmt () [ varDecl (Var.defName home name) jsBody ])
98-- EXPRESSIONS
104-- EXPRESSIONS
100−toJsExpr :: Opt.Expr -> State Int (Expression ())
106+generateJsExpr :: Opt.Expr -> State Int (Expression ())
101−toJsExpr =
107+generateJsExpr optExpr =
102− exprToJsExpr Nothing
108+ toExpr <$> generateCode optExpr
105−toCode :: Opt.Expr -> State Int Code
110−exprToJsExpr :: TailCallContext -> Opt.Expr -> State Int (Expression ())
111−exprToJsExpr tcc canonicalExpr =
112− toExpr <$> exprToCode tcc canonicalExpr
115−exprToCode :: TailCallContext -> Opt.Expr -> State Int Code
111+generateCode :: Opt.Expr -> State Int Code
116−exprToCode tcc annotatedExpr@(A.A _ expr) =
112+generateCode expr =
117 case expr of
113 case expr of
118 Var var ->
114 Var var ->
119 jsExpr $ Var.canonical var
115 jsExpr $ Var.canonical var
@@ -122,28 +118,28 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
122 jsExpr (Literal.literal lit)
118 jsExpr (Literal.literal lit)
124 Range lo hi ->
120 Range lo hi ->
125− do lo' <- toJsExpr lo
121+ do lo' <- generateJsExpr lo
126− hi' <- toJsExpr hi
122+ hi' <- generateJsExpr hi
127 jsExpr $ BuiltIn.range lo' hi'
123 jsExpr $ BuiltIn.range lo' hi'
129 Access record field ->
125 Access record field ->
130− do record' <- toJsExpr record
126+ do record' <- generateJsExpr record
131 jsExpr $ DotRef () record' (var (Var.safe field))
127 jsExpr $ DotRef () record' (var (Var.safe field))
133 Update record fields ->
129 Update record fields ->
135 fieldToJs (field, value) =
131 fieldToJs (field, value) =
136− do jsValue <- toJsExpr value
132+ do jsValue <- generateJsExpr value
137 return (Var.safe field, jsValue)
133 return (Var.safe field, jsValue)
139− do jsRecord <- toJsExpr record
135+ do jsRecord <- generateJsExpr record
140 jsFields <- mapM fieldToJs fields
136 jsFields <- mapM fieldToJs fields
141 jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
137 jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
143 Record fields ->
139 Record fields ->
144 do fields' <-
140 do fields' <-
145 forM fields $ \(field, e) ->
141 forM fields $ \(field, e) ->
146− (,) (Var.safe field) <$> toJsExpr e
142+ (,) (Var.safe field) <$> generateJsExpr e
148 let fieldMap =
144 let fieldMap =
149 List.foldl' combine Map.empty fields'
145 List.foldl' combine Map.empty fields'
@@ -163,70 +159,96 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
163 Binop op leftExpr rightExpr ->
159 Binop op leftExpr rightExpr ->
164 binop op leftExpr rightExpr
160 binop op leftExpr rightExpr
166− Lambda _ _ ->
162+ Function args body ->
167− generateFunction (Expr.collectLambdas annotatedExpr)
163+ generateFunction args body
169− App _ _ ->
165+ Call func args ->
170− generateApplication tcc annotatedExpr
166+ let
168+ aN = "A" ++ show arity
170+ do jsFunc <- generateJsExpr func
171+ jsArgs <- mapM generateJsExpr args
173+ if 2 <= arity && arity <= 9 then
174+ ref aN `call` (jsFunc:jsArgs)
176+ foldl1 (<|) (jsFunc:jsArgs)
178+ TailCall name argNames args ->
180+ reassign name tempName =
181+ ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
183+ do args' <- mapM generateJsExpr args
184+ tempNames <- mapM (\_ -> Var.fresh) args
186+ VarDeclStmt () (zipWith varDecl tempNames args')
187+ : zipWith reassign argNames tempNames
188+ ++ [ContinueStmt () (Just (Id () name))]
172 Let defs body ->
190 Let defs body ->
173− generateLet tcc defs body
191+ do stmts <- mapM generateDef defs
192+ code <- generateCode body
193+ jsBlock (stmts ++ toStatementList code)
175 If branches finally ->
195 If branches finally ->
176− generateIf tcc branches finally
196+ generateIf branches finally
178− Case expr branches ->
198+ Case root decisionTree branches ->
179− generateCase tcc expr branches
199+ JsBlock <$> generateCase root decisionTree branches
181 ExplicitList elements ->
201 ExplicitList elements ->
182− do jsElements <- mapM toJsExpr elements
202+ do jsElements <- mapM generateJsExpr elements
183 jsExpr $ BuiltIn.list jsElements
203 jsExpr $ BuiltIn.list jsElements
185 Data tag members ->
205 Data tag members ->
186− do jsMembers <- mapM toJsExpr members
206+ do jsMembers <- mapM generateJsExpr members
187 jsExpr $ ObjectLit () (ctor : fields jsMembers)
207 jsExpr $ ObjectLit () (ctor : fields jsMembers)
189 ctor = (prop "ctor", string tag)
209 ctor = (prop "ctor", string tag)
191 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
211 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
213+ DataAccess dataExpr index ->
214+ do jsDataExpr <- generateJsExpr dataExpr
215+ jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
193 GLShader _uid src _tipe ->
217 GLShader _uid src _tipe ->
194− jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
218+ jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (L.Str src))]
196 Port impl ->
220 Port impl ->
197 case impl of
221 case impl of
198− In name portType ->
222+ Expr.In name portType ->
199 jsExpr (Port.inbound name portType)
223 jsExpr (Port.inbound name portType)
201− Out name expr portType ->
225+ Expr.Out name expr portType ->
202− do expr' <- toJsExpr expr
226+ do expr' <- generateJsExpr expr
203 jsExpr (Port.outbound name expr' portType)
227 jsExpr (Port.outbound name expr' portType)
205− Task name expr portType ->
229+ Expr.Task name expr portType ->
206− do expr' <- toJsExpr expr
230+ do expr' <- generateJsExpr expr
207 jsExpr (Port.task name expr' portType)
231 jsExpr (Port.task name expr' portType)
209− Crash details ->
233+ Crash region maybeCaseCrashValue ->
210− jsExpr $ Crash.crash details
234+ jsExpr $ BuiltIn.crash region maybeCaseCrashValue
213-- FUNCTIONS
237-- FUNCTIONS
215−generateFunction :: ([P.Optimized], Opt.Expr) -> State Int Code
239+generateFunction :: [String] -> Opt.Expr -> State Int Code
216−generateFunction (args, initialBody) =
240+generateFunction args body =
217− do (argVars, patternDefs) <- destructuredArgs args
241+ do code <- generateCode body
218− code <- generateLet Nothing patternDefs initialBody
219− jsExpr (generateFunctionWithArity argVars code)
242+ jsExpr (generateFunctionWithArity args code)
222−generateTailFunction :: String -> ([P.Optimized], Opt.Expr) -> State Int (Expression ())
245+generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
223−generateTailFunction name (args, initialBody) =
246+generateTailFunction name args body =
224− do (argVars, patternDefs) <- destructuredArgs args
247+ do code <- generateCode body
225− label <- Id () <$> Case.newVar
248+ return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
226− code <- generateLet (Just (name, argVars, label)) patternDefs initialBody
249+ LabelledStmt ()
227− let whileLoop =
250+ (Id () name)
228− JsBlock [ LabelledStmt () label (WhileStmt () (BoolLit () True) (toStatement code)) ]
251+ (WhileStmt () (BoolLit () True) (toStatement code))
229− return (generateFunctionWithArity argVars whileLoop)
232generateFunctionWithArity :: [String] -> Code -> Expression ()
254generateFunctionWithArity :: [String] -> Code -> Expression ()
@@ -247,105 +269,16 @@ generateFunctionWithArity args code =
247 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
269 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
250−destructuredArgs :: [P.Optimized] -> State Int ([String], [Opt.Def])
251−destructuredArgs args =
252− do (argVars, maybePatternDefs) <- unzip <$> mapM destructPattern args
253− return (argVars, Maybe.catMaybes maybePatternDefs)
256−destructPattern :: P.Optimized -> State Int (String, Maybe Opt.Def)
257−destructPattern pattern@(A.A ann pat) =
260− return (Var.safe x, Nothing)
263− do arg <- Case.newVar
266− , Just $ Opt.Definition Opt.dummyFacts pattern (A.A ann (localVar arg))
272−generateApplication :: TailCallContext -> Opt.Expr -> State Int Code
273−generateApplication tcc expr =
276− Expr.collectApps expr
281− reassign name tempName =
282− ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
287− case isTailCall tcc func arity of
288− Just (argNames, label) ->
289− do args' <- mapM toJsExpr args
290− tempNames <- mapM (\_ -> Case.newVar) args
292− VarDeclStmt () (zipWith varDecl tempNames args')
293− : zipWith reassign argNames tempNames
294− ++ [ContinueStmt () (Just label)]
297− do func' <- toJsExpr func
298− args' <- mapM toJsExpr args
300− if 2 <= arity && arity <= 9 then
301− ref aN `call` (func':args')
303− foldl1 (<|) (func':args')
306−isTailCall :: TailCallContext -> Opt.Expr -> Int -> Maybe ([String], Label)
307−isTailCall tcc (A.A _ func) arity =
309− (Var (Var.Canonical Var.Local name), Just (tcName, tcArgs, tcLabel)) ->
310− if name == tcName && length tcArgs == arity then
311− Just (tcArgs, tcLabel)
315− (Var (Var.Canonical (Var.TopLevel _) name), Just (tcName, tcArgs, tcLabel)) ->
316− if name == tcName && length tcArgs == arity then
317− Just (tcArgs, tcLabel)
332−generateLet tcc givenDefs givenBody =
333− do let (defs, body) = flattenLets givenDefs givenBody
334− stmts <- concat <$> mapM defToStatements defs
335− code <- exprToCode tcc body
336− jsBlock (stmts ++ toStatementList code)
339-- GENERATE IFS
272-- GENERATE IFS
341−generateIf :: TailCallContext -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
274+generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
342−generateIf tcc givenBranches givenFinally =
275+generateIf givenBranches givenFinally =
344 (branches, finally) =
277 (branches, finally) =
345 crushIfs givenBranches givenFinally
278 crushIfs givenBranches givenFinally
347 convertBranch (condition, expr) =
280 convertBranch (condition, expr) =
348− (,) <$> toJsExpr condition <*> exprToCode tcc expr
281+ (,) <$> generateJsExpr condition <*> generateCode expr
350 ifExpression (condition, branch) otherwise =
283 ifExpression (condition, branch) otherwise =
351 CondExpr () condition branch otherwise
284 CondExpr () condition branch otherwise
@@ -354,7 +287,7 @@ generateIf tcc givenBranches givenFinally =
354 IfStmt () condition branch otherwise
287 IfStmt () condition branch otherwise
356 do jsBranches <- mapM convertBranch branches
289 do jsBranches <- mapM convertBranch branches
357− jsFinally <- exprToCode tcc finally
290+ jsFinally <- generateCode finally
359 if any isBlock (jsFinally : map snd jsBranches)
292 if any isBlock (jsFinally : map snd jsBranches)
@@ -380,263 +313,146 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
380 case unvisitedBranches of
313 case unvisitedBranches of
382 case finally of
315 case finally of
383− A.A _ (If subBranches subFinally) ->
316+ If subBranches subFinally ->
384 crushIfsHelp visitedBranches subBranches subFinally
317 crushIfsHelp visitedBranches subBranches subFinally
387 (reverse visitedBranches, finally)
320 (reverse visitedBranches, finally)
389− (A.A _ (Literal (Boolean True)), branch) : _ ->
322+ (Literal (L.Boolean True), branch) : _ ->
390 crushIfsHelp visitedBranches [] branch
323 crushIfsHelp visitedBranches [] branch
392 visiting : unvisited ->
325 visiting : unvisited ->
393 crushIfsHelp (visiting : visitedBranches) unvisited finally
326 crushIfsHelp (visiting : visitedBranches) unvisited finally
397−-- DEFINITIONS
331+generateCase
333+ -> DT.DecisionTree Opt.Jump
334+ -> [(Int, Opt.Branch)]
399−defToStatements :: Opt.Def -> State Int [Statement ()]
335+ -> State Int [Statement ()]
400−defToStatements (Opt.Definition facts pattern expr) =
336+generateCase root decisionTree jumpBranches =
401− case Opt.tailRecursionDetails facts of
337+ do decider <- generateDecisionTree root decisionTree
402− Just name ->
338+ foldM (goto root) decider jumpBranches
403− do func <- generateTailFunction name (Expr.collectLambdas expr)
404− return [ VarDeclStmt () [ varDecl name func ] ]
407− defToStatementsHelp facts pattern =<< toJsExpr expr
414− -> State Int [Statement ()]
341+goto :: String -> [Statement ()] -> (Int, Opt.Branch) -> State Int [Statement ()]
415−defToStatementsHelp facts annPattern@(A.A _ pattern) jsExpr =
342+goto root decider (target, branch) =
417− define x =
344+ deciderStmt =
418− varDecl x jsExpr
345+ LabelledStmt ()
346+ (targetLabel root target)
347+ (DoWhileStmt () (BlockStmt () decider) (BoolLit () False))
420− case pattern of
349+ do stmts <- generateBranch root branch
421− P.Var x ->
350+ return (deciderStmt : stmts)
424− op = LBracket () (ref "_op") (string x)
426− return [ ExprStmt () $ AssignExpr () OpAssign op jsExpr ]
428− return [ VarDeclStmt () [ define (Var.safe x) ] ]
433− varDecl name (obj ["$",name])
435− return [ VarDeclStmt () (define "$" : map setField fields) ]
437− P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
438− return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
440− vars = getVars patterns
443− A.A _ (P.Var x) : rest ->
444− (Var.safe x :) `fmap` getVars rest
450− decl x n = varDecl x (obj ["$","_" ++ show n])
452− | Help.isTuple name = define "$" : vars
453− | otherwise = define "_raw" : safeAssign : vars
455− safeAssign = varDecl "$" (CondExpr () if' (ref "_raw") exception)
456− if' = InfixExpr () OpStrictEq (obj ["_raw","ctor"]) (string name)
457− exception = Crash.crash (Crash.IncompletePatternMatch (error "TODO"))
460− do defs' <- concat <$> mapM toDef vars
461− return (VarDeclStmt () [define "_"] : defs')
463− vars = P.boundVarList annPattern
464− mkVar = A.A () . localVar
466− let expr = A.A () $ Case (mkVar "_") [(annPattern, mkVar y)]
467− pat = A.A () (P.Var y)
469− defToStatements (Opt.Definition facts pat expr)
472−-- CASE EXPRESSIONS
353+targetLabel :: String -> Int -> Id ()
354+targetLabel root target =
355+ Id () (root ++ "_" ++ show target)
474−generateCase :: TailCallContext -> Opt.Expr -> [(P.Optimized, Opt.Expr)] -> State Int Code
475−generateCase tcc expr branches =
476− do (tempVar, initialMatch) <-
477− Case.toMatch branches
479− (revisedMatch, stmt) <-
481− A.A _ (Var (Var.Canonical Var.Local x)) ->
482− return (Case.matchSubst [(tempVar, Var.safe x)] initialMatch, [])
484− A.A _ (Var (Var.Canonical (Var.TopLevel _) x)) ->
485− return (Case.matchSubst [(tempVar, Var.safe x)] initialMatch, [])
488− do expr' <- toJsExpr expr
489− return (initialMatch, [VarDeclStmt () [varDecl tempVar expr']])
491− match' <- match tcc revisedMatch
493− jsBlock (stmt ++ match')
496−match :: TailCallContext -> Case.Match -> State Int [Statement ()]
499− Case.Match name clauses mtch' ->
500− do (isChars, clauses') <- unzip <$> mapM (clause tcc name) clauses
501− mtch'' <- match tcc mtch'
502− return (SwitchStmt () (format isChars (access name)) clauses' : mtch'')
506− Case.Clause (Right _) _ _ ->
512− if any isLiteral clauses then
515− obj (Help.splitDots name ++ ["ctor"])
517− format isChars expr =
519− InfixExpr () OpAdd expr (string "")
524− return [ ExprStmt () (Crash.crash (Crash.IncompletePatternMatch (error "TODO"))) ]
527− return [BreakStmt () Nothing]
530− toStatementList <$> exprToCode tcc expr
533− concat <$> mapM (match tcc) (dropEnd [] ms)
535− dropEnd acc [] = acc
536− dropEnd acc (m:ms) =
538− Case.Other _ -> acc ++ [m]
539− _ -> dropEnd (acc ++ [m]) ms
542−clause :: TailCallContext -> String -> Case.Clause -> State Int (Bool, CaseClause ())
543−clause tcc variable (Case.Clause value vars mtch) =
544− do statemens <- match tcc (Case.matchSubst (zip vars vars') mtch)
545− return ((,) isChar (CaseClause () pattern statemens))
548− map (\n -> variable ++ "._" ++ show n) [0..]
550− (isChar, pattern) =
358+generateDecisionTree :: String -> DT.DecisionTree Opt.Jump -> State Int [Statement ()]
551− case value of
359+generateDecisionTree root decisionTree =
552− Right (Chr c) -> (True, string [c])
555− case value of
360+ case decisionTree of
556− Right (Boolean b) -> BoolLit () b
361+ DT.Match (Opt.Inline branch) ->
557− Right lit -> Literal.literal lit
362+ generateBranch root branch
558− Left (Var.Canonical _ name) ->
364+ DT.Match (Opt.Jump target) ->
365+ return [ BreakStmt () (Just (targetLabel root target)) ]
562−flattenLets :: [Opt.Def] -> Opt.Expr -> ([Opt.Def], Opt.Expr)
367+ DT.Decision testPath edges fallback ->
563−flattenLets defs lexpr@(A.A _ expr) =
368+ do accessExpr <- generateJsExpr (pathToExpr root testPath)
565− Let ds body -> flattenLets (defs ++ ds) body
371+ case fst (head edges) of
373+ DotRef () accessExpr (Id () "ctor")
569−-- BINARY OPERATORS
375+ DT.Literal _ ->
571−binop
378+ caseClauses <- mapM (edgeToCaseClause root) edges
572− :: Var.Canonical
379+ caseDefault <- fallbackToDefault root fallback
576−binop func left right
577− | func == Var.Canonical Var.BuiltIn "::" =
578− toCode (A.A () (Data "::" [left,right]))
580− | func == forwardCompose =
381+ return [ SwitchStmt () testExpr (caseClauses ++ caseDefault) ]
581− compose (collectLeftAssoc forwardCompose left right)
583− | func == backwardCompose =
584− compose (collectRightAssoc backwardCompose left right)
586− | func == forwardApply =
384+edgeToCaseClause :: String -> (DT.Test, DT.DecisionTree Opt.Jump) -> State Int (CaseClause ())
587− pipe (collectLeftAssoc forwardApply left right)
385+edgeToCaseClause root (test, subTree) =
386+ CaseClause () (testToExpr test) <$> generateDecisionTree root subTree
589− | func == backwardApply =
590− pipe (collectRightAssoc backwardApply left right)
592− | otherwise =
389+testToExpr :: DT.Test -> Expression ()
593− do jsLeft <- toJsExpr left
390+testToExpr test =
594− jsRight <- toJsExpr right
391+ case test of
595− jsExpr (makeExpr func jsLeft jsRight)
392+ DT.Constructor (Var.Canonical _ tag) ->
395+ DT.Literal (L.Chr char) ->
598−-- CONTROL FLOW OPERATOR HELPERS
398+ DT.Literal lit ->
600−apply :: Expression () -> Expression () -> Expression ()
402+fallbackToDefault :: String -> Maybe (DT.DecisionTree Opt.Jump) -> State Int [CaseClause ()]
403+fallbackToDefault root fallback =
605−compose :: [Opt.Expr] -> State Int Code
408+ Just subTree ->
606−compose functions =
409+ do stmts <- generateDecisionTree root subTree
607− do jsFunctions <- mapM toJsExpr functions
410+ return [ CaseDefault () stmts ]
608− jsExpr $ ["$"] ==> List.foldl' apply (ref "$") jsFunctions
611−pipe :: [Opt.Expr] -> State Int Code
413+generateBranch :: String -> Opt.Branch -> State Int [Statement ()]
612−pipe expressions =
414+generateBranch root (Opt.Branch substitutions expr) =
613− do (value:functions) <- mapM toJsExpr expressions
415+ do subts <- mapM (loadPath root) substitutions
614− jsExpr $ List.foldl' apply value functions
416+ code <- generateCode expr
417+ return (subts ++ toStatementList code)
617−forwardCompose :: Var.Canonical
420+loadPath :: String -> (String, DT.Path) -> State Int (Statement ())
618−forwardCompose =
421+loadPath root (name, path) =
619− inBasics ">>"
422+ do jsAccessExpr <- generateJsExpr (pathToExpr root path)
423+ return $ VarDeclStmt () [ varDecl name jsAccessExpr ]
622−backwardCompose :: Var.Canonical
426+pathToExpr :: String -> DT.Path -> Opt.Expr
623−backwardCompose =
427+pathToExpr root fullPath =
624− inBasics "<<"
428+ go (Opt.Var (Var.local root)) fullPath
432+ DT.Position index subpath ->
433+ go (Opt.DataAccess expr index) subpath
435+ DT.Field field subpath ->
436+ go (Opt.Access expr field) subpath
627−forwardApply :: Var.Canonical
438+ DT.Empty ->
628−forwardApply =
439+ expr
632−backwardApply :: Var.Canonical
637−inBasics :: String -> Var.Canonical
448+ :: Var.Canonical
638−inBasics name =
449+ -> Opt.Expr
639− Var.inCore ["Basics"] name
450+ -> Opt.Expr
452+binop func left right =
453+ do jsLeft <- generateJsExpr left
454+ jsRight <- generateJsExpr right
455+ jsExpr (makeExpr func jsLeft jsRight)
642-- BINARY OPERATOR HELPERS
458-- BINARY OPERATOR HELPERS
@@ -676,7 +492,6 @@ infixOps =
676specialOps :: [(String, Expression () -> Expression () -> Expression ())]
492specialOps :: [(String, Expression () -> Expression () -> Expression ())]
677specialOps =
493specialOps =
678 [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
494 [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
679− , (,) "|>" $ flip (<|)
680 , (,) "==" $ \a b -> BuiltIn.eq a b
495 , (,) "==" $ \a b -> BuiltIn.eq a b
681 , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (BuiltIn.eq a b)
496 , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (BuiltIn.eq a b)
682 , (,) "<" $ cmp OpLT 0
497 , (,) "<" $ cmp OpLT 0
@@ -690,38 +505,3 @@ specialOps =
690cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
505cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
691cmp op n a b =
506cmp op n a b =
692 InfixExpr () op (BuiltIn.compare a b) (IntLit () n)
507 InfixExpr () op (BuiltIn.compare a b) (IntLit () n)
695−-- BINARY OPERATOR COLLECTORS
697−-- (h << g << f) becomes [f, g, h] which is the order you want for doing stuff
698−collectRightAssoc :: Var.Canonical -> Opt.Expr -> Opt.Expr -> [Opt.Expr]
699−collectRightAssoc desiredOp left right =
700− collectRightAssocHelp desiredOp [left] right
703−collectRightAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
704−collectRightAssocHelp desiredOp exprList expr =
706− A.A _ (Binop op left right) | op == desiredOp ->
707− collectRightAssocHelp desiredOp (left : exprList) right
713−-- (f >> g >> h) becomes [f, g, h] which is the order you want for doing stuff
714−collectLeftAssoc :: Var.Canonical -> Opt.Expr -> Opt.Expr -> [Opt.Expr]
715−collectLeftAssoc desiredOp left right =
716− collectLeftAssocHelp desiredOp [right] left
719−collectLeftAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
720−collectLeftAssocHelp desiredOp exprList expr =
722− A.A _ (Binop op left right) | op == desiredOp ->
723− collectLeftAssocHelp desiredOp (right : exprList) left