@@ -1,7 +1,7 @@
1module Generate.JavaScript (generate) where
1module Generate.JavaScript (generate) where
3import Control.Applicative ((<$>),(<*>))
3import Control.Applicative ((<$>),(<*>))
4−import Control.Arrow (first,(***))
4+import Control.Arrow (first, second, (***))
5import Control.Monad.State
5import Control.Monad.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
@@ -21,9 +21,11 @@ import qualified AST.Variable as Var
21import Elm.Utils ((|>))
21import Elm.Utils ((|>))
22import Generate.JavaScript.Helpers as Help
22import Generate.JavaScript.Helpers as Help
23import qualified Generate.Cases as Case
23import qualified Generate.Cases as Case
24+import qualified Generate.JavaScript.Crash as Crash
24import qualified Generate.JavaScript.Port as Port
25import qualified Generate.JavaScript.Port as Port
25import qualified Generate.JavaScript.Variable as Var
26import qualified Generate.JavaScript.Variable as Var
26import qualified Reporting.Annotation as A
27import qualified Reporting.Annotation as A
28+import qualified Reporting.Crash as Crash
27import qualified Reporting.Region as R
29import qualified Reporting.Region as R
@@ -32,7 +34,7 @@ internalImports name =
32 [ varDecl "_N" (obj ["Elm","Native"])
34 [ varDecl "_N" (obj ["Elm","Native"])
33 , include "_U" "Utils"
35 , include "_U" "Utils"
34 , include "_L" "List"
36 , include "_L" "List"
35− , varDecl Help.localModuleName (string (Module.nameToString name))
37+ , varDecl Crash.localModuleName (string (Module.nameToString name))
38 include :: String -> String -> VarDecl ()
40 include :: String -> String -> VarDecl ()
@@ -60,53 +62,111 @@ literal lit =
60 Boolean b -> BoolLit () b
62 Boolean b -> BoolLit () b
68+ = JsExpr (Expression ())
69+ | JsBlock [Statement ()]
72+jsExpr :: Expression () -> State Int Code
77+jsBlock :: [Statement ()] -> State Int Code
82+isBlock :: Code -> Bool
89+toStatementList :: Code -> [Statement ()]
90+toStatementList code =
98+toStatement :: Code -> Statement ()
109+toExpr :: Code -> Expression ()
115+ function [] stmts `call` []
63-- EXPRESSIONS
118-- EXPRESSIONS
65−expression :: Canonical.Expr -> State Int (Expression ())
120+exprToJsExpr :: Canonical.Expr -> State Int (Expression ())
121+exprToJsExpr canonicalExpr =
122+ toExpr <$> exprToCode canonicalExpr
125+exprToCode :: Canonical.Expr -> State Int Code
66−expression annotatedExpr@(A.A region expr) =
126+exprToCode annotatedExpr@(A.A region expr) =
67 case expr of
127 case expr of
68 Var var ->
128 Var var ->
69− return $ Var.canonical var
129+ jsExpr $ Var.canonical var
71 Literal lit ->
131 Literal lit ->
72− return $ literal lit
132+ jsExpr $ literal lit
74 Range lo hi ->
134 Range lo hi ->
75− do lo' <- expression lo
135+ do lo' <- exprToJsExpr lo
76− hi' <- expression hi
136+ hi' <- exprToJsExpr hi
77− return $ _List "range" `call` [lo',hi']
137+ jsExpr $ _List "range" `call` [lo',hi']
79− Access e field ->
139+ Access record field ->
80− do e' <- expression e
140+ do record' <- exprToJsExpr record
81− return $ DotRef () e' (var (Var.varName field))
141+ jsExpr $ DotRef () record' (var (Var.varName field))
83− Remove e field ->
143+ Remove record field ->
84− do e' <- expression e
144+ do record' <- exprToJsExpr record
85− return $ _Utils "remove" `call` [ string (Var.varName field), e' ]
145+ jsExpr $ _Utils "remove" `call` [ string (Var.varName field), record' ]
87− Insert e field value ->
147+ Insert record field value ->
88− do value' <- expression value
148+ do value' <- exprToJsExpr value
89− e' <- expression e
149+ record' <- exprToJsExpr record
90− return $ _Utils "insert" `call` [ string (Var.varName field), value', e' ]
150+ jsExpr $ _Utils "insert" `call` [ string (Var.varName field), value', record' ]
92− Modify e fields ->
152+ Modify record fields ->
93− do e' <- expression e
153+ do record' <- exprToJsExpr record
94 fields' <-
154 fields' <-
95 forM fields $ \(field, value) ->
155 forM fields $ \(field, value) ->
96− do value' <- expression value
156+ do value' <- exprToJsExpr value
97 return $ ArrayLit () [ string (Var.varName field), value' ]
157 return $ ArrayLit () [ string (Var.varName field), value' ]
99− return $ _Utils "replace" `call` [ArrayLit () fields', e']
159+ jsExpr $ _Utils "replace" `call` [ArrayLit () fields', record']
101 Record fields ->
161 Record fields ->
102 do fields' <-
162 do fields' <-
103 forM fields $ \(field, e) ->
163 forM fields $ \(field, e) ->
104− (,) (Var.varName field) <$> expression e
164+ (,) (Var.varName field) <$> exprToJsExpr e
106 let fieldMap =
166 let fieldMap =
107 List.foldl' combine Map.empty fields'
167 List.foldl' combine Map.empty fields'
109− return $ ObjectLit () $ (prop "_", hidden fieldMap) : visible fieldMap
169+ jsExpr $ ObjectLit () $ (prop "_", hidden fieldMap) : visible fieldMap
111 combine record (field, value) =
171 combine record (field, value) =
112 Map.insertWith (++) field [value] record
172 Map.insertWith (++) field [value] record
@@ -118,102 +178,80 @@ expression annotatedExpr@(A.A region expr) =
118 visible fs =
178 visible fs =
119 map (first prop) (Map.toList (Map.map head fs))
179 map (first prop) (Map.toList (Map.map head fs))
121− Binop op e1 e2 ->
181+ Binop op leftExpr rightExpr ->
122− binop region op e1 e2
182+ binop region op leftExpr rightExpr
124 Lambda _ _ ->
184 Lambda _ _ ->
125 generateFunction (Expr.collectLambdas annotatedExpr)
185 generateFunction (Expr.collectLambdas annotatedExpr)
127− App e1 e2 ->
187+ App funcExpr argExpr ->
128− do func' <- expression func
188+ do func' <- exprToJsExpr func
129− args' <- mapM expression args
189+ args' <- mapM exprToJsExpr args
130− return $
190+ jsExpr $
131 case args' of
191 case args' of
132 [arg] -> func' <| arg
192 [arg] -> func' <| arg
133 _ | length args' <= 9 -> ref aN `call` (func':args')
193 _ | length args' <= 9 -> ref aN `call` (func':args')
134 | otherwise -> foldl1 (<|) (func':args')
194 | otherwise -> foldl1 (<|) (func':args')
136 aN = "A" ++ show (length args)
196 aN = "A" ++ show (length args)
137− (func, args) = getArgs e1 [e2]
197+ (func, args) = getArgs funcExpr [argExpr]
138 getArgs func args =
198 getArgs func args =
139 case func of
199 case func of
140 (A.A _ (App f arg)) -> getArgs f (arg : args)
200 (A.A _ (App f arg)) -> getArgs f (arg : args)
141 _ -> (func, args)
201 _ -> (func, args)
143 Let defs body ->
203 Let defs body ->
144− do (stmts, bodyExpr) <- generateLetPieces defs body
204+ generateLet defs body
145− return $ function [] (stmts ++ [ ret bodyExpr ]) `call` []
205+
148− MultiIf branches ->
206+ MultiIf branches finally ->
149− do branches' <- forM branches $ \(b,e) -> (,) <$> expression b <*> expression e
151− case last branches of
152− (A.A _ (Var (Var.Canonical (Var.Module ["Basics"]) "otherwise")), _) ->
154− (A.A _ (Literal (Boolean True)), _) ->
157− ifs branches' (throw "badIf" region)
159− safeIfs branches = ifs (init branches) (snd (last branches))
160− ifs branches finally = foldr iff finally branches
207+ generateIf branches finally
161− iff (if', then') else' = CondExpr () if' then' else'
208+
162−
209+ Case expr branches ->
163− Case e cases ->
210+ generateCase region expr branches
164− do (tempVar,initialMatch) <- Case.toMatch cases
211+
165− (revisedMatch, stmt) <-
167− A.A _ (Var (Var.Canonical Var.Local x)) ->
168− return (Case.matchSubst [(tempVar, Var.varName x)] initialMatch, [])
170− do e' <- expression e
171− return (initialMatch, [VarDeclStmt () [varDecl tempVar e']])
172− match' <- match region revisedMatch
173− return (function [] (stmt ++ match') `call` [])
175− ExplicitList es ->
212+ ExplicitList elements ->
176− do es' <- mapM expression es
213+ do jsElements <- mapM exprToJsExpr elements
177− return $ _List "fromArray" <| ArrayLit () es'
214+ jsExpr $ _List "fromArray" <| ArrayLit () jsElements
179− Data name es ->
216+ Data tag members ->
180− do es' <- mapM expression es
217+ do jsMembers <- mapM exprToJsExpr members
181− return $ ObjectLit () (ctor : fields es')
218+ jsExpr $ ObjectLit () (ctor : fields jsMembers)
183− ctor = (prop "ctor", string name)
220+ ctor = (prop "ctor", string tag)
185 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
222 zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
187 GLShader _uid src _tipe ->
224 GLShader _uid src _tipe ->
188− return $ ObjectLit () [(PropString () "src", literal (Str src))]
225+ jsExpr $ ObjectLit () [(PropString () "src", literal (Str src))]
190 Port impl ->
227 Port impl ->
191 case impl of
228 case impl of
192 In name portType ->
229 In name portType ->
193− return (Port.inbound name portType)
230+ jsExpr (Port.inbound name portType)
195 Out name expr portType ->
232 Out name expr portType ->
196− do expr' <- expression expr
233+ do expr' <- exprToJsExpr expr
197− return (Port.outbound name expr' portType)
234+ jsExpr (Port.outbound name expr' portType)
199 Task name expr portType ->
236 Task name expr portType ->
200− do expr' <- expression expr
237+ do expr' <- exprToJsExpr expr
201− return (Port.task name expr' portType)
238+ jsExpr (Port.task name expr' portType)
241+ jsExpr $ Crash.crash region details
204-- FUNCTIONS
244-- FUNCTIONS
207− :: ([P.CanonicalPattern], Canonical.Expr)
246+generateFunction :: ([P.CanonicalPattern], Canonical.Expr) -> State Int Code
208− -> State Int (Expression ())
209generateFunction (args, initialBody) =
247generateFunction (args, initialBody) =
210 do (argVars, patternDefs) <- destructuredArgs args
248 do (argVars, patternDefs) <- destructuredArgs args
211− (stmts, expr) <- generateLetPieces patternDefs initialBody
249+ code <- generateLet patternDefs initialBody
212− return (generateFunctionWithArity argVars stmts expr)
250+ jsExpr (generateFunctionWithArity argVars code)
215−generateFunctionWithArity :: [String] -> [Statement ()] -> Expression () -> Expression ()
253+generateFunctionWithArity :: [String] -> Code -> Expression ()
216−generateFunctionWithArity args stmts expr =
254+generateFunctionWithArity args code =
218 arity = length args
256 arity = length args
@@ -221,11 +259,11 @@ generateFunctionWithArity args stmts expr =
222 fN = "F" ++ show arity
260 fN = "F" ++ show arity
224− ref fN <| function args (stmts ++ [ret expr])
262+ ref fN <| function args (toStatementList code)
227 (lastArg:otherArgs) = reverse args
265 (lastArg:otherArgs) = reverse args
228− innerBody = function [lastArg] (stmts ++ [ret expr])
266+ innerBody = function [lastArg] (toStatementList code)
230 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
268 foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
@@ -252,70 +290,129 @@ destructPattern pattern@(A.A ann pat) =
253-- LET EXPRESSIONS
291-- LET EXPRESSIONS
255−generateLetPieces
293+generateLet
256 :: [Canonical.Def]
294 :: [Canonical.Def]
257 -> Canonical.Expr
295 -> Canonical.Expr
258− -> State Int ([Statement ()], Expression ())
296+ -> State Int Code
259−generateLetPieces givenDefs givenBody =
297+generateLet givenDefs givenBody =
260 do let (defs, body) = flattenLets givenDefs givenBody
298 do let (defs, body) = flattenLets givenDefs givenBody
261− stmts <- concat <$> mapM definition defs
304+ do stmts <- concat <$> mapM defToStatements defs
262− expr <- expression body
305+ code <- exprToCode body
263− return (stmts, expr)
306+ jsBlock (stmts ++ toStatementList code)
311+generateIf :: [(Canonical.Expr, Canonical.Expr)] -> Canonical.Expr -> State Int Code
312+generateIf branches finally =
314+ convertBranch (condition, expr) =
315+ (,) <$> exprToJsExpr condition <*> exprToCode expr
317+ ifExpression (condition, branch) otherwise =
318+ CondExpr () condition branch otherwise
320+ ifStatement (condition, branch) otherwise =
321+ IfStmt () condition branch otherwise
323+ do jsBranches <- mapM convertBranch branches
324+ jsFinally <- exprToCode finally
326+ if any isBlock (jsFinally : map snd jsBranches)
328+ jsBlock [ foldr ifStatement (toStatement jsFinally) (map (second toStatement) jsBranches) ]
330+ jsExpr (foldr ifExpression (toExpr jsFinally) (map (second toExpr) jsBranches))
266-- DEFINITIONS
333-- DEFINITIONS
268−definition :: Canonical.Def -> State Int [Statement ()]
335+defToStatements :: Canonical.Def -> State Int [Statement ()]
269−definition (Canonical.Definition annPattern expr@(A.A region _) _) =
336+defToStatements (Canonical.Definition pattern expr _) =
270− do expr' <- expression expr
337+ defToStatementsHelp pattern =<< exprToJsExpr expr
271− let assign x = varDecl x expr'
272− let (A.A patternRegion pattern) = annPattern
276− let op = LBracket () (ref "_op") (string x) in
277− return [ ExprStmt () $ AssignExpr () OpAssign op expr' ]
280− return [ VarDeclStmt () [ assign (Var.varName x) ] ]
283− let setField f = varDecl f (obj ["$",f]) in
284− return [ VarDeclStmt () (assign "$" : map setField fields) ]
286− P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
287− return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
289− vars = getVars patterns
292− A.A _ (P.Var x) : rest ->
293− (Var.varName x :) `fmap` getVars rest
299− decl x n = varDecl x (obj ["$","_" ++ show n])
301− | Help.isTuple name = assign "$" : vars
302− | otherwise = assign "_raw" : safeAssign : vars
304− safeAssign = varDecl "$" (CondExpr () if' (ref "_raw") exception)
305− if' = InfixExpr () OpStrictEq (obj ["_raw","ctor"]) (string name)
306− exception = Help.throw "badCase" region
340+defToStatementsHelp :: P.CanonicalPattern -> Expression () -> State Int [Statement ()]
341+defToStatementsHelp annPattern@(A.A patternRegion pattern) jsExpr =
350+ op = LBracket () (ref "_op") (string x)
352+ return [ ExprStmt () $ AssignExpr () OpAssign op jsExpr ]
354+ return [ VarDeclStmt () [ define (Var.varName x) ] ]
359+ varDecl name (obj ["$",name])
361+ return [ VarDeclStmt () (define "$" : map setField fields) ]
363+ P.Data (Var.Canonical _ name) patterns | vars /= Nothing ->
364+ return [ VarDeclStmt () (setup (zipWith decl (maybe [] id vars) [0..])) ]
366+ vars = getVars patterns
369+ A.A _ (P.Var x) : rest ->
370+ (Var.varName x :) `fmap` getVars rest
376+ decl x n = varDecl x (obj ["$","_" ++ show n])
378+ | Help.isTuple name = define "$" : vars
379+ | otherwise = define "_raw" : safeAssign : vars
381+ safeAssign = varDecl "$" (CondExpr () if' (ref "_raw") exception)
382+ if' = InfixExpr () OpStrictEq (obj ["_raw","ctor"]) (string name)
383+ exception = Crash.crash patternRegion Crash.IncompletePatternMatch
309− do defs' <- concat <$> mapM toDef vars
386+ do defs' <- concat <$> mapM toDef vars
310− return (VarDeclStmt () [assign "_"] : defs')
387+ return (VarDeclStmt () [define "_"] : defs')
312− vars = P.boundVarList annPattern
389+ vars = P.boundVarList annPattern
313− mkVar = A.A region . localVar
390+ mkVar = A.A patternRegion . localVar
314− toDef y =
391+ toDef y =
315− let expr = A.A region $ Case (mkVar "_") [(annPattern, mkVar y)]
392+ let expr = A.A patternRegion $ Case (mkVar "_") [(annPattern, mkVar y)]
316− pat = A.A patternRegion (P.Var y)
393+ pat = A.A patternRegion (P.Var y)
318− definition (Canonical.Definition pat expr Nothing)
395+ defToStatements (Canonical.Definition pat expr Nothing)
400+generateCase :: R.Region -> Canonical.Expr -> [(P.CanonicalPattern, Canonical.Expr)] -> State Int Code
401+generateCase region expr branches =
402+ do (tempVar, initialMatch) <-
403+ Case.toMatch branches
405+ (revisedMatch, stmt) <-
407+ A.A _ (Var (Var.Canonical Var.Local x)) ->
408+ return (Case.matchSubst [(tempVar, Var.varName x)] initialMatch, [])
410+ do expr' <- exprToJsExpr expr
411+ return (initialMatch, [VarDeclStmt () [varDecl tempVar expr']])
413+ match' <- match region revisedMatch
415+ jsBlock (stmt ++ match')
321match :: R.Region -> Case.Match -> State Int [Statement ()]
418match :: R.Region -> Case.Match -> State Int [Statement ()]
@@ -328,26 +425,31 @@ match region mtch =
329 isLiteral p =
426 isLiteral p =
330 case p of
427 case p of
331− Case.Clause (Right _) _ _ -> True
428+ Case.Clause (Right _) _ _ ->
332− _ -> False
431+ False
334− access name
433+ access name =
335− | any isLiteral clauses = obj [name]
434+ if any isLiteral clauses then
336− | otherwise = obj (Help.splitDots name ++ ["ctor"])
437+ obj (Help.splitDots name ++ ["ctor"])
338− format isChars e
439+ format isChars expr =
339− | or isChars = InfixExpr () OpAdd e (string "")
441+ InfixExpr () OpAdd expr (string "")
340− | otherwise = e
442+ else
342 Case.Fail ->
445 Case.Fail ->
343− return [ ExprStmt () (Help.throw "badCase" region) ]
446+ return [ ExprStmt () (Crash.crash region Crash.IncompletePatternMatch) ]
345 Case.Break ->
448 Case.Break ->
346 return [BreakStmt () Nothing]
449 return [BreakStmt () Nothing]
348− Case.Other e ->
451+ Case.Other expr ->
349− do e' <- expression e
452+ toStatementList <$> exprToCode expr
352 Case.Seq ms ->
454 Case.Seq ms ->
353 concat <$> mapM (match region) (dropEnd [] ms)
455 concat <$> mapM (match region) (dropEnd [] ms)
@@ -434,7 +536,7 @@ generate modul =
434 Module.program (Module.body modul)
536 Module.program (Module.body modul)
435 |> flattenLets []
537 |> flattenLets []
437− |> mapM definition
539+ |> mapM defToStatements
439 setup namespace path =
541 setup namespace path =
440 map create paths
542 map create paths
@@ -471,63 +573,105 @@ generate modul =
471 AssignExpr () OpAssign (LDot () (obj (init path)) (last path)) expr
573 AssignExpr () OpAssign (LDot () (obj (init path)) (last path)) expr
475 :: R.Region
579 :: R.Region
476 -> Var.Canonical
580 -> Var.Canonical
477 -> Canonical.Expr
581 -> Canonical.Expr
478 -> Canonical.Expr
582 -> Canonical.Expr
479− -> State Int (Expression ())
583+ -> State Int Code
480−binop region func@(Var.Canonical home op) e1 e2 =
584+binop region func left right
482− (Var.Module ["Basics"], ">>") ->
483− do es <- mapM expression (collectLeftAssoc [e2] e1)
484− return $ ["$"] ==> List.foldl' (\e f -> f <| e) (ref "$") es
486− (Var.Module ["Basics"], "<<") ->
487− do es <- mapM expression (e1 : collectRightAssoc [] e2)
488− return $ ["$"] ==> foldr (<|) (ref "$") es
490− (Var.Module ["Basics"], "<|") ->
491− do e2' <- expression e2
492− es <- mapM expression (collectRightAssoc [] e1)
493− return $ foldr (<|) e2' es
495− (Var.BuiltIn, "::") ->
585+ | func == Var.Canonical Var.BuiltIn "::" =
496− expression (A.A region (Data "::" [e1,e2]))
586+ exprToCode (A.A region (Data "::" [left,right]))
498− (Var.Module ["Basics"], _) ->
499− do e1' <- expression e1
500− e2' <- expression e2
501− case Map.lookup op basicOps of
506− return (ref "A2" `call` [ Var.canonical func, e1', e2' ])
508− _ ->
588+ | func == forwardCompose =
509− do e1' <- expression e1
589+ compose (collectLeftAssoc forwardCompose left right)
510− e2' <- expression e2
511− return (ref "A2" `call` [ Var.canonical func, e1', e2' ])
513− where
591+ | func == backwardCompose =
514− collectRightAssoc es e =
592+ compose (collectRightAssoc backwardCompose left right)
516− A.A _ (Binop (Var.Canonical (Var.Module ["Basics"]) "<<") e1 e2) ->
594+ | func == forwardApply =
517− collectRightAssoc (es ++ [e1]) e2
595+ pipe (collectLeftAssoc forwardApply left right)
519−
597+ | func == backwardApply =
520− collectLeftAssoc es e =
598+ pipe (collectRightAssoc backwardApply left right)
601+ do jsLeft <- exprToJsExpr left
602+ jsRight <- exprToJsExpr right
603+ jsExpr (makeExpr func jsLeft jsRight)
606+-- CONTROL FLOW OPERATOR HELPERS
608+apply :: Expression () -> Expression () -> Expression ()
613+compose :: [Canonical.Expr] -> State Int Code
615+ do jsFunctions <- mapM exprToJsExpr functions
616+ jsExpr $ ["$"] ==> List.foldl' apply (ref "$") jsFunctions
619+pipe :: [Canonical.Expr] -> State Int Code
621+ do (value:functions) <- mapM exprToJsExpr expressions
622+ jsExpr $ List.foldl' apply value functions
625+forwardCompose :: Var.Canonical
630+backwardCompose :: Var.Canonical
635+forwardApply :: Var.Canonical
640+backwardApply :: Var.Canonical
645+inBasics :: String -> Var.Canonical
647+ Var.Canonical (Var.Module ["Basics"]) name
650+-- BINARY OPERATOR HELPERS
652+makeExpr :: Var.Canonical -> (Expression () -> Expression () -> Expression ())
653+makeExpr qualifiedOp@(Var.Canonical home op) =
655+ simpleMake left right =
656+ ref "A2" `call` [ Var.canonical qualifiedOp, left, right ]
522− A.A _ (Binop (Var.Canonical (Var.Module ["Basics"]) ">>") e1 e2) ->
658+ if home == Var.Module ["Basics"] then
523− collectLeftAssoc (e2 : es) e1
659+ Map.findWithDefault simpleMake op basicOps
524− _ -> e : es
660+ else
664+basicOps :: Map.Map String (Expression () -> Expression () -> Expression ())
526− basicOps =
665+basicOps =
527− Map.fromList (infixOps ++ specialOps)
666+ Map.fromList (infixOps ++ specialOps)
669+infixOps :: [(String, Expression () -> Expression () -> Expression ())]
530− let infixOp str op = (str, InfixExpr () op) in
673+ (str, InfixExpr () op)
531 [ infixOp "+" OpAdd
675 [ infixOp "+" OpAdd
532 , infixOp "-" OpSub
676 , infixOp "-" OpSub
533 , infixOp "*" OpMul
677 , infixOp "*" OpMul
@@ -536,17 +680,56 @@ binop region func@(Var.Canonical home op) e1 e2 =
536 , infixOp "||" OpLOr
680 , infixOp "||" OpLOr
540− [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
541− , (,) "|>" $ flip (<|)
542− , (,) "==" $ \a b -> _Utils "eq" `call` [a,b]
543− , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (_Utils "eq" `call` [a,b])
544− , (,) "<" $ cmp OpLT 0
545− , (,) ">" $ cmp OpGT 0
546− , (,) "<=" $ cmp OpLT 1
547− , (,) ">=" $ cmp OpGT (-1)
548− , (,) "//" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
684+specialOps :: [(String, Expression () -> Expression () -> Expression ())]
686+ [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
687+ , (,) "|>" $ flip (<|)
688+ , (,) "==" $ \a b -> _Utils "eq" `call` [a,b]
689+ , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (_Utils "eq" `call` [a,b])
690+ , (,) "<" $ cmp OpLT 0
691+ , (,) ">" $ cmp OpGT 0
692+ , (,) "<=" $ cmp OpLT 1
693+ , (,) ">=" $ cmp OpGT (-1)
694+ , (,) "//" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
698+cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
551− cmp op n a b =
699+cmp op n a b =
552− InfixExpr () op (_Utils "cmp" `call` [a,b]) (IntLit () n)
700+ InfixExpr () op (_Utils "cmp" `call` [a,b]) (IntLit () n)
703+-- BINARY OPERATOR COLLECTORS
705+-- (h << g << f) becomes [f, g, h] which is the order you want for doing stuff
706+collectRightAssoc :: Var.Canonical -> Canonical.Expr -> Canonical.Expr -> [Canonical.Expr]
707+collectRightAssoc desiredOp left right =
708+ collectRightAssocHelp desiredOp [left] right
711+collectRightAssocHelp :: Var.Canonical -> [Canonical.Expr] -> Canonical.Expr -> [Canonical.Expr]
712+collectRightAssocHelp desiredOp exprList expr =
714+ A.A _ (Binop op left right) | op == desiredOp ->
715+ collectRightAssocHelp desiredOp (left : exprList) right
721+-- (f >> g >> h) becomes [f, g, h] which is the order you want for doing stuff
722+collectLeftAssoc :: Var.Canonical -> Canonical.Expr -> Canonical.Expr -> [Canonical.Expr]
723+collectLeftAssoc desiredOp left right =
724+ collectLeftAssocHelp desiredOp [right] left
727+collectLeftAssocHelp :: Var.Canonical -> [Canonical.Expr] -> Canonical.Expr -> [Canonical.Expr]
728+collectLeftAssocHelp desiredOp exprList expr =
730+ A.A _ (Binop op left right) | op == desiredOp ->
731+ collectLeftAssocHelp desiredOp (right : exprList) left