@@ -2,34 +2,34 @@ module Generate.JavaScript (generate) where
22
33import Control.Applicative ((<$>),(<*>))
44import Control.Arrow (first, second, (***))
5−import Control.Monad.State
5+import Control.Monad.State as State
66import qualified Data.List as List
77import qualified Data.Map as Map
8−import qualified Data.Maybe as Maybe
8+import Language.ECMAScript3.PrettyPrint as ES
99import Language.ECMAScript3.Syntax
10+import qualified Text.PrettyPrint.Leijen as PP
1011
11−import AST.Expression.General as Expr
12−import qualified AST.Expression.Optimized as Opt
13−import qualified AST.Helpers as Help
14−import AST.Literal
12+import qualified AST.Expression.General as Expr
13+import AST.Expression.Optimized as Opt
14+import qualified AST.Literal as L
1515import qualified AST.Module as Module
1616import qualified AST.Module.Name as ModuleName
17−import qualified AST.Pattern as P
1817import qualified AST.Variable as Var
1918import Generate.JavaScript.Helpers as Help
2019import qualified Generate.JavaScript.BuiltIn as BuiltIn
21−import qualified Generate.JavaScript.Crash as Crash
2220import qualified Generate.JavaScript.Literal as Literal
2321import qualified Generate.JavaScript.Port as Port
2422import qualified Generate.JavaScript.Variable as Var
25−import qualified Optimize.Cases as Case
26−import qualified Reporting.Annotation as A
27−import qualified Reporting.Crash as Crash
23+import qualified Optimize.Patterns.DecisionTree as DT
2824
2925
3026generate :: Module.Optimized -> String
31−generate modul =
32− error "TODO" modul exprToCode
27+generate definitions =
28+ let
29+ stmts =
30+ State.evalState (mapM generateDef definitions) 0
31+ in
32+ PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint stmts)) ""
3333
3434
3535-- CODE CHUNKS
@@ -81,39 +81,35 @@ toExpr code =
8181 case code of
8282 JsExpr expr ->
8383 expr
84+
8485 JsBlock stmts ->
8586 function [] stmts `call` []
8687
8788
88−-- TAIL CALL CONTEXT
89+-- DEFINITIONS
8990
90−type TailCallContext =
91− Maybe (String, [String], Label)
91+generateDef :: Opt.Def -> State Int (Statement ())
92+generateDef def =
93+ do (home, name, jsBody) <-
94+ case def of
95+ Opt.TailDef (Opt.Facts home _) name argNames body ->
96+ (,,) home name <$> generateTailFunction name argNames body
9297
98+ Opt.Def (Opt.Facts home _) name body ->
99+ (,,) home name <$> generateJsExpr body
93100
94−type Label =
95− Id ()
101+ return (VarDeclStmt () [ varDecl (Var.defName home name) jsBody ])
96102
97103
98104-- EXPRESSIONS
99105
100−toJsExpr :: Opt.Expr -> State Int (Expression ())
101−toJsExpr =
102− exprToJsExpr Nothing
103−
106+generateJsExpr :: Opt.Expr -> State Int (Expression ())
107+generateJsExpr optExpr =
108+ toExpr <$> generateCode optExpr
104109
105−toCode :: Opt.Expr -> State Int Code
106−toCode =
107− exprToCode Nothing
108110
109−
110−exprToJsExpr :: TailCallContext -> Opt.Expr -> State Int (Expression ())
111−exprToJsExpr tcc canonicalExpr =
112− toExpr <$> exprToCode tcc canonicalExpr
113−
114−
115−exprToCode :: TailCallContext -> Opt.Expr -> State Int Code
116−exprToCode tcc annotatedExpr@(A.A _ expr) =
111+generateCode :: Opt.Expr -> State Int Code
112+generateCode expr =
117113 case expr of
118114 Var var ->
119115 jsExpr $ Var.canonical var
@@ -122,28 +118,28 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
122118 jsExpr (Literal.literal lit)
123119
124120 Range lo hi ->
125− do lo' <- toJsExpr lo
126− hi' <- toJsExpr hi
121+ do lo' <- generateJsExpr lo
122+ hi' <- generateJsExpr hi
127123 jsExpr $ BuiltIn.range lo' hi'
128124
129125 Access record field ->
130− do record' <- toJsExpr record
126+ do record' <- generateJsExpr record
131127 jsExpr $ DotRef () record' (var (Var.safe field))
132128
133129 Update record fields ->
134130 let
135131 fieldToJs (field, value) =
136− do jsValue <- toJsExpr value
132+ do jsValue <- generateJsExpr value
137133 return (Var.safe field, jsValue)
138134 in
139− do jsRecord <- toJsExpr record
135+ do jsRecord <- generateJsExpr record
140136 jsFields <- mapM fieldToJs fields
141137 jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
142138
143139 Record fields ->
144140 do fields' <-
145141 forM fields $ \(field, e) ->
146− (,) (Var.safe field) <$> toJsExpr e
142+ (,) (Var.safe field) <$> generateJsExpr e
147143
148144 let fieldMap =
149145 List.foldl' combine Map.empty fields'
@@ -163,70 +159,96 @@ exprToCode tcc annotatedExpr@(A.A _ expr) =
163159 Binop op leftExpr rightExpr ->
164160 binop op leftExpr rightExpr
165161
166− Lambda _ _ ->
167− generateFunction (Expr.collectLambdas annotatedExpr)
162+ Function args body ->
163+ generateFunction args body
168164
169− App _ _ ->
170− generateApplication tcc annotatedExpr
165+ Call func args ->
166+ let
167+ arity = length args
168+ aN = "A" ++ show arity
169+ in
170+ do jsFunc <- generateJsExpr func
171+ jsArgs <- mapM generateJsExpr args
172+ jsExpr $
173+ if 2 <= arity && arity <= 9 then
174+ ref aN `call` (jsFunc:jsArgs)
175+ else
176+ foldl1 (<|) (jsFunc:jsArgs)
177+
178+ TailCall name argNames args ->
179+ let
180+ reassign name tempName =
181+ ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
182+ in
183+ do args' <- mapM generateJsExpr args
184+ tempNames <- mapM (\_ -> Var.fresh) args
185+ jsBlock $
186+ VarDeclStmt () (zipWith varDecl tempNames args')
187+ : zipWith reassign argNames tempNames
188+ ++ [ContinueStmt () (Just (Id () name))]
171189
172190 Let defs body ->
173− generateLet tcc defs body
191+ do stmts <- mapM generateDef defs
192+ code <- generateCode body
193+ jsBlock (stmts ++ toStatementList code)
174194
175195 If branches finally ->
176− generateIf tcc branches finally
196+ generateIf branches finally
177197
178− Case expr branches ->
179− generateCase tcc expr branches
198+ Case root decisionTree branches ->
199+ JsBlock <$> generateCase root decisionTree branches
180200
181201 ExplicitList elements ->
182− do jsElements <- mapM toJsExpr elements
202+ do jsElements <- mapM generateJsExpr elements
183203 jsExpr $ BuiltIn.list jsElements
184204
185205 Data tag members ->
186− do jsMembers <- mapM toJsExpr members
206+ do jsMembers <- mapM generateJsExpr members
187207 jsExpr $ ObjectLit () (ctor : fields jsMembers)
188208 where
189209 ctor = (prop "ctor", string tag)
190210 fields =
191211 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
192212
213+ DataAccess dataExpr index ->
214+ do jsDataExpr <- generateJsExpr dataExpr
215+ jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
216+
193217 GLShader _uid src _tipe ->
194− jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
218+ jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (L.Str src))]
195219
196220 Port impl ->
197221 case impl of
198− In name portType ->
222+ Expr.In name portType ->
199223 jsExpr (Port.inbound name portType)
200224
201− Out name expr portType ->
202− do expr' <- toJsExpr expr
225+ Expr.Out name expr portType ->
226+ do expr' <- generateJsExpr expr
203227 jsExpr (Port.outbound name expr' portType)
204228
205− Task name expr portType ->
206− do expr' <- toJsExpr expr
229+ Expr.Task name expr portType ->
230+ do expr' <- generateJsExpr expr
207231 jsExpr (Port.task name expr' portType)
208232
209− Crash details ->
210− jsExpr $ Crash.crash details
233+ Crash region maybeCaseCrashValue ->
234+ jsExpr $ BuiltIn.crash region maybeCaseCrashValue
211235
212236
213237-- FUNCTIONS
214238
215−generateFunction :: ([P.Optimized], Opt.Expr) -> State Int Code
216−generateFunction (args, initialBody) =
217− do (argVars, patternDefs) <- destructuredArgs args
218− code <- generateLet Nothing patternDefs initialBody
219− jsExpr (generateFunctionWithArity argVars code)
239+generateFunction :: [String] -> Opt.Expr -> State Int Code
240+generateFunction args body =
241+ do code <- generateCode body
242+ jsExpr (generateFunctionWithArity args code)
220243
221244
222−generateTailFunction :: String -> ([P.Optimized], Opt.Expr) -> State Int (Expression ())
223−generateTailFunction name (args, initialBody) =
224− do (argVars, patternDefs) <- destructuredArgs args
225− label <- Id () <$> Case.newVar
226− code <- generateLet (Just (name, argVars, label)) patternDefs initialBody
227− let whileLoop =
228− JsBlock [ LabelledStmt () label (WhileStmt () (BoolLit () True) (toStatement code)) ]
229− return (generateFunctionWithArity argVars whileLoop)
245+generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
246+generateTailFunction name args body =
247+ do code <- generateCode body
248+ return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
249+ LabelledStmt ()
250+ (Id () name)
251+ (WhileStmt () (BoolLit () True) (toStatement code))
230252
231253
232254generateFunctionWithArity :: [String] -> Code -> Expression ()
@@ -247,105 +269,16 @@ generateFunctionWithArity args code =
247269 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
248270
249271
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)
254−
255−
256−destructPattern :: P.Optimized -> State Int (String, Maybe Opt.Def)
257−destructPattern pattern@(A.A ann pat) =
258− case pat of
259− P.Var x ->
260− return (Var.safe x, Nothing)
261−
262− _ ->
263− do arg <- Case.newVar
264− return
265− ( arg
266− , Just $ Opt.Definition Opt.dummyFacts pattern (A.A ann (localVar arg))
267− )
268−
269−
270−-- APPLICATIONS
271−
272−generateApplication :: TailCallContext -> Opt.Expr -> State Int Code
273−generateApplication tcc expr =
274− let
275− (func:args) =
276− Expr.collectApps expr
277−
278− arity =
279− length args
280−
281− reassign name tempName =
282− ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
283−
284− aN =
285− "A" ++ show arity
286− in
287− case isTailCall tcc func arity of
288− Just (argNames, label) ->
289− do args' <- mapM toJsExpr args
290− tempNames <- mapM (\_ -> Case.newVar) args
291− jsBlock $
292− VarDeclStmt () (zipWith varDecl tempNames args')
293− : zipWith reassign argNames tempNames
294− ++ [ContinueStmt () (Just label)]
295−
296− _ ->
297− do func' <- toJsExpr func
298− args' <- mapM toJsExpr args
299− jsExpr $
300− if 2 <= arity && arity <= 9 then
301− ref aN `call` (func':args')
302− else
303− foldl1 (<|) (func':args')
304−
305−
306−isTailCall :: TailCallContext -> Opt.Expr -> Int -> Maybe ([String], Label)
307−isTailCall tcc (A.A _ func) arity =
308− case (func, tcc) of
309− (Var (Var.Canonical Var.Local name), Just (tcName, tcArgs, tcLabel)) ->
310− if name == tcName && length tcArgs == arity then
311− Just (tcArgs, tcLabel)
312− else
313− Nothing
314−
315− (Var (Var.Canonical (Var.TopLevel _) name), Just (tcName, tcArgs, tcLabel)) ->
316− if name == tcName && length tcArgs == arity then
317− Just (tcArgs, tcLabel)
318− else
319− Nothing
320−
321− _ ->
322− Nothing
323−
324−
325−-- LET EXPRESSIONS
326−
327−generateLet
328− :: TailCallContext
329− -> [Opt.Def]
330− -> Opt.Expr
331− -> State Int Code
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)
337−
338−
339272-- GENERATE IFS
340273
341−generateIf :: TailCallContext -> [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
342−generateIf tcc givenBranches givenFinally =
274+generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
275+generateIf givenBranches givenFinally =
343276 let
344277 (branches, finally) =
345278 crushIfs givenBranches givenFinally
346279
347280 convertBranch (condition, expr) =
348− (,) <$> toJsExpr condition <*> exprToCode tcc expr
281+ (,) <$> generateJsExpr condition <*> generateCode expr
349282
350283 ifExpression (condition, branch) otherwise =
351284 CondExpr () condition branch otherwise
@@ -354,7 +287,7 @@ generateIf tcc givenBranches givenFinally =
354287 IfStmt () condition branch otherwise
355288 in
356289 do jsBranches <- mapM convertBranch branches
357− jsFinally <- exprToCode tcc finally
290+ jsFinally <- generateCode finally
358291
359292 if any isBlock (jsFinally : map snd jsBranches)
360293 then
@@ -380,263 +313,146 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
380313 case unvisitedBranches of
381314 [] ->
382315 case finally of
383− A.A _ (If subBranches subFinally) ->
316+ If subBranches subFinally ->
384317 crushIfsHelp visitedBranches subBranches subFinally
385318
386319 _ ->
387320 (reverse visitedBranches, finally)
388321
389− (A.A _ (Literal (Boolean True)), branch) : _ ->
322+ (Literal (L.Boolean True), branch) : _ ->
390323 crushIfsHelp visitedBranches [] branch
391324
392325 visiting : unvisited ->
393326 crushIfsHelp (visiting : visitedBranches) unvisited finally
394327
395328
329+-- CASE EXPRESSIONS
396330
397−-- DEFINITIONS
398−
399−defToStatements :: Opt.Def -> State Int [Statement ()]
400−defToStatements (Opt.Definition facts pattern expr) =
401− case Opt.tailRecursionDetails facts of
402− Just name ->
403− do func <- generateTailFunction name (Expr.collectLambdas expr)
404− return [ VarDeclStmt () [ varDecl name func ] ]
405−
406− Nothing ->
407− defToStatementsHelp facts pattern =<< toJsExpr expr
331+generateCase
332+ :: String
333+ -> DT.DecisionTree Opt.Jump
334+ -> [(Int, Opt.Branch)]
335+ -> State Int [Statement ()]
336+generateCase root decisionTree jumpBranches =
337+ do decider <- generateDecisionTree root decisionTree
338+ foldM (goto root) decider jumpBranches
408339
409340
410−defToStatementsHelp
411− :: Opt.Facts
412− -> P.Optimized
413− -> Expression ()
414− -> State Int [Statement ()]
415−defToStatementsHelp facts annPattern@(A.A _ pattern) jsExpr =
341+goto :: String -> [Statement ()] -> (Int, Opt.Branch) -> State Int [Statement ()]
342+goto root decider (target, branch) =
416343 let
417− define x =
418− varDecl x jsExpr
344+ deciderStmt =
345+ LabelledStmt ()
346+ (targetLabel root target)
347+ (DoWhileStmt () (BlockStmt () decider) (BoolLit () False))
419348 in
420− case pattern of
421− P.Var x ->
422− if Help.isOp x then
423− let
424− op = LBracket () (ref "_op") (string x)
425− in
426− return [ ExprStmt () $ AssignExpr () OpAssign op jsExpr ]
427− else
428− return [ VarDeclStmt () [ define (Var.safe x) ] ]
429−
430− P.Record fields ->
431− let
432− setField name =
433− varDecl name (obj ["$",name])
434− in
435− return [ VarDeclStmt () (define "$" : map setField fields) ]
436−
437− P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
438− return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
439− where
440− vars = getVars patterns
441− getVars patterns =
442− case patterns of
443− A.A _ (P.Var x) : rest ->
444− (Var.safe x :) `fmap` getVars rest
445− [] ->
446− Just []
447− _ ->
448− Nothing
449−
450− decl x n = varDecl x (obj ["$","_" ++ show n])
451− setup vars
452− | Help.isTuple name = define "$" : vars
453− | otherwise = define "_raw" : safeAssign : vars
454−
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"))
458−
459− _ ->
460− do defs' <- concat <$> mapM toDef vars
461− return (VarDeclStmt () [define "_"] : defs')
462− where
463− vars = P.boundVarList annPattern
464− mkVar = A.A () . localVar
465− toDef y =
466− let expr = A.A () $ Case (mkVar "_") [(annPattern, mkVar y)]
467− pat = A.A () (P.Var y)
468− in
469− defToStatements (Opt.Definition facts pat expr)
349+ do stmts <- generateBranch root branch
350+ return (deciderStmt : stmts)
470351
471352
472−-- CASE EXPRESSIONS
353+targetLabel :: String -> Int -> Id ()
354+targetLabel root target =
355+ Id () (root ++ "_" ++ show target)
473356
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
478−
479− (revisedMatch, stmt) <-
480− case expr of
481− A.A _ (Var (Var.Canonical Var.Local x)) ->
482− return (Case.matchSubst [(tempVar, Var.safe x)] initialMatch, [])
483−
484− A.A _ (Var (Var.Canonical (Var.TopLevel _) x)) ->
485− return (Case.matchSubst [(tempVar, Var.safe x)] initialMatch, [])
486−
487− _ ->
488− do expr' <- toJsExpr expr
489− return (initialMatch, [VarDeclStmt () [varDecl tempVar expr']])
490−
491− match' <- match tcc revisedMatch
492−
493− jsBlock (stmt ++ match')
494−
495−
496−match :: TailCallContext -> Case.Match -> State Int [Statement ()]
497−match tcc mtch =
498− case mtch of
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'')
503− where
504− isLiteral p =
505− case p of
506− Case.Clause (Right _) _ _ ->
507− True
508− _ ->
509− False
510−
511− access name =
512− if any isLiteral clauses then
513− obj [name]
514− else
515− obj (Help.splitDots name ++ ["ctor"])
516−
517− format isChars expr =
518− if or isChars then
519− InfixExpr () OpAdd expr (string "")
520− else
521− expr
522−
523− Case.Fail ->
524− return [ ExprStmt () (Crash.crash (Crash.IncompletePatternMatch (error "TODO"))) ]
525−
526− Case.Break ->
527− return [BreakStmt () Nothing]
528−
529− Case.Other expr ->
530− toStatementList <$> exprToCode tcc expr
531−
532− Case.Seq ms ->
533− concat <$> mapM (match tcc) (dropEnd [] ms)
534− where
535− dropEnd acc [] = acc
536− dropEnd acc (m:ms) =
537− case m of
538− Case.Other _ -> acc ++ [m]
539− _ -> dropEnd (acc ++ [m]) ms
540−
541−
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))
546− where
547− vars' =
548− map (\n -> variable ++ "._" ++ show n) [0..]
549357
550− (isChar, pattern) =
551− case value of
552− Right (Chr c) -> (True, string [c])
553− _ ->
554− (,) False $
555− case value of
556− Right (Boolean b) -> BoolLit () b
557− Right lit -> Literal.literal lit
558− Left (Var.Canonical _ name) ->
559− string name
358+generateDecisionTree :: String -> DT.DecisionTree Opt.Jump -> State Int [Statement ()]
359+generateDecisionTree root decisionTree =
360+ case decisionTree of
361+ DT.Match (Opt.Inline branch) ->
362+ generateBranch root branch
560363
364+ DT.Match (Opt.Jump target) ->
365+ return [ BreakStmt () (Just (targetLabel root target)) ]
561366
562−flattenLets :: [Opt.Def] -> Opt.Expr -> ([Opt.Def], Opt.Expr)
563−flattenLets defs lexpr@(A.A _ expr) =
564− case expr of
565− Let ds body -> flattenLets (defs ++ ds) body
566− _ -> (defs, lexpr)
367+ DT.Decision testPath edges fallback ->
368+ do accessExpr <- generateJsExpr (pathToExpr root testPath)
567369
370+ let testExpr =
371+ case fst (head edges) of
372+ DT.Constructor _ ->
373+ DotRef () accessExpr (Id () "ctor")
568374
569−-- BINARY OPERATORS
375+ DT.Literal _ ->
376+ accessExpr
570377
571−binop
572− :: Var.Canonical
573− -> Opt.Expr
574− -> Opt.Expr
575− -> State Int Code
576−binop func left right
577− | func == Var.Canonical Var.BuiltIn "::" =
578− toCode (A.A () (Data "::" [left,right]))
378+ caseClauses <- mapM (edgeToCaseClause root) edges
379+ caseDefault <- fallbackToDefault root fallback
579380
580− | func == forwardCompose =
581− compose (collectLeftAssoc forwardCompose left right)
381+ return [ SwitchStmt () testExpr (caseClauses ++ caseDefault) ]
582382
583− | func == backwardCompose =
584− compose (collectRightAssoc backwardCompose left right)
585383
586− | func == forwardApply =
587− pipe (collectLeftAssoc forwardApply left right)
384+edgeToCaseClause :: String -> (DT.Test, DT.DecisionTree Opt.Jump) -> State Int (CaseClause ())
385+edgeToCaseClause root (test, subTree) =
386+ CaseClause () (testToExpr test) <$> generateDecisionTree root subTree
588387
589− | func == backwardApply =
590− pipe (collectRightAssoc backwardApply left right)
591388
592− | otherwise =
593− do jsLeft <- toJsExpr left
594− jsRight <- toJsExpr right
595− jsExpr (makeExpr func jsLeft jsRight)
389+testToExpr :: DT.Test -> Expression ()
390+testToExpr test =
391+ case test of
392+ DT.Constructor (Var.Canonical _ tag) ->
393+ StringLit () tag
596394
395+ DT.Literal (L.Chr char) ->
396+ StringLit () [char]
597397
598−-- CONTROL FLOW OPERATOR HELPERS
398+ DT.Literal lit ->
399+ Literal.literal lit
599400
600−apply :: Expression () -> Expression () -> Expression ()
601−apply arg func =
602− func <| arg
603401
402+fallbackToDefault :: String -> Maybe (DT.DecisionTree Opt.Jump) -> State Int [CaseClause ()]
403+fallbackToDefault root fallback =
404+ case fallback of
405+ Nothing ->
406+ return []
604407
605−compose :: [Opt.Expr] -> State Int Code
606−compose functions =
607− do jsFunctions <- mapM toJsExpr functions
608− jsExpr $ ["$"] ==> List.foldl' apply (ref "$") jsFunctions
408+ Just subTree ->
409+ do stmts <- generateDecisionTree root subTree
410+ return [ CaseDefault () stmts ]
609411
610412
611−pipe :: [Opt.Expr] -> State Int Code
612−pipe expressions =
613− do (value:functions) <- mapM toJsExpr expressions
614− jsExpr $ List.foldl' apply value functions
413+generateBranch :: String -> Opt.Branch -> State Int [Statement ()]
414+generateBranch root (Opt.Branch substitutions expr) =
415+ do subts <- mapM (loadPath root) substitutions
416+ code <- generateCode expr
417+ return (subts ++ toStatementList code)
615418
616419
617−forwardCompose :: Var.Canonical
618−forwardCompose =
619− inBasics ">>"
420+loadPath :: String -> (String, DT.Path) -> State Int (Statement ())
421+loadPath root (name, path) =
422+ do jsAccessExpr <- generateJsExpr (pathToExpr root path)
423+ return $ VarDeclStmt () [ varDecl name jsAccessExpr ]
620424
621425
622−backwardCompose :: Var.Canonical
623−backwardCompose =
624− inBasics "<<"
426+pathToExpr :: String -> DT.Path -> Opt.Expr
427+pathToExpr root fullPath =
428+ go (Opt.Var (Var.local root)) fullPath
429+ where
430+ go expr path =
431+ case path of
432+ DT.Position index subpath ->
433+ go (Opt.DataAccess expr index) subpath
625434
435+ DT.Field field subpath ->
436+ go (Opt.Access expr field) subpath
626437
627−forwardApply :: Var.Canonical
628−forwardApply =
629− inBasics "|>"
438+ DT.Empty ->
439+ expr
630440
441+ DT.Alias ->
442+ expr
631443
632−backwardApply :: Var.Canonical
633−backwardApply =
634− inBasics "<|"
635444
445+-- BINARY OPERATORS
636446
637−inBasics :: String -> Var.Canonical
638−inBasics name =
639− Var.inCore ["Basics"] name
447+binop
448+ :: Var.Canonical
449+ -> Opt.Expr
450+ -> Opt.Expr
451+ -> State Int Code
452+binop func left right =
453+ do jsLeft <- generateJsExpr left
454+ jsRight <- generateJsExpr right
455+ jsExpr (makeExpr func jsLeft jsRight)
640456
641457
642458-- BINARY OPERATOR HELPERS
@@ -676,7 +492,6 @@ infixOps =
676492specialOps :: [(String, Expression () -> Expression () -> Expression ())]
677493specialOps =
678494 [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
679− , (,) "|>" $ flip (<|)
680495 , (,) "==" $ \a b -> BuiltIn.eq a b
681496 , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (BuiltIn.eq a b)
682497 , (,) "<" $ cmp OpLT 0
@@ -690,38 +505,3 @@ specialOps =
690505cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
691506cmp op n a b =
692507 InfixExpr () op (BuiltIn.compare a b) (IntLit () n)
693−
694−
695−-- BINARY OPERATOR COLLECTORS
696−
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
701−
702−
703−collectRightAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
704−collectRightAssocHelp desiredOp exprList expr =
705− case expr of
706− A.A _ (Binop op left right) | op == desiredOp ->
707− collectRightAssocHelp desiredOp (left : exprList) right
708−
709− _ ->
710− expr : exprList
711−
712−
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
717−
718−
719−collectLeftAssocHelp :: Var.Canonical -> [Opt.Expr] -> Opt.Expr -> [Opt.Expr]
720−collectLeftAssocHelp desiredOp exprList expr =
721− case expr of
722− A.A _ (Binop op left right) | op == desiredOp ->
723− collectLeftAssocHelp desiredOp (right : exprList) left
724−
725− _ ->
726− expr : exprList
727−