on master help sign in
Merge pull request #1071 from elm-lang/dev

Go back to old code gen format

commit255f9df70203a53d938fa32acc7c8202afce543e authorEvan Czaplicki <info@elm-lang.org> dateWed 30 Sep 2015, 01:35 (11 years ago) parent7c3a3fd2767b43
57 files changed+1000−776
src/AST/Module.hs−1 src/AST/Module/Name.hs−1 src/AST/Type.hs−1 src/AST/Variable.hs−1 src/Canonicalize.hs+4−3 src/Canonicalize/Port.hs−1 src/Canonicalize/Setup.hs−1 src/Canonicalize/Sort.hs−1 src/Canonicalize/Type.hs−1 src/Docs/Check.hs−1 src/Elm/Compiler/Type.hs−1 src/Elm/Docs.hs+1−1 src/Elm/Package.hs−1 src/Generate/JavaScript.hs+103−486 src/Generate/JavaScript/Expression.hs+531 src/Generate/JavaScript/Helpers.hs+7−17 src/Generate/JavaScript/Port.hs+13−13 src/Generate/JavaScript/Variable.hs+33−38 src/Nitpick/PatternMatches.hs−1 src/Optimize.hs−1 src/Parse/Binop.hs−1 src/Parse/Declaration.hs−1 src/Parse/Expression.hs−1 src/Parse/Helpers.hs+1−2 src/Parse/Literal.hs−1 src/Parse/Module.hs−1 src/Parse/Parse.hs−1 src/Parse/Pattern.hs−1 src/Parse/Type.hs−1 src/Reporting/Result.hs+1−1 src/Type/Constrain/Expression.hs−1 src/Type/Constrain/Pattern.hs−1 src/Type/Environment.hs−1 src/Type/Solve.hs+1−1 src/Type/State.hs+1−1 src/Type/Type.hs−1 src/Validate.hs−1 tests/test-files/good-expected-js/AliasSubstitution.elm.js+10−3 tests/test-files/good-expected-js/CaseExpression3.elm.js+31−27 tests/test-files/good-expected-js/Lists/EmptyList.elm.js+9−2 tests/test-files/good-expected-js/Lists/ListRange.elm.js+9−3 tests/test-files/good-expected-js/Lists/NonEmptyList.elm.js+9−4 tests/test-files/good-expected-js/NoExpressions.elm.js+8−1 tests/test-files/good-expected-js/Otherwise.elm.js+12−3 tests/test-files/good-expected-js/Ports.elm.js+58−55 tests/test-files/good-expected-js/PortsWithTypeAliases.elm.js+26−25 tests/test-files/good-expected-js/QuotesAndComments.elm.js+18−7 tests/test-files/good-expected-js/Soundness/Apply.elm.js+11−4 tests/test-files/good-expected-js/Soundness/ApplyAnnotated.elm.js+11−4 tests/test-files/good-expected-js/Soundness/Id.elm.js+12−5 tests/test-files/good-expected-js/Soundness/IdAnnotated.elm.js+12−5 tests/test-files/good-expected-js/Soundness/TrickyId.elm.js+8−4 tests/test-files/good-expected-js/Soundness/TrickyIdAnnotated.elm.js+8−4 tests/test-files/good-expected-js/Strings/Multiline.elm.js+9−2 tests/test-files/good-expected-js/Strings/MultilineNormal.elm.js+9−2 tests/test-files/good-expected-js/TailRecursive.elm.js+24−17 tests/test-files/good-expected-js/Unify/NonHomogeneousRecords.elm.js+10−10
src/AST/Module.hs−1
@@ -9,7 +9,6 @@ module AST.Module
99 , UserImport, DefaultImport, ImportMethod(..)
1010 ) where
1111
12−import Control.Applicative ((<$>),(<*>))
1312import Data.Binary
1413import qualified Data.Map as Map
1514
src/AST/Module/Name.hs−1
@@ -1,6 +1,5 @@
11module AST.Module.Name where
22
3−import Control.Applicative ((<$>),(<*>))
43import Data.Binary
54import qualified Data.List as List
65
src/AST/Type.hs−1
@@ -8,7 +8,6 @@ module AST.Type
88 , tuple
99 ) where
1010
11−import Control.Applicative ((<$>), (<*>))
1211import Control.Arrow (second)
1312import Data.Binary
1413import qualified Data.Map as Map
src/AST/Variable.hs−1
@@ -1,6 +1,5 @@
11module AST.Variable where
22
3−import Control.Applicative ((<$>), (<*>))
43import Data.Binary
54import qualified Data.Map as Map
65import qualified Data.Maybe as Maybe
src/Canonicalize.hs+4−3
@@ -1,6 +1,5 @@
11module Canonicalize (module') where
22
3−import Control.Applicative ((<$>),(<*>))
43import qualified Data.List as List
54import qualified Data.Map as Map
65import qualified Data.Maybe as Maybe
@@ -321,9 +320,11 @@ declToValue (A.A _ decl) =
321320
322321 D.TypeAlias name _ tipe ->
323322 case tipe of
324− A.A _ (Type.RRecord _ _) ->
323+ A.A _ (Type.RRecord _ Nothing) ->
325324 [ Var.Alias name, Var.Value name ]
326− _ -> [ Var.Alias name ]
325+
326+ _ ->
327+ [ Var.Alias name ]
327328
328329 _ -> []
329330
src/Canonicalize/Port.hs−1
@@ -1,6 +1,5 @@
11module Canonicalize.Port (check) where
22
3−import Control.Applicative ((<$>))
43import qualified Data.Foldable as Foldable
54
65import qualified AST.Declaration as D
src/Canonicalize/Setup.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall #-}
22module Canonicalize.Setup (environment) where
33
4−import Control.Applicative ((<$>))
54import Control.Arrow (second)
65import qualified Data.Graph as Graph
76import qualified Data.Map as Map
src/Canonicalize/Sort.hs−1
@@ -2,7 +2,6 @@
22module Canonicalize.Sort (definitions) where
33
44import Control.Monad.State
5−import Control.Applicative ((<$>),(<*>))
65import qualified Data.Graph as Graph
76import qualified Data.Map as Map
87import qualified Data.Maybe as Maybe
src/Canonicalize/Type.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall #-}
22module Canonicalize.Type (tipe) where
33
4−import Control.Applicative ((<$>),(<*>))
54import qualified Data.Traversable as Trav
65
76import qualified AST.Type as T
src/Docs/Check.hs−1
@@ -1,6 +1,5 @@
11module Docs.Check (check) where
22
3−import Control.Applicative ((<$>),(<*>))
43import qualified Data.List as List
54import qualified Data.Map as Map
65import qualified Data.Set as Set
src/Elm/Compiler/Type.hs−1
@@ -4,7 +4,6 @@ module Elm.Compiler.Type
44 , toString
55 ) where
66
7−import Control.Applicative ((<$>), (<*>))
87import Control.Arrow (second)
98import Data.Aeson ((.:))
109import qualified Data.Aeson as Json
src/Elm/Docs.hs+1−1
@@ -1,7 +1,7 @@
11{-# LANGUAGE OverloadedStrings #-}
22module Elm.Docs where
33
4−import Control.Applicative ((<$>),(<*>),(<|>))
4+import Control.Applicative ((<|>))
55import Control.Monad
66import Data.Aeson ((.:), (.:?), (.=))
77import qualified Data.Aeson as Json
src/Elm/Package.hs−1
@@ -1,6 +1,5 @@
11module Elm.Package where
22
3−import Control.Applicative ((<$>), (<*>))
43import Data.Aeson
54import Data.Binary
65import qualified Data.Char as Char
src/Generate/JavaScript.hs+103−486
@@ -1,547 +1,164 @@
11module Generate.JavaScript (generate) where
22
3−import Control.Applicative ((<$>),(<*>))
4−import Control.Arrow (first, second, (***))
53import Control.Monad.State as State
64import qualified Data.List as List
7−import qualified Data.Map as Map
85import Language.ECMAScript3.PrettyPrint as ES
96import Language.ECMAScript3.Syntax
107import qualified Text.PrettyPrint.Leijen as PP
118
12−import qualified AST.Expression.General as Expr
13−import AST.Expression.Optimized as Opt
14−import qualified AST.Literal as L
9+import qualified AST.Expression.Optimized as Optimized
10+import qualified AST.Helpers as Help
1511import qualified AST.Module as Module
1612import qualified AST.Module.Name as ModuleName
17−import qualified AST.Variable as Var
18−import Generate.JavaScript.Helpers as Help
19−import qualified Generate.JavaScript.BuiltIn as BuiltIn
20−import qualified Generate.JavaScript.Literal as Literal
21−import qualified Generate.JavaScript.Port as Port
13+import qualified AST.Variable as Variable
14+import qualified Generate.JavaScript.Expression as JS
15+import Generate.JavaScript.Helpers (call, function, localRuntime, obj, prop, ref, varDecl)
2216import qualified Generate.JavaScript.Variable as Var
23−import qualified Optimize.Patterns.DecisionTree as DT
2417
2518
2619generate :: Module.Optimized -> String
2720generate module_ =
2821 let
29− definitions =
30− Module.program (Module.body module_)
22+ (ModuleName.Canonical _ name) =
23+ Module.name module_
24+
25+ body =
26+ concat
27+ [ useStrict
28+ , checkForCachedVersion name
29+ , imports (Module.imports module_)
30+ , definitions (Module.program (Module.body module_))
31+ , exports name (Module.exports module_)
32+ ]
3133
32− setup =
33− Var.define (Just (Module.name module_)) "_op" (ObjectLit () [])
34+ make =
35+ "Elm" : name ++ ["make"]
3436
35− stmts =
36− State.evalState (mapM generateDef definitions) 0
37+ javascript =
38+ buildIntermediateObjects make
39+ ++
40+ [ assign make (function [localRuntime] body)
41+ ]
3742 in
38− PP.displayS (PP.renderPretty 0.4 120 (ES.prettyPrint (setup:stmts))) ""
39−
40−
41−-- CODE CHUNKS
42−
43−data Code
44− = JsExpr (Expression ())
45− | JsBlock [Statement ()]
46−
47−
48−jsExpr :: Expression () -> State Int Code
49−jsExpr exp =
50− return (JsExpr exp)
51−
52−
53−jsBlock :: [Statement ()] -> State Int Code
54−jsBlock exp =
55− return (JsBlock exp)
56−
57−
58−isBlock :: Code -> Bool
59−isBlock code =
60− case code of
61− JsBlock _ -> True
62− JsExpr _ -> False
63−
43+ PP.displayS (PP.renderPretty 0.4 160 (ES.prettyPrint javascript)) ""
6444
65−toStatementList :: Code -> [Statement ()]
66−toStatementList code =
67− case code of
68− JsExpr expr ->
69− [ ret expr ]
70− JsBlock stmts ->
71− stmts
7245
7346
74−toStatement :: Code -> Statement ()
75−toStatement code =
76− case code of
77− JsExpr expr ->
78− ret expr
79− JsBlock [stmt] ->
80− stmt
81− JsBlock stmts ->
82− BlockStmt () stmts
47+-- INTRO
8348
8449
85−toExpr :: Code -> Expression ()
86−toExpr code =
87− case code of
88− JsExpr expr ->
89− expr
50+useStrict :: [Statement ()]
51+useStrict =
52+ [ ExprStmt () (StringLit () "use strict")
53+ ]
9054
91− JsBlock stmts ->
92− function [] stmts `call` []
9355
94−
95−-- DEFINITIONS
96−
97−generateDef :: Opt.Def -> State Int (Statement ())
98−generateDef def =
99− do (home, name, jsBody) <-
100− case def of
101− Opt.TailDef (Opt.Facts home _) name argNames body ->
102− (,,) home name <$> generateTailFunction name argNames body
103−
104− Opt.Def (Opt.Facts home _) name body ->
105− (,,) home name <$> generateJsExpr body
106−
107− return (Var.define home name jsBody)
108−
109−
110−-- EXPRESSIONS
111−
112−generateJsExpr :: Opt.Expr -> State Int (Expression ())
113−generateJsExpr optExpr =
114− toExpr <$> generateCode optExpr
115−
116−
117−generateCode :: Opt.Expr -> State Int Code
118−generateCode expr =
119− case expr of
120− Var var ->
121− jsExpr $ Var.canonical var
122−
123− Literal lit ->
124− jsExpr (Literal.literal lit)
125−
126− Range lo hi ->
127− do lo' <- generateJsExpr lo
128− hi' <- generateJsExpr hi
129− jsExpr $ BuiltIn.range lo' hi'
130−
131− Access record field ->
132− do record' <- generateJsExpr record
133− jsExpr $ DotRef () record' (var (Var.safe field))
134−
135− Update record fields ->
136− let
137− fieldToJs (field, value) =
138− do jsValue <- generateJsExpr value
139− return (Var.safe field, jsValue)
140− in
141− do jsRecord <- generateJsExpr record
142− jsFields <- mapM fieldToJs fields
143− jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
144−
145− Record fields ->
146− do fields' <-
147− forM fields $ \(field, e) ->
148− (,) (Var.safe field) <$> generateJsExpr e
149−
150− let fieldMap =
151− List.foldl' combine Map.empty fields'
152−
153− jsExpr $ ObjectLit () $ (prop "_", hidden fieldMap) : visible fieldMap
154− where
155− combine record (field, value) =
156− Map.insertWith (++) field [value] record
157−
158− hidden fs =
159− ObjectLit () . map (prop *** ArrayLit ()) $
160− Map.toList (Map.filter (not . null) (Map.map tail fs))
161−
162− visible fs =
163− map (first prop) (Map.toList (Map.map head fs))
164−
165− Binop op leftExpr rightExpr ->
166− binop op leftExpr rightExpr
167−
168− Function args body ->
169− generateFunction args body
170−
171− Call func args ->
172− let
173− arity = length args
174− aN = "A" ++ show arity
175− in
176− do jsFunc <- generateJsExpr func
177− jsArgs <- mapM generateJsExpr args
178− jsExpr $
179− if 2 <= arity && arity <= 9 then
180− ref aN `call` (jsFunc:jsArgs)
181− else
182− foldl1 (<|) (jsFunc:jsArgs)
183−
184− TailCall name argNames args ->
185− let
186− reassign name tempName =
187− ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
188− in
189− do args' <- mapM generateJsExpr args
190− tempNames <- mapM (\_ -> Var.fresh) args
191− jsBlock $
192− VarDeclStmt () (zipWith varDecl tempNames args')
193− : zipWith reassign argNames tempNames
194− ++ [ContinueStmt () (Just (Id () name))]
195−
196− Let defs body ->
197− do stmts <- mapM generateDef defs
198− code <- generateCode body
199− jsBlock (stmts ++ toStatementList code)
200−
201− If branches finally ->
202− generateIf branches finally
203−
204− Case root decisionTree branches ->
205− JsBlock <$> generateCase root decisionTree branches
206−
207− ExplicitList elements ->
208− do jsElements <- mapM generateJsExpr elements
209− jsExpr $ BuiltIn.list jsElements
210−
211− Data tag members ->
212− do jsMembers <- mapM generateJsExpr members
213− jsExpr $ ObjectLit () (ctor : fields jsMembers)
214− where
215− ctor = (prop "ctor", string tag)
216− fields =
217− zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
218−
219− DataAccess dataExpr index ->
220− do jsDataExpr <- generateJsExpr dataExpr
221− jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
222−
223− GLShader _uid src _tipe ->
224− jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (L.Str src))]
225−
226− Port impl ->
227− case impl of
228− Expr.In name portType ->
229− jsExpr (Port.inbound name portType)
230−
231− Expr.Out name expr portType ->
232− do expr' <- generateJsExpr expr
233− jsExpr (Port.outbound name expr' portType)
234−
235− Expr.Task name expr portType ->
236− do expr' <- generateJsExpr expr
237− jsExpr (Port.task name expr' portType)
238−
239− Crash region maybeCaseCrashValue ->
240− jsExpr $ BuiltIn.crash region maybeCaseCrashValue
241−
242−
243−-- FUNCTIONS
244−
245−generateFunction :: [String] -> Opt.Expr -> State Int Code
246−generateFunction args body =
247− do code <- generateCode body
248− jsExpr (generateFunctionWithArity args code)
249−
250−
251−generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
252−generateTailFunction name args body =
253− do code <- generateCode body
254− return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
255− LabelledStmt ()
256− (Id () name)
257− (WhileStmt () (BoolLit () True) (toStatement code))
258−
259−
260−generateFunctionWithArity :: [String] -> Code -> Expression ()
261−generateFunctionWithArity rawArgs code =
262− let
263− args = map Var.safe rawArgs
264− arity = length args
265− in
266− if 2 <= arity && arity <= 9 then
267− let
268− fN = "F" ++ show arity
269− in
270− ref fN <| function args (toStatementList code)
271− else
272− let
273− (lastArg:otherArgs) = reverse args
274− innerBody = function [lastArg] (toStatementList code)
275− in
276− foldl (\body arg -> function [arg] [ret body]) innerBody otherArgs
277−
278−
279−-- GENERATE IFS
280−
281−generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
282−generateIf givenBranches givenFinally =
56+checkForCachedVersion :: ModuleName.Raw -> [Statement ()]
57+checkForCachedVersion name =
28358 let
284− (branches, finally) =
285− crushIfs givenBranches givenFinally
59+ values =
60+ localRuntime : name ++ ["values"]
28661
287− convertBranch (condition, expr) =
288− (,) <$> generateJsExpr condition <*> generateCode expr
289−
290− ifExpression (condition, branch) otherwise =
291− CondExpr () condition branch otherwise
292−
293− ifStatement (condition, branch) otherwise =
294− IfStmt () condition branch otherwise
62+ valuesObject =
63+ obj values
29564 in
296− do jsBranches <- mapM convertBranch branches
297− jsFinally <- generateCode finally
298−
299− if any isBlock (jsFinally : map snd jsBranches)
300− then
301− jsBlock [ foldr ifStatement (toStatement jsFinally) (map (second toStatement) jsBranches) ]
302− else
303− jsExpr (foldr ifExpression (toExpr jsFinally) (map (second toExpr) jsBranches))
304−
305−
306−crushIfs
307− :: [(Opt.Expr, Opt.Expr)]
308− -> Opt.Expr
309− -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
310−crushIfs branches finally =
311− crushIfsHelp [] branches finally
312−
313−
314−crushIfsHelp
315− :: [(Opt.Expr, Opt.Expr)]
316− -> [(Opt.Expr, Opt.Expr)]
317− -> Opt.Expr
318− -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
319−crushIfsHelp visitedBranches unvisitedBranches finally =
320− case unvisitedBranches of
321− [] ->
322− case finally of
323− If subBranches subFinally ->
324− crushIfsHelp visitedBranches subBranches subFinally
325−
326− _ ->
327− (reverse visitedBranches, finally)
328−
329− (Literal (L.Boolean True), branch) : _ ->
330− crushIfsHelp visitedBranches [] branch
331−
332− visiting : unvisited ->
333− crushIfsHelp (visiting : visitedBranches) unvisited finally
334−
335−
336−-- CASE EXPRESSIONS
337−
338−generateCase
339− :: String
340− -> DT.DecisionTree Opt.Jump
341− -> [(Int, Opt.Branch)]
342− -> State Int [Statement ()]
343−generateCase root decisionTree jumpBranches =
344− do decider <- generateDecisionTree root decisionTree
345− foldM (goto root) decider jumpBranches
65+ buildIntermediateObjects values
66+ ++
67+ [ IfSingleStmt () valuesObject (ReturnStmt () (Just valuesObject))
68+ ]
34669
34770
348−goto :: String -> [Statement ()] -> (Int, Opt.Branch) -> State Int [Statement ()]
349−goto root decider (target, branch) =
71+buildIntermediateObjects :: [String] -> [Statement ()]
72+buildIntermediateObjects path =
35073 let
351− deciderStmt =
352− LabelledStmt ()
353− (targetLabel root target)
354− (DoWhileStmt () (BlockStmt () decider) (BoolLit () False))
355− in
356− do stmts <- generateBranch root branch
357− return (deciderStmt : stmts)
358−
359−
360−targetLabel :: String -> Int -> Id ()
361−targetLabel root target =
362− Id () (root ++ "_" ++ show target)
363−
364−
365−generateDecisionTree :: String -> DT.DecisionTree Opt.Jump -> State Int [Statement ()]
366−generateDecisionTree root decisionTree =
367− case decisionTree of
368− DT.Match (Opt.Inline branch) ->
369− generateBranch root branch
370−
371− DT.Match (Opt.Jump target) ->
372− return [ BreakStmt () (Just (targetLabel root target)) ]
373−
374− DT.Decision testPath [(test, subTree)] (Just fallback) ->
375− let
376− (tests, deepestSubTree) =
377− collapseTests [(testPath, test)] fallback subTree
378−
379− makeTest (path, test) =
380− do testExpr <- pathToTestableExpr root path test
381− return (InfixExpr () OpStrictEq testExpr (testToExpr test))
382− in
383− do testExprs <- mapM makeTest tests
384− let cond = List.foldl1' (InfixExpr () OpLAnd) testExprs
385− thenBranch <- generateDecisionTree root deepestSubTree
386− elseBranch <- generateDecisionTree root fallback
387− return [ IfStmt () cond (BlockStmt () thenBranch) (BlockStmt () elseBranch) ]
388−
389− DT.Decision testPath edges fallback ->
390− do testExpr <- pathToTestableExpr root testPath (fst (head edges))
391− caseClauses <- mapM (edgeToCaseClause root) edges
392− caseDefault <- fallbackToDefault root fallback
393− return [ SwitchStmt () testExpr (caseClauses ++ caseDefault) ]
394−
395−
396−collapseTests
397− :: [(DT.Path, DT.Test)]
398− -> DT.DecisionTree Opt.Jump
399− -> DT.DecisionTree Opt.Jump
400− -> ([(DT.Path, DT.Test)], DT.DecisionTree Opt.Jump)
401−collapseTests tests outerFallback decisionTree =
402− case decisionTree of
403− DT.Decision testPath [(test, subTree)] (Just fallback)
404− | fallback == outerFallback ->
405− collapseTests ((testPath, test) : tests) outerFallback subTree
406−
407− _ ->
408− (tests, decisionTree)
409−
410−
411−edgeToCaseClause :: String -> (DT.Test, DT.DecisionTree Opt.Jump) -> State Int (CaseClause ())
412−edgeToCaseClause root (test, subTree) =
413− CaseClause () (testToExpr test) <$> generateDecisionTree root subTree
74+ create name =
75+ assign name (InfixExpr () OpLOr (obj name) (ObjectLit () []))
41476
415−
416−pathToTestableExpr :: String -> DT.Path -> DT.Test -> State Int (Expression ())
417−pathToTestableExpr root path exampleTest =
418− do accessExpr <- generateJsExpr (pathToExpr root path)
419− case exampleTest of
420− DT.Constructor _ ->
421− return (DotRef () accessExpr (Id () "ctor"))
422−
423− DT.Literal _ ->
424− return accessExpr
77+ paths =
78+ drop 2 (init (List.inits path))
79+ in
80+ map create paths
42581
42682
427−testToExpr :: DT.Test -> Expression ()
428−testToExpr test =
429− case test of
430− DT.Constructor (Var.Canonical _ tag) ->
431− StringLit () tag
83+assign :: [String] -> Expression () -> Statement ()
84+assign path expr =
85+ case path of
86+ [x] ->
87+ VarDeclStmt () [ varDecl x expr ]
43288
433− DT.Literal (L.Chr char) ->
434− StringLit () [char]
89+ _ ->
90+ ExprStmt () $
91+ AssignExpr () OpAssign (LDot () (obj (init path)) (last path)) expr
43592
436− DT.Literal lit ->
437− Literal.literal lit
43893
43994
440−fallbackToDefault :: String -> Maybe (DT.DecisionTree Opt.Jump) -> State Int [CaseClause ()]
441−fallbackToDefault root fallback =
442− case fallback of
443− Nothing ->
444− return []
95+-- IMPORTS
44596
446− Just subTree ->
447− do stmts <- generateDecisionTree root subTree
448− return [ CaseDefault () stmts ]
44997
98+imports :: [ModuleName.Raw] -> [Statement ()]
99+imports rawImports =
100+ case rawImports of
101+ [] ->
102+ []
450103
451−generateBranch :: String -> Opt.Branch -> State Int [Statement ()]
452−generateBranch root (Opt.Branch substitutions expr) =
453− do substs <- mapM (loadPath root) substitutions
454− let substStmts =
455− if null substs then [] else [ VarDeclStmt () substs ]
456− code <- generateCode expr
457− return (substStmts ++ toStatementList code)
104+ _ ->
105+ [ VarDeclStmt () (map jsImport rawImports)
106+ ]
458107
459108
460−loadPath :: String -> (String, DT.Path) -> State Int (VarDecl ())
461−loadPath root (name, path) =
462− do jsAccessExpr <- generateJsExpr (pathToExpr root path)
463− return $ varDecl (Var.safe name) jsAccessExpr
109+jsImport :: ModuleName.Raw -> VarDecl ()
110+jsImport name =
111+ let
112+ make =
113+ obj ("Elm" : name ++ ["make"])
114+ in
115+ varDecl (Var.modulePrefix name) (call make [ref localRuntime])
464116
465117
466−pathToExpr :: String -> DT.Path -> Opt.Expr
467−pathToExpr root fullPath =
468− go (Opt.Var (Var.local root)) fullPath
469− where
470− go expr path =
471− case path of
472− DT.Position index subpath ->
473− go (Opt.DataAccess expr index) subpath
474118
475− DT.Field field subpath ->
476− go (Opt.Access expr field) subpath
119+-- DEFINITIONS
477120
478− DT.Empty ->
479− expr
480121
481− DT.Alias ->
482− expr
122+definitions :: [Optimized.Def] -> [Statement ()]
123+definitions defs =
124+ let
125+ setup =
126+ Var.define "_op" (ObjectLit () [])
127+ in
128+ setup : State.evalState (mapM JS.generateDef defs) 0
483129
484130
485−-- BINARY OPERATORS
486131
487−binop
488− :: Var.Canonical
489− -> Opt.Expr
490− -> Opt.Expr
491− -> State Int Code
492−binop func left right =
493− do jsLeft <- generateJsExpr left
494− jsRight <- generateJsExpr right
495− jsExpr (makeExpr func jsLeft jsRight)
132+-- EXPORTS
496133
497134
498−-- BINARY OPERATOR HELPERS
135+exports :: ModuleName.Raw -> [Variable.Value] -> [Statement ()]
136+exports name exportedValues =
137+ let
138+ exportedFields =
139+ map toField ("_op" : concatMap extract exportedValues)
499140
500−makeExpr :: Var.Canonical -> (Expression () -> Expression () -> Expression ())
501−makeExpr qualifiedOp@(Var.Canonical home op) =
502− let
503− simpleMake left right =
504− ref "A2" `call` [ Var.canonical qualifiedOp, left, right ]
505− in
506− if home == Var.Module (ModuleName.inCore ["Basics"]) then
507− Map.findWithDefault simpleMake op basicOps
508− else
509− simpleMake
141+ toField x =
142+ (prop x, ref x)
510143
144+ extract value =
145+ case value of
146+ Variable.Alias _ ->
147+ []
511148
512−basicOps :: Map.Map String (Expression () -> Expression () -> Expression ())
513−basicOps =
514− Map.fromList (infixOps ++ specialOps)
149+ Variable.Value x ->
150+ if Help.isOp x then
151+ []
515152
153+ else
154+ [Var.safe x]
516155
517−infixOps :: [(String, Expression () -> Expression () -> Expression ())]
518−infixOps =
519− let
520− infixOp str op =
521− (str, InfixExpr () op)
522− in
523− [ infixOp "+" OpAdd
524− , infixOp "-" OpSub
525− , infixOp "*" OpMul
526− , infixOp "/" OpDiv
527− , infixOp "&&" OpLAnd
528− , infixOp "||" OpLOr
529− ]
530−
156+ Variable.Union _ (Variable.Listing ctors _) ->
157+ map Var.safe ctors
531158
532−specialOps :: [(String, Expression () -> Expression () -> Expression ())]
533−specialOps =
534− [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
535− , (,) "==" $ \a b -> BuiltIn.eq a b
536− , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (BuiltIn.eq a b)
537− , (,) "<" $ cmp OpLT 0
538− , (,) ">" $ cmp OpGT 0
539− , (,) "<=" $ cmp OpLT 1
540− , (,) ">=" $ cmp OpGT (-1)
541− , (,) "//" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
159+ values =
160+ LDot () (obj (localRuntime : name)) "values"
161+ in
162+ [ ReturnStmt () $ Just $
163+ AssignExpr () OpAssign values (ObjectLit () exportedFields)
542164 ]
543−
544−
545−cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
546−cmp op n a b =
547− InfixExpr () op (BuiltIn.compare a b) (IntLit () n)
src/Generate/JavaScript/Expression.hsnew file+531
@@ -0,0 +1,531 @@
1+module Generate.JavaScript.Expression (generateDef) where
2+
3+import Control.Arrow (first, second, (***))
4+import Control.Monad.State (State, forM, foldM)
5+import qualified Data.List as List
6+import qualified Data.Map as Map
7+import Language.ECMAScript3.Syntax
8+
9+import qualified AST.Expression.General as Expr
10+import AST.Expression.Optimized as Opt
11+import qualified AST.Literal as L
12+import qualified AST.Module.Name as ModuleName
13+import qualified AST.Variable as Var
14+import Generate.JavaScript.Helpers as Help
15+import qualified Generate.JavaScript.BuiltIn as BuiltIn
16+import qualified Generate.JavaScript.Literal as Literal
17+import qualified Generate.JavaScript.Port as Port
18+import qualified Generate.JavaScript.Variable as Var
19+import qualified Optimize.Patterns.DecisionTree as DT
20+
21+
22+-- CODE CHUNKS
23+
24+data Code
25+ = JsExpr (Expression ())
26+ | JsBlock [Statement ()]
27+
28+
29+jsExpr :: Expression () -> State Int Code
30+jsExpr exp =
31+ return (JsExpr exp)
32+
33+
34+jsBlock :: [Statement ()] -> State Int Code
35+jsBlock exp =
36+ return (JsBlock exp)
37+
38+
39+isBlock :: Code -> Bool
40+isBlock code =
41+ case code of
42+ JsBlock _ -> True
43+ JsExpr _ -> False
44+
45+
46+toStatementList :: Code -> [Statement ()]
47+toStatementList code =
48+ case code of
49+ JsExpr expr ->
50+ [ ReturnStmt () (Just expr) ]
51+
52+ JsBlock stmts ->
53+ stmts
54+
55+
56+toStatement :: Code -> Statement ()
57+toStatement code =
58+ case code of
59+ JsExpr expr ->
60+ ReturnStmt () (Just expr)
61+
62+ JsBlock [stmt] ->
63+ stmt
64+
65+ JsBlock stmts ->
66+ BlockStmt () stmts
67+
68+
69+toExpr :: Code -> Expression ()
70+toExpr code =
71+ case code of
72+ JsExpr expr ->
73+ expr
74+
75+ JsBlock stmts ->
76+ function [] stmts `call` []
77+
78+
79+-- DEFINITIONS
80+
81+generateDef :: Opt.Def -> State Int (Statement ())
82+generateDef def =
83+ do (home, name, jsBody) <-
84+ case def of
85+ Opt.TailDef (Opt.Facts home _) name argNames body ->
86+ (,,) home name <$> generateTailFunction name argNames body
87+
88+ Opt.Def (Opt.Facts home _) name body ->
89+ (,,) home name <$> generateJsExpr body
90+
91+ return (Var.define name jsBody)
92+
93+
94+-- EXPRESSIONS
95+
96+generateJsExpr :: Opt.Expr -> State Int (Expression ())
97+generateJsExpr optExpr =
98+ toExpr <$> generateCode optExpr
99+
100+
101+generateCode :: Opt.Expr -> State Int Code
102+generateCode expr =
103+ case expr of
104+ Var var ->
105+ jsExpr $ Var.canonical var
106+
107+ Literal lit ->
108+ jsExpr (Literal.literal lit)
109+
110+ Range lo hi ->
111+ do lo' <- generateJsExpr lo
112+ hi' <- generateJsExpr hi
113+ jsExpr $ BuiltIn.range lo' hi'
114+
115+ Access record field ->
116+ do record' <- generateJsExpr record
117+ jsExpr $ DotRef () record' (var (Var.safe field))
118+
119+ Update record fields ->
120+ let
121+ fieldToJs (field, value) =
122+ do jsValue <- generateJsExpr value
123+ return (Var.safe field, jsValue)
124+ in
125+ do jsRecord <- generateJsExpr record
126+ jsFields <- mapM fieldToJs fields
127+ jsExpr $ BuiltIn.recordUpdate jsRecord jsFields
128+
129+ Record fields ->
130+ do fields' <-
131+ forM fields $ \(field, e) ->
132+ (,) (Var.safe field) <$> generateJsExpr e
133+
134+ let fieldMap =
135+ List.foldl' combine Map.empty fields'
136+
137+ jsExpr $ ObjectLit () $ (prop "_", hidden fieldMap) : visible fieldMap
138+ where
139+ combine record (field, value) =
140+ Map.insertWith (++) field [value] record
141+
142+ hidden fs =
143+ ObjectLit () . map (prop *** ArrayLit ()) $
144+ Map.toList (Map.filter (not . null) (Map.map tail fs))
145+
146+ visible fs =
147+ map (first prop) (Map.toList (Map.map head fs))
148+
149+ Binop op leftExpr rightExpr ->
150+ binop op leftExpr rightExpr
151+
152+ Function args body ->
153+ generateFunction args body
154+
155+ Call func args ->
156+ let
157+ arity = length args
158+ aN = "A" ++ show arity
159+ in
160+ do jsFunc <- generateJsExpr func
161+ jsArgs <- mapM generateJsExpr args
162+ jsExpr $
163+ if 2 <= arity && arity <= 9 then
164+ ref aN `call` (jsFunc:jsArgs)
165+ else
166+ foldl1 (<|) (jsFunc:jsArgs)
167+
168+ TailCall name argNames args ->
169+ let
170+ reassign name tempName =
171+ ExprStmt () (AssignExpr () OpAssign (LVar () name) (ref tempName))
172+ in
173+ do args' <- mapM generateJsExpr args
174+ tempNames <- mapM (\_ -> Var.fresh) args
175+ jsBlock $
176+ VarDeclStmt () (zipWith varDecl tempNames args')
177+ : zipWith reassign argNames tempNames
178+ ++ [ContinueStmt () (Just (Id () name))]
179+
180+ Let defs body ->
181+ do stmts <- mapM generateDef defs
182+ code <- generateCode body
183+ jsBlock (stmts ++ toStatementList code)
184+
185+ If branches finally ->
186+ generateIf branches finally
187+
188+ Case root decisionTree branches ->
189+ JsBlock <$> generateCase root decisionTree branches
190+
191+ ExplicitList elements ->
192+ do jsElements <- mapM generateJsExpr elements
193+ jsExpr $ BuiltIn.list jsElements
194+
195+ Data tag members ->
196+ do jsMembers <- mapM generateJsExpr members
197+ jsExpr $ ObjectLit () (ctor : fields jsMembers)
198+ where
199+ ctor = (prop "ctor", StringLit () tag)
200+ fields =
201+ zipWith (\n e -> (prop ("_" ++ show n), e)) [ 0 :: Int .. ]
202+
203+ DataAccess dataExpr index ->
204+ do jsDataExpr <- generateJsExpr dataExpr
205+ jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
206+
207+ GLShader _uid src _tipe ->
208+ jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (L.Str src))]
209+
210+ Port impl ->
211+ case impl of
212+ Expr.In name portType ->
213+ jsExpr (Port.inbound name portType)
214+
215+ Expr.Out name expr portType ->
216+ do expr' <- generateJsExpr expr
217+ jsExpr (Port.outbound name expr' portType)
218+
219+ Expr.Task name expr portType ->
220+ do expr' <- generateJsExpr expr
221+ jsExpr (Port.task name expr' portType)
222+
223+ Crash region maybeCaseCrashValue ->
224+ jsExpr $ BuiltIn.crash region maybeCaseCrashValue
225+
226+
227+-- FUNCTIONS
228+
229+generateFunction :: [String] -> Opt.Expr -> State Int Code
230+generateFunction args body =
231+ do code <- generateCode body
232+ jsExpr (generateFunctionWithArity args code)
233+
234+
235+generateTailFunction :: String -> [String] -> Opt.Expr -> State Int (Expression ())
236+generateTailFunction name args body =
237+ do code <- generateCode body
238+ return $ generateFunctionWithArity args $ JsBlock $ (:[]) $
239+ LabelledStmt ()
240+ (Id () name)
241+ (WhileStmt () (BoolLit () True) (toStatement code))
242+
243+
244+generateFunctionWithArity :: [String] -> Code -> Expression ()
245+generateFunctionWithArity rawArgs code =
246+ let
247+ args = map Var.safe rawArgs
248+ arity = length args
249+ in
250+ if 2 <= arity && arity <= 9 then
251+ let
252+ fN = "F" ++ show arity
253+ in
254+ ref fN <| function args (toStatementList code)
255+ else
256+ let
257+ (lastArg:otherArgs) = reverse args
258+ innerBody = function [lastArg] (toStatementList code)
259+ in
260+ foldl (\body arg -> function [arg] [ReturnStmt () (Just body)]) innerBody otherArgs
261+
262+
263+-- GENERATE IFS
264+
265+generateIf :: [(Opt.Expr, Opt.Expr)] -> Opt.Expr -> State Int Code
266+generateIf givenBranches givenFinally =
267+ let
268+ (branches, finally) =
269+ crushIfs givenBranches givenFinally
270+
271+ convertBranch (condition, expr) =
272+ (,) <$> generateJsExpr condition <*> generateCode expr
273+
274+ ifExpression (condition, branch) otherwise =
275+ CondExpr () condition branch otherwise
276+
277+ ifStatement (condition, branch) otherwise =
278+ IfStmt () condition branch otherwise
279+ in
280+ do jsBranches <- mapM convertBranch branches
281+ jsFinally <- generateCode finally
282+
283+ if any isBlock (jsFinally : map snd jsBranches)
284+ then
285+ jsBlock [ foldr ifStatement (toStatement jsFinally) (map (second toStatement) jsBranches) ]
286+ else
287+ jsExpr (foldr ifExpression (toExpr jsFinally) (map (second toExpr) jsBranches))
288+
289+
290+crushIfs
291+ :: [(Opt.Expr, Opt.Expr)]
292+ -> Opt.Expr
293+ -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
294+crushIfs branches finally =
295+ crushIfsHelp [] branches finally
296+
297+
298+crushIfsHelp
299+ :: [(Opt.Expr, Opt.Expr)]
300+ -> [(Opt.Expr, Opt.Expr)]
301+ -> Opt.Expr
302+ -> ([(Opt.Expr, Opt.Expr)], Opt.Expr)
303+crushIfsHelp visitedBranches unvisitedBranches finally =
304+ case unvisitedBranches of
305+ [] ->
306+ case finally of
307+ If subBranches subFinally ->
308+ crushIfsHelp visitedBranches subBranches subFinally
309+
310+ _ ->
311+ (reverse visitedBranches, finally)
312+
313+ (Literal (L.Boolean True), branch) : _ ->
314+ crushIfsHelp visitedBranches [] branch
315+
316+ visiting : unvisited ->
317+ crushIfsHelp (visiting : visitedBranches) unvisited finally
318+
319+
320+-- CASE EXPRESSIONS
321+
322+generateCase
323+ :: String
324+ -> DT.DecisionTree Opt.Jump
325+ -> [(Int, Opt.Branch)]
326+ -> State Int [Statement ()]
327+generateCase root decisionTree jumpBranches =
328+ do decider <- generateDecisionTree root decisionTree
329+ foldM (goto root) decider jumpBranches
330+
331+
332+goto :: String -> [Statement ()] -> (Int, Opt.Branch) -> State Int [Statement ()]
333+goto root decider (target, branch) =
334+ let
335+ deciderStmt =
336+ LabelledStmt ()
337+ (targetLabel root target)
338+ (DoWhileStmt () (BlockStmt () decider) (BoolLit () False))
339+ in
340+ do stmts <- generateBranch root branch
341+ return (deciderStmt : stmts)
342+
343+
344+targetLabel :: String -> Int -> Id ()
345+targetLabel root target =
346+ Id () (root ++ "_" ++ show target)
347+
348+
349+generateDecisionTree :: String -> DT.DecisionTree Opt.Jump -> State Int [Statement ()]
350+generateDecisionTree root decisionTree =
351+ case decisionTree of
352+ DT.Match (Opt.Inline branch) ->
353+ generateBranch root branch
354+
355+ DT.Match (Opt.Jump target) ->
356+ return [ BreakStmt () (Just (targetLabel root target)) ]
357+
358+ DT.Decision testPath [(test, subTree)] (Just fallback) ->
359+ let
360+ (tests, deepestSubTree) =
361+ collapseTests [(testPath, test)] fallback subTree
362+
363+ makeTest (path, test) =
364+ do testExpr <- pathToTestableExpr root path test
365+ return (InfixExpr () OpStrictEq testExpr (testToExpr test))
366+ in
367+ do testExprs <- mapM makeTest tests
368+ let cond = List.foldl1' (InfixExpr () OpLAnd) testExprs
369+ thenBranch <- generateDecisionTree root deepestSubTree
370+ elseBranch <- generateDecisionTree root fallback
371+ return [ IfStmt () cond (BlockStmt () thenBranch) (BlockStmt () elseBranch) ]
372+
373+ DT.Decision testPath edges fallback ->
374+ do testExpr <- pathToTestableExpr root testPath (fst (head edges))
375+ caseClauses <- mapM (edgeToCaseClause root) edges
376+ caseDefault <- fallbackToDefault root fallback
377+ return [ SwitchStmt () testExpr (caseClauses ++ caseDefault) ]
378+
379+
380+collapseTests
381+ :: [(DT.Path, DT.Test)]
382+ -> DT.DecisionTree Opt.Jump
383+ -> DT.DecisionTree Opt.Jump
384+ -> ([(DT.Path, DT.Test)], DT.DecisionTree Opt.Jump)
385+collapseTests tests outerFallback decisionTree =
386+ case decisionTree of
387+ DT.Decision testPath [(test, subTree)] (Just fallback)
388+ | fallback == outerFallback ->
389+ collapseTests ((testPath, test) : tests) outerFallback subTree
390+
391+ _ ->
392+ (tests, decisionTree)
393+
394+
395+edgeToCaseClause :: String -> (DT.Test, DT.DecisionTree Opt.Jump) -> State Int (CaseClause ())
396+edgeToCaseClause root (test, subTree) =
397+ CaseClause () (testToExpr test) <$> generateDecisionTree root subTree
398+
399+
400+pathToTestableExpr :: String -> DT.Path -> DT.Test -> State Int (Expression ())
401+pathToTestableExpr root path exampleTest =
402+ do accessExpr <- generateJsExpr (pathToExpr root path)
403+ case exampleTest of
404+ DT.Constructor _ ->
405+ return (DotRef () accessExpr (Id () "ctor"))
406+
407+ DT.Literal _ ->
408+ return accessExpr
409+
410+
411+testToExpr :: DT.Test -> Expression ()
412+testToExpr test =
413+ case test of
414+ DT.Constructor (Var.Canonical _ tag) ->
415+ StringLit () tag
416+
417+ DT.Literal (L.Chr char) ->
418+ StringLit () [char]
419+
420+ DT.Literal lit ->
421+ Literal.literal lit
422+
423+
424+fallbackToDefault :: String -> Maybe (DT.DecisionTree Opt.Jump) -> State Int [CaseClause ()]
425+fallbackToDefault root fallback =
426+ case fallback of
427+ Nothing ->
428+ return []
429+
430+ Just subTree ->
431+ do stmts <- generateDecisionTree root subTree
432+ return [ CaseDefault () stmts ]
433+
434+
435+generateBranch :: String -> Opt.Branch -> State Int [Statement ()]
436+generateBranch root (Opt.Branch substitutions expr) =
437+ do substs <- mapM (loadPath root) substitutions
438+ let substStmts =
439+ if null substs then [] else [ VarDeclStmt () substs ]
440+ code <- generateCode expr
441+ return (substStmts ++ toStatementList code)
442+
443+
444+loadPath :: String -> (String, DT.Path) -> State Int (VarDecl ())
445+loadPath root (name, path) =
446+ do jsAccessExpr <- generateJsExpr (pathToExpr root path)
447+ return $ varDecl (Var.safe name) jsAccessExpr
448+
449+
450+pathToExpr :: String -> DT.Path -> Opt.Expr
451+pathToExpr root fullPath =
452+ go (Opt.Var (Var.local root)) fullPath
453+ where
454+ go expr path =
455+ case path of
456+ DT.Position index subpath ->
457+ go (Opt.DataAccess expr index) subpath
458+
459+ DT.Field field subpath ->
460+ go (Opt.Access expr field) subpath
461+
462+ DT.Empty ->
463+ expr
464+
465+ DT.Alias ->
466+ expr
467+
468+
469+-- BINARY OPERATORS
470+
471+binop
472+ :: Var.Canonical
473+ -> Opt.Expr
474+ -> Opt.Expr
475+ -> State Int Code
476+binop func left right =
477+ do jsLeft <- generateJsExpr left
478+ jsRight <- generateJsExpr right
479+ jsExpr (makeExpr func jsLeft jsRight)
480+
481+
482+-- BINARY OPERATOR HELPERS
483+
484+makeExpr :: Var.Canonical -> (Expression () -> Expression () -> Expression ())
485+makeExpr qualifiedOp@(Var.Canonical home op) =
486+ let
487+ simpleMake left right =
488+ ref "A2" `call` [ Var.canonical qualifiedOp, left, right ]
489+ in
490+ if home == Var.Module (ModuleName.inCore ["Basics"]) then
491+ Map.findWithDefault simpleMake op basicOps
492+ else
493+ simpleMake
494+
495+
496+basicOps :: Map.Map String (Expression () -> Expression () -> Expression ())
497+basicOps =
498+ Map.fromList (infixOps ++ specialOps)
499+
500+
501+infixOps :: [(String, Expression () -> Expression () -> Expression ())]
502+infixOps =
503+ let
504+ infixOp str op =
505+ (str, InfixExpr () op)
506+ in
507+ [ infixOp "+" OpAdd
508+ , infixOp "-" OpSub
509+ , infixOp "*" OpMul
510+ , infixOp "/" OpDiv
511+ , infixOp "&&" OpLAnd
512+ , infixOp "||" OpLOr
513+ ]
514+
515+
516+specialOps :: [(String, Expression () -> Expression () -> Expression ())]
517+specialOps =
518+ [ (,) "^" $ \a b -> obj ["Math","pow"] `call` [a,b]
519+ , (,) "==" $ \a b -> BuiltIn.eq a b
520+ , (,) "/=" $ \a b -> PrefixExpr () PrefixLNot (BuiltIn.eq a b)
521+ , (,) "<" $ cmp OpLT 0
522+ , (,) ">" $ cmp OpGT 0
523+ , (,) "<=" $ cmp OpLT 1
524+ , (,) ">=" $ cmp OpGT (-1)
525+ , (,) "//" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
526+ ]
527+
528+
529+cmp :: InfixOp -> Int -> Expression () -> Expression () -> Expression ()
530+cmp op n a b =
531+ InfixExpr () op (BuiltIn.compare a b) (IntLit () n)
src/Generate/JavaScript/Helpers.hs+7−17
@@ -40,14 +40,14 @@ prop name =
4040 PropId () (var name)
4141
4242
43−string = StringLit ()
44−
45−
4643obj :: [String] -> Expression ()
4744obj vars =
4845 case vars of
49− x:xs -> foldl (DotRef ()) (ref x) (map var xs)
50− [] -> error "dotSep must be called on a non-empty list of variables"
46+ x:xs ->
47+ foldl (DotRef ()) (ref x) (map var xs)
48+
49+ [] ->
50+ error "dotSep must be called on a non-empty list of variables"
5151
5252
5353-- Function Calls
@@ -57,16 +57,6 @@ obj vars =
5757 CallExpr () f [x]
5858
5959
60−ret :: Expression () -> Statement ()
61−ret e =
62− ReturnStmt () (Just e)
63−
64−
65−(==>) :: [String] -> Expression () -> Expression ()
66−(==>) args e =
67− FuncExpr () Nothing (map var args) [ ret e ]
68−
69−
7060function :: [String] -> [Statement ()] -> Expression ()
7161function args stmts =
7262 FuncExpr () Nothing (map var args) stmts
@@ -91,9 +81,9 @@ instanceof tipe x =
9181
9282typeof :: String -> Expression () -> Expression ()
9383typeof tipe x =
94− equal (PrefixExpr () PrefixTypeof x) (string tipe)
84+ equal (PrefixExpr () PrefixTypeof x) (StringLit () tipe)
9585
9686
9787member :: String -> Expression () -> Expression ()
9888member field x =
99− InfixExpr () OpIn (string field) x
89+ InfixExpr () OpIn (StringLit () field) x
src/Generate/JavaScript/Port.hs+13−13
@@ -19,7 +19,7 @@ task name expr portType =
1919 _Task "perform" `call` [ expr ]
2020
2121 T.Signal _ _ ->
22− _Task "performSignal" `call` [ string name, expr ]
22+ _Task "performSignal" `call` [ StringLit () name, expr ]
2323
2424
2525
@@ -77,7 +77,7 @@ check x jsType continue =
7777 foldl1 (InfixExpr () op) (map ($ value) checks)
7878
7979 throw =
80− obj ["_U","badPort"] `call` [ string (typeToString jsType), x ]
80+ obj ["_U","badPort"] `call` [ StringLit () (typeToString jsType), x ]
8181
8282 checks =
8383 case jsType of
@@ -96,22 +96,22 @@ inbound name portType =
9696 case portType of
9797 T.Normal tipe ->
9898 _Port "inbound" `call`
99− [ string name
100− , string (show (P.pretty Map.empty False tipe))
99+ [ StringLit () name
100+ , StringLit () (show (P.pretty Map.empty False tipe))
101101 , toTypeFunction tipe
102102 ]
103103
104104 T.Signal _root arg ->
105105 _Port "inboundSignal" `call`
106− [ string name
107− , string (show (P.pretty Map.empty False arg))
106+ [ StringLit () name
107+ , StringLit () (show (P.pretty Map.empty False arg))
108108 , toTypeFunction arg
109109 ]
110110
111111
112112toTypeFunction :: T.Canonical -> Expression ()
113113toTypeFunction tipe =
114− ["v"] ==> toType tipe (ref "v")
114+ function ["v"] [ ReturnStmt () (Just (toType tipe (ref "v"))) ]
115115
116116
117117toType :: T.Canonical -> Expression () -> Expression ()
@@ -186,7 +186,7 @@ toTuple types x =
186186 (prop "ctor", ctor) : zipWith convert [0..] types
187187
188188 ctor =
189− string ("_Tuple" ++ show (length types))
189+ StringLit () ("_Tuple" ++ show (length types))
190190
191191 convert n t =
192192 ( prop ('_':show n)
@@ -200,15 +200,15 @@ outbound :: String -> Expression () -> T.Port T.Canonical -> Expression ()
200200outbound name expr portType =
201201 case portType of
202202 T.Normal tipe ->
203− _Port "outbound" `call` [ string name, fromTypeFunction tipe, expr ]
203+ _Port "outbound" `call` [ StringLit () name, fromTypeFunction tipe, expr ]
204204
205205 T.Signal _ arg ->
206− _Port "outboundSignal" `call` [ string name, fromTypeFunction arg, expr ]
206+ _Port "outboundSignal" `call` [ StringLit () name, fromTypeFunction arg, expr ]
207207
208208
209209fromTypeFunction :: T.Canonical -> Expression ()
210210fromTypeFunction tipe =
211− ["v"] ==> fromType tipe (ref "v")
211+ function ["v"] [ ReturnStmt () (Just (fromType tipe (ref "v"))) ]
212212
213213
214214fromType :: T.Canonical -> Expression () -> Expression ()
@@ -230,7 +230,7 @@ fromType tipe x =
230230 func body =
231231 function (take numArgs args)
232232 [ VarDeclStmt () [VarDecl () (var "_r") (Just body)]
233− , ret (fromType (last ts) (ref "_r"))
233+ , ReturnStmt () (Just (fromType (last ts) (ref "_r")))
234234 ]
235235
236236 T.Var _ ->
@@ -250,7 +250,7 @@ fromType tipe x =
250250 T.Type name : [t]
251251 | Var.isMaybe name ->
252252 CondExpr ()
253− (equal (DotRef () x (var "ctor")) (string "Nothing"))
253+ (equal (DotRef () x (var "ctor")) (StringLit () "Nothing"))
254254 (NullLit ())
255255 (fromType t (DotRef () x (var "_0")))
256256
src/Generate/JavaScript/Variable.hs+33−38
@@ -1,4 +1,11 @@
1−module Generate.JavaScript.Variable (fresh, canonical, define, safe) where
1+module Generate.JavaScript.Variable
2+ ( fresh
3+ , canonical
4+ , modulePrefix
5+ , define
6+ , safe
7+ )
8+ where
29
310import qualified Control.Monad.State as State
411import qualified Data.List as List
@@ -8,7 +15,6 @@ import qualified Language.ECMAScript3.Syntax as JS
815import qualified AST.Helpers as Help
916import qualified AST.Module.Name as ModuleName
1017import qualified AST.Variable as Var
11−import qualified Elm.Package as Pkg
1218import qualified Generate.JavaScript.Helpers as JS
1319
1420
@@ -23,29 +29,20 @@ fresh =
2329
2430-- DEF NAMES
2531
26−define :: Maybe ModuleName.Canonical -> String -> JS.Expression () -> JS.Statement ()
27−define maybeHome name body =
28− let
29− varDecl safeName =
30− JS.VarDeclStmt () [ JS.VarDecl () (JS.Id () safeName) (Just body) ]
31− in
32− case maybeHome of
33− Nothing ->
34− varDecl (safe name)
35−
36− Just home ->
37− if Help.isOp name then
38− let
39− root =
40− JS.VarRef () (JS.Id () (canonicalPrefix home "_op"))
32+define :: String -> JS.Expression () -> JS.Statement ()
33+define name body =
34+ if Help.isOp name then
35+ let
36+ root =
37+ JS.VarRef () (JS.Id () "_op")
4138
42− lvalue =
43− JS.LBracket () root (JS.StringLit () name)
44− in
45− JS.ExprStmt () (JS.AssignExpr () JS.OpAssign lvalue body)
39+ lvalue =
40+ JS.LBracket () root (JS.StringLit () name)
41+ in
42+ JS.ExprStmt () (JS.AssignExpr () JS.OpAssign lvalue body)
4643
47− else
48− varDecl (canonicalPrefix home (safe name))
44+ else
45+ JS.VarDeclStmt () [ JS.VarDecl () (JS.Id () (safe name)) (Just body) ]
4946
5047
5148-- INSTANTIATE VARIABLES
@@ -53,34 +50,31 @@ define maybeHome name body =
5350canonical :: Var.Canonical -> JS.Expression ()
5451canonical (Var.Canonical home name) =
5552 if Help.isOp name then
56− JS.BracketRef () (JS.ref (addRoot home "_op")) (JS.string name)
53+ JS.BracketRef () (addRoot home "_op") (JS.StringLit () name)
5754
5855 else
59− JS.ref (addRoot home (safe name))
56+ addRoot home (safe name)
6057
6158
62−addRoot :: Var.Home -> String -> String
59+addRoot :: Var.Home -> String -> JS.Expression ()
6360addRoot home name =
6461 case home of
6562 Var.Local ->
66− name
63+ JS.ref name
6764
68− Var.TopLevel moduleName ->
69− canonicalPrefix moduleName name
65+ Var.TopLevel _moduleName ->
66+ JS.ref name
7067
7168 Var.BuiltIn ->
72− name
69+ JS.ref name
7370
74− Var.Module moduleName ->
75− canonicalPrefix moduleName name
71+ Var.Module (ModuleName.Canonical _ moduleName) ->
72+ JS.DotRef () (JS.ref (modulePrefix moduleName)) (JS.Id () name)
7673
7774
78−canonicalPrefix :: ModuleName.Canonical -> String -> String
79−canonicalPrefix (ModuleName.Canonical (Pkg.Name user project) moduleName) name =
80− map (swap '-' '_') user
81− ++ '$' : map (swap '-' '_') project
82− ++ '$' : List.intercalate "$" moduleName
83− ++ '$' : safe name
75+modulePrefix :: ModuleName.Raw -> String
76+modulePrefix moduleName =
77+ '$' : List.intercalate "$" moduleName
8478
8579
8680swap :: Char -> Char -> Char -> Char
@@ -115,4 +109,5 @@ jsReserveds =
115109 -- reserved by the Elm runtime system
116110 , "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
117111 , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
112+ , JS.localRuntime
118113 ]
src/Nitpick/PatternMatches.hs−1
@@ -1,6 +1,5 @@
11module Nitpick.PatternMatches (patternMatches) where
22
3−import Control.Applicative ((<$>), (<*))
43import Control.Arrow (second)
54import qualified Data.Foldable as F
65import qualified Data.Map as Map
src/Optimize.hs−1
@@ -1,6 +1,5 @@
11module Optimize (optimize) where
22
3−import Control.Applicative
43import qualified Control.Monad as M
54import qualified Data.Traversable as T
65
src/Parse/Binop.hs−1
@@ -1,6 +1,5 @@
11module Parse.Binop (binops, OpTable) where
22
3−import Control.Applicative ((<$>))
43import qualified Data.List as List
54import qualified Data.Map as Map
65import Text.Parsec ((<|>), choice, getState, try)
src/Parse/Declaration.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
22module Parse.Declaration where
33
4−import Control.Applicative ((<$>))
54import Text.Parsec ( (<|>), (<?>), choice, digit, optionMaybe, string, try )
65
76import qualified AST.Declaration as D
src/Parse/Expression.hs−1
@@ -1,6 +1,5 @@
11module Parse.Expression (term, typeAnnotation, definition, expr) where
22
3−import Control.Applicative ((<$>), (<*>))
43import qualified Data.List as List
54import Text.Parsec hiding (newline, spaces)
65import Text.Parsec.Indent (block, withPos)
src/Parse/Helpers.hs+1−2
@@ -1,7 +1,6 @@
11module Parse.Helpers where
22
33import Prelude hiding (until)
4−import Control.Applicative ((<$>),(<*>),(<*))
54import Control.Monad (guard, join)
65import Control.Monad.State (State)
76import Data.Char (isUpper)
@@ -118,7 +117,7 @@ anyOp =
118117
119118symOp :: IParser String
120119symOp =
121− do op <- many1 (satisfy Help.isSymbol)
120+ do op <- many1 (satisfy (\c -> Help.isSymbol c && c /= '`'))
122121 guard (op `notElem` [ "=", "..", "->", "--", "|", ":" ])
123122 case op of
124123 "." -> notFollowedBy lower >> return op
src/Parse/Literal.hs−1
@@ -1,7 +1,6 @@
11module Parse.Literal (literal) where
22
33import Prelude hiding (exponent)
4−import Control.Applicative ((<$>))
54import Text.Parsec ((<|>), (<?>), digit, hexDigit, lookAhead, many1, option, string, try)
65import Parse.Helpers (IParser, chr, str)
76import qualified AST.Literal as L
src/Parse/Module.hs−1
@@ -1,6 +1,5 @@
11module Parse.Module (moduleDecl, header, getModuleName) where
22
3−import Control.Applicative ((<$>), (<*>))
43import Text.Parsec hiding (newline, spaces)
54
65import Parse.Helpers
src/Parse/Parse.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall #-}
22module Parse.Parse (program, parse) where
33
4−import Control.Applicative ((<$>), (<*>))
54import qualified Data.Map as Map
65import qualified Data.Traversable as T
76import Text.Parsec (char, eof, letter, many, optional, putState, (<|>))
src/Parse/Pattern.hs−1
@@ -1,6 +1,5 @@
11module Parse.Pattern (term, expr) where
22
3−import Control.Applicative ((<$>))
43import Data.Char (isUpper)
54import qualified Data.List as List
65import Text.Parsec ((<|>), (<?>), char, choice, optionMaybe, try)
src/Parse/Type.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
22module Parse.Type where
33
4−import Control.Applicative ((<$>),(<*>),(<*))
54import Data.List (intercalate)
65import Text.Parsec ((<|>), (<?>), char, many, optionMaybe, string, try)
76
src/Reporting/Result.hs+1−1
@@ -1,6 +1,6 @@
11module Reporting.Result where
22
3−import Control.Applicative (Applicative, (<*>), (<|>), pure)
3+import Control.Applicative ((<|>))
44import qualified Control.Monad as M
55import Control.Monad.Except (Except, runExcept)
66
src/Type/Constrain/Expression.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall #-}
22module Type.Constrain.Expression where
33
4−import Control.Applicative ((<$>))
54import Control.Arrow (second)
65import qualified Control.Monad as Monad
76import qualified Data.List as List
src/Type/Constrain/Pattern.hs−1
@@ -2,7 +2,6 @@
22module Type.Constrain.Pattern where
33
44import Control.Arrow (second)
5−import Control.Applicative ((<$>))
65import qualified Control.Monad as Monad
76import qualified Data.Map as Map
87
src/Type/Environment.hs−1
@@ -1,6 +1,5 @@
11module Type.Environment where
22
3−import Control.Applicative ((<$>), (<*>))
43import Control.Monad (forM)
54import qualified Control.Monad.State as State
65import qualified Data.Traversable as Traverse
src/Type/Solve.hs+1−1
@@ -1,6 +1,6 @@
11module Type.Solve (solve) where
22
3−import Control.Applicative ((<$>), (<*>), (<|>))
3+import Control.Applicative ((<|>))
44import Control.Monad
55import Control.Monad.State (StateT, execStateT, liftIO)
66import Control.Monad.Except (ExceptT, throwError)
src/Type/State.hs+1−1
@@ -2,7 +2,7 @@
22{-# LANGUAGE MultiParamTypeClasses #-}
33module Type.State where
44
5−import Control.Applicative ( Applicative, (<$>), (<*>), (<|>) )
5+import Control.Applicative ((<|>))
66import Control.Monad.State
77import Data.Map ((!))
88import qualified Data.Map as Map
src/Type/Type.hs−1
@@ -1,6 +1,5 @@
11module Type.Type where
22
3−import Control.Applicative ((<$>),(<*>))
43import Control.Monad.State (StateT)
54import qualified Control.Monad.State as State
65import qualified Data.Char as Char
src/Validate.hs−1
@@ -1,7 +1,6 @@
11{-# OPTIONS_GHC -Wall #-}
22module Validate (declarations) where
33
4−import Control.Applicative ((<$>),(<*>))
54import qualified Data.Map as Map
65import qualified Data.Set as Set
76import qualified Data.Foldable as F
tests/test-files/good-expected-js/AliasSubstitution.elm.js+10−3
@@ -1,4 +1,11 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$extractVec = function (v) {
3− return {_: {},x: v.x,y: v.y};
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var extractVec = function (v) {
8+ return {_: {},x: v.x,y: v.y};
9+ };
10+ return _elm.Main.values = {_op: _op,extractVec: extractVec};
411};
tests/test-files/good-expected-js/CaseExpression3.elm.js+31−27
@@ -1,27 +1,31 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$Cons = F2(function (a,
3−b) {
4− return {ctor: "Cons",_0: a,_1: b};
5−});
6−var elm_lang$core$Main$Nil = {ctor: "Nil"};
7−var elm_lang$core$Main$zip = F2(function (list1,
8−list2) {
9− var _p0 = {ctor: "_Tuple2"
10− ,_0: list1
11− ,_1: list2};
12− if (_p0._0.ctor === "Nil") {
13− return elm_lang$core$Main$Nil;
14− } else {
15− if (_p0._1.ctor === "Nil") {
16− return elm_lang$core$Main$Nil;
17− } else {
18− var x = _p0._0._0,
19− xs = _p0._0._1,
20− y = _p0._1._0,
21− ys = _p0._1._1;
22− return A2(elm_lang$core$Main$Cons,
23− {ctor: "_Tuple2",_0: x,_1: y},
24− A2(elm_lang$core$Main$zip,xs,ys));
25− }
26− }
27−});
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var Cons = F2(function (a,b) {
8+ return {ctor: "Cons",_0: a,_1: b};
9+ });
10+ var Nil = {ctor: "Nil"};
11+ var zip = F2(function (list1,list2) {
12+ var _p0 = {ctor: "_Tuple2",_0: list1,_1: list2};
13+ if (_p0._0.ctor === "Nil") {
14+ return Nil;
15+ } else {
16+ if (_p0._1.ctor === "Nil") {
17+ return Nil;
18+ } else {
19+ var x = _p0._0._0,
20+ xs = _p0._0._1,
21+ y = _p0._1._0,
22+ ys = _p0._1._1;
23+ return A2(Cons,{ctor: "_Tuple2",_0: x,_1: y},A2(zip,xs,ys));
24+ }
25+ }
26+ });
27+ return _elm.Main.values = {_op: _op
28+ ,Nil: Nil
29+ ,Cons: Cons
30+ ,zip: zip};
31+};
tests/test-files/good-expected-js/Lists/EmptyList.elm.js+9−2
@@ -1,2 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$emptyList = _utils.list([]);
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var emptyList = _utils.list([]);
8+ return _elm.Main.values = {_op: _op,emptyList: emptyList};
9+};
tests/test-files/good-expected-js/Lists/ListRange.elm.js+9−3
@@ -1,3 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$listRange = _utils.range(2,
3−10);
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var listRange = _utils.range(2,10);
8+ return _elm.Main.values = {_op: _op,listRange: listRange};
9+};
tests/test-files/good-expected-js/Lists/NonEmptyList.elm.js+9−4
@@ -1,4 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$nonEmptyList = _utils.list([1
3− ,4
4− ,5]);
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var nonEmptyList = _utils.list([1,4,5]);
8+ return _elm.Main.values = {_op: _op,nonEmptyList: nonEmptyList};
9+};
tests/test-files/good-expected-js/NoExpressions.elm.js+8−1
@@ -1 +1,8 @@
1−var elm_lang$core$Main$_op = {};
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ return _elm.Main.values = {_op: _op};
8+};
tests/test-files/good-expected-js/Otherwise.elm.js+12−3
@@ -1,3 +1,12 @@
1−var elm_lang$core$Otherwise$_op = {};
2−var elm_lang$core$Otherwise$boo = false ? "Yay" : "Boo";
3−var elm_lang$core$Otherwise$otherwise = 3;
1+Elm.Otherwise = Elm.Otherwise || {};
2+Elm.Otherwise.make = function (_elm) {
3+ "use strict";
4+ _elm.Otherwise = _elm.Otherwise || {};
5+ if (_elm.Otherwise.values) return _elm.Otherwise.values;
6+ var _op = {};
7+ var boo = false ? "Yay" : "Boo";
8+ var otherwise = 3;
9+ return _elm.Otherwise.values = {_op: _op
10+ ,otherwise: otherwise
11+ ,boo: boo};
12+};
tests/test-files/good-expected-js/Ports.elm.js+58−55
@@ -1,57 +1,60 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$students = Elm.Native.Port.make(_elm).outbound("students",
3−function (v) {
4− return Elm.Native.List.make(_elm).toArray(v).map(function (v) {
5− return {name: v.name,age: v.age};
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var students = Elm.Native.Port.make(_elm).outbound("students",
8+ function (v) {
9+ return Elm.Native.List.make(_elm).toArray(v).map(function (v) {
10+ return {name: v.name,age: v.age};
11+ });
12+ },
13+ _utils.list([{_: {},age: 42,name: "Tom"}]));
14+ var time = Elm.Native.Port.make(_elm).outbound("time",
15+ function (v) {
16+ return v;
17+ },
18+ 3.14);
19+ var fortyTwo = Elm.Native.Port.make(_elm).outbound("fortyTwo",
20+ function (v) {
21+ return v;
22+ },
23+ 42);
24+ var record = Elm.Native.Port.make(_elm).inbound("record",
25+ "{ x : Float, y : Float }",
26+ function (v) {
27+ return typeof v === "object" && "x" in v && "y" in v ? {_: {}
28+ ,x: typeof v.x === "number" ? v.x : _U.badPort("a number",v.x)
29+ ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
30+ v.y)} : _U.badPort("an object with fields `x`, `y`",v);
631 });
7−},
8−_utils.list([{_: {},age: 42,name: "Tom"}]));
9−var elm_lang$core$Main$time = Elm.Native.Port.make(_elm).outbound("time",
10−function (v) {
11− return v;
12−},
13−3.14);
14−var elm_lang$core$Main$fortyTwo = Elm.Native.Port.make(_elm).outbound("fortyTwo",
15−function (v) {
16− return v;
17−},
18−42);
19−var elm_lang$core$Main$record = Elm.Native.Port.make(_elm).inbound("record",
20−"{ x : Float, y : Float }",
21−function (v) {
22− return typeof v === "object" && "x" in v && "y" in v ? {_: {}
23− ,x: typeof v.x === "number" ? v.x : _U.badPort("a number",
24− v.x)
25− ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
26− v.y)} : _U.badPort("an object with fields `x`, `y`",
27− v);
28−});
29−var elm_lang$core$Main$array = Elm.Native.Port.make(_elm).inbound("array",
30−"List Int",
31−function (v) {
32− return typeof v === "object" && v instanceof Array ? Elm.Native.List.make(_elm).fromArray(v.map(function (v) {
33− return typeof v === "number" ? v : _U.badPort("a number",
32+ var array = Elm.Native.Port.make(_elm).inbound("array",
33+ "List Int",
34+ function (v) {
35+ return typeof v === "object" && v instanceof Array ? Elm.Native.List.make(_elm).fromArray(v.map(function (v) {
36+ return typeof v === "number" ? v : _U.badPort("a number",v);
37+ })) : _U.badPort("an array",v);
38+ });
39+ var tuple = Elm.Native.Port.make(_elm).inbound("tuple",
40+ "(Float, Bool)",
41+ function (v) {
42+ return typeof v === "object" && v instanceof Array ? {ctor: "_Tuple2"
43+ ,_0: typeof v[0] === "number" ? v[0] : _U.badPort("a number",
44+ v[0])
45+ ,_1: typeof v[1] === "boolean" ? v[1] : _U.badPort("a boolean (true or false)",
46+ v[1])} : _U.badPort("an array",v);
47+ });
48+ var number = Elm.Native.Port.make(_elm).inbound("number",
49+ "Int",
50+ function (v) {
51+ return typeof v === "number" ? v : _U.badPort("a number",v);
52+ });
53+ var userID = Elm.Native.Port.make(_elm).inbound("userID",
54+ "String",
55+ function (v) {
56+ return typeof v === "string" || typeof v === "object" && v instanceof String ? v : _U.badPort("a string",
3457 v);
35− })) : _U.badPort("an array",v);
36−});
37−var elm_lang$core$Main$tuple = Elm.Native.Port.make(_elm).inbound("tuple",
38−"(Float, Bool)",
39−function (v) {
40− return typeof v === "object" && v instanceof Array ? {ctor: "_Tuple2"
41− ,_0: typeof v[0] === "number" ? v[0] : _U.badPort("a number",
42− v[0])
43− ,_1: typeof v[1] === "boolean" ? v[1] : _U.badPort("a boolean (true or false)",
44− v[1])} : _U.badPort("an array",v);
45−});
46−var elm_lang$core$Main$number = Elm.Native.Port.make(_elm).inbound("number",
47−"Int",
48−function (v) {
49− return typeof v === "number" ? v : _U.badPort("a number",
50− v);
51−});
52−var elm_lang$core$Main$userID = Elm.Native.Port.make(_elm).inbound("userID",
53−"String",
54−function (v) {
55− return typeof v === "string" || typeof v === "object" && v instanceof String ? v : _U.badPort("a string",
56− v);
57−});
58+ });
59+ return _elm.Main.values = {_op: _op};
60+};
tests/test-files/good-expected-js/PortsWithTypeAliases.elm.js+26−25
@@ -1,25 +1,26 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$pairs = Elm.Native.Port.make(_elm).inbound("pairs",
3−"Main.Point String String",
4−function (v) {
5− return typeof v === "object" && "x" in v && "y" in v ? {_: {}
6− ,x: typeof v.x === "string" || typeof v.x === "object" && v.x instanceof String ? v.x : _U.badPort("a string",
7− v.x)
8− ,y: typeof v.y === "string" || typeof v.y === "object" && v.y instanceof String ? v.y : _U.badPort("a string",
9− v.y)} : _U.badPort("an object with fields `x`, `y`",
10− v);
11−});
12−var elm_lang$core$Main$points = Elm.Native.Port.make(_elm).inbound("points",
13−"Main.Point2D",
14−function (v) {
15− return typeof v === "object" && "x" in v && "y" in v ? {_: {}
16− ,x: typeof v.x === "number" ? v.x : _U.badPort("a number",
17− v.x)
18− ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
19− v.y)} : _U.badPort("an object with fields `x`, `y`",
20− v);
21−});
22−var elm_lang$core$Main$Point = F2(function (a,
23−b) {
24− return {_: {},x: a,y: b};
25−});
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var pairs = Elm.Native.Port.make(_elm).inbound("pairs",
8+ "Main.Point String String",
9+ function (v) {
10+ return typeof v === "object" && "x" in v && "y" in v ? {_: {}
11+ ,x: typeof v.x === "string" || typeof v.x === "object" && v.x instanceof String ? v.x : _U.badPort("a string",
12+ v.x)
13+ ,y: typeof v.y === "string" || typeof v.y === "object" && v.y instanceof String ? v.y : _U.badPort("a string",
14+ v.y)} : _U.badPort("an object with fields `x`, `y`",v);
15+ });
16+ var points = Elm.Native.Port.make(_elm).inbound("points",
17+ "Main.Point2D",
18+ function (v) {
19+ return typeof v === "object" && "x" in v && "y" in v ? {_: {}
20+ ,x: typeof v.x === "number" ? v.x : _U.badPort("a number",v.x)
21+ ,y: typeof v.y === "number" ? v.y : _U.badPort("a number",
22+ v.y)} : _U.badPort("an object with fields `x`, `y`",v);
23+ });
24+ var Point = F2(function (a,b) { return {_: {},x: a,y: b};});
25+ return _elm.Main.values = {_op: _op,Point: Point};
26+};
tests/test-files/good-expected-js/QuotesAndComments.elm.js+18−7
@@ -1,8 +1,19 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$commentStart = "{-";
3−var elm_lang$core$Main$singleQuote = _utils.chr("\'");
4−var elm_lang$core$Main$doubleQuote = _utils.chr("\"");
5−var elm_lang$core$Main$variablesWithPrimes = function (x) {
6− var x$ = x;
7− return x$;
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var commentStart = "{-";
8+ var singleQuote = _utils.chr("\'");
9+ var doubleQuote = _utils.chr("\"");
10+ var variablesWithPrimes = function (x) {
11+ var x$ = x;
12+ return x$;
13+ };
14+ return _elm.Main.values = {_op: _op
15+ ,variablesWithPrimes: variablesWithPrimes
16+ ,doubleQuote: doubleQuote
17+ ,singleQuote: singleQuote
18+ ,commentStart: commentStart};
819};
tests/test-files/good-expected-js/Soundness/Apply.elm.js+11−4
@@ -1,5 +1,12 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$apply = function (f) {
3− var g = function (x) { return f(x);};
4− return g;
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var apply = function (f) {
8+ var g = function (x) { return f(x);};
9+ return g;
10+ };
11+ return _elm.Main.values = {_op: _op,apply: apply};
512};
tests/test-files/good-expected-js/Soundness/ApplyAnnotated.elm.js+11−4
@@ -1,5 +1,12 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$apply = function (f) {
3− var g = function (x) { return f(x);};
4− return g;
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var apply = function (f) {
8+ var g = function (x) { return f(x);};
9+ return g;
10+ };
11+ return _elm.Main.values = {_op: _op,apply: apply};
512};
tests/test-files/good-expected-js/Soundness/Id.elm.js+12−5
@@ -1,5 +1,12 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$myId = function () {
3− var id = function (x) { return x;};
4− return id;
5−}();
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var myId = function () {
8+ var id = function (x) { return x;};
9+ return id;
10+ }();
11+ return _elm.Main.values = {_op: _op,myId: myId};
12+};
tests/test-files/good-expected-js/Soundness/IdAnnotated.elm.js+12−5
@@ -1,5 +1,12 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$myId = function () {
3− var id = function (x) { return x;};
4− return id;
5−}();
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var myId = function () {
8+ var id = function (x) { return x;};
9+ return id;
10+ }();
11+ return _elm.Main.values = {_op: _op,myId: myId};
12+};
tests/test-files/good-expected-js/Soundness/TrickyId.elm.js+8−4
@@ -1,5 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$myId = function (x) {
3− var y = x;
4− return y;
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var myId = function (x) { var y = x;return y;};
8+ return _elm.Main.values = {_op: _op,myId: myId};
59};
tests/test-files/good-expected-js/Soundness/TrickyIdAnnotated.elm.js+8−4
@@ -1,5 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$myId = function (x) {
3− var y = x;
4− return y;
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var myId = function (x) { var y = x;return y;};
8+ return _elm.Main.values = {_op: _op,myId: myId};
59};
tests/test-files/good-expected-js/Strings/Multiline.elm.js+9−2
@@ -1,2 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$s = "\nhere\'s a quote: \"\n\n";
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var s = "\nhere\'s a quote: \"\n\n";
8+ return _elm.Main.values = {_op: _op,s: s};
9+};
tests/test-files/good-expected-js/Strings/MultilineNormal.elm.js+9−2
@@ -1,2 +1,9 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$s = "\nhere\'s a quote: \"\n\n";
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var s = "\nhere\'s a quote: \"\n\n";
8+ return _elm.Main.values = {_op: _op,s: s};
9+};
tests/test-files/good-expected-js/TailRecursive.elm.js+24−17
@@ -1,17 +1,24 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$any = F2(function (f,l) {
3− any: while (true) {
4− var _p0 = l;
5− if (_p0.ctor === "::") {
6− var x = _p0._0,xs = _p0._1;
7− if (f(x)) return true; else {
8− var _v0 = f,_v1 = xs;
9− f = _v0;
10− l = _v1;
11− continue any;
12− }
13− } else {
14− return false;
15− }
16− }
17−});
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var any = F2(function (f,l) {
8+ any: while (true) {
9+ var _p0 = l;
10+ if (_p0.ctor === "::") {
11+ var x = _p0._0,xs = _p0._1;
12+ if (f(x)) return true; else {
13+ var _v0 = f,_v1 = xs;
14+ f = _v0;
15+ l = _v1;
16+ continue any;
17+ }
18+ } else {
19+ return false;
20+ }
21+ }
22+ });
23+ return _elm.Main.values = {_op: _op,any: any};
24+};
tests/test-files/good-expected-js/Unify/NonHomogeneousRecords.elm.js+10−10
@@ -1,10 +1,10 @@
1−var elm_lang$core$Main$_op = {};
2−var elm_lang$core$Main$f = function (t) {
3− var y = t.y;
4− var x = t.x;
5− return t;
6−};
7−var elm_lang$core$Main$Thing = F2(function (a,
8−b) {
9− return {_: {},x: a,y: b};
10−});
1+Elm.Main = Elm.Main || {};
2+Elm.Main.make = function (_elm) {
3+ "use strict";
4+ _elm.Main = _elm.Main || {};
5+ if (_elm.Main.values) return _elm.Main.values;
6+ var _op = {};
7+ var f = function (t) { var y = t.y;var x = t.x;return t;};
8+ var Thing = F2(function (a,b) { return {_: {},x: a,y: b};});
9+ return _elm.Main.values = {_op: _op,Thing: Thing,f: f};
10+};