@@ -5,13 +5,15 @@ import Control.Monad (liftM,(<=<),join,ap)
5import Data.Char (isAlpha,isDigit)
5import Data.Char (isAlpha,isDigit)
6import Data.List (intercalate,sortBy,inits,foldl')
6import Data.List (intercalate,sortBy,inits,foldl')
7import qualified Data.Map as Map
7import qualified Data.Map as Map
8+import qualified Data.Set as Set
8import Data.Either (partitionEithers)
9import Data.Either (partitionEithers)
9import qualified Text.Pandoc as Pan
10import qualified Text.Pandoc as Pan
10−import Data.Maybe (maybeToList)
12import Unique
12import Unique
13import Generate.Cases
13import Generate.Cases
14import SourceSyntax.Everything hiding (parens)
14import SourceSyntax.Everything hiding (parens)
15+import SourceSyntax.Location as Loc
16+import Transform.SortDefinitions
15import Types.Types ( Type(RecordT) )
17import Types.Types ( Type(RecordT) )
17showErr :: String -> String
19showErr :: String -> String
@@ -80,10 +82,15 @@ getExports names stmts = "\n"++ intercalate ";\n" (op : map fnPair fns)
81 op = ("_.$op = "++) . jsObj $ map opPair ops
83 op = ("_.$op = "++) . jsObj $ map opPair ops
83− get' (FnDef x _ _) = Just (Left x)
85+ get' def =
84− get' (OpDef op _ _ _) = Just (Right op)
86+ case def of
85− get' (TypeAnnotation _ _) = Nothing
87+ TypeAnnotation _ _ -> []
89+ case Set.toList (boundVars pattern) of
90+ [var@(c:_)] -> [if isOp c then Right var else Left var]
91+ vars -> map Left vars
86− get s = case s of Definition d -> maybeToList (get' d)
93+ get s = case s of Definition def -> get' def
87 Datatype _ _ tcs -> map (Left . fst) tcs
94 Datatype _ _ tcs -> map (Left . fst) tcs
88 ImportEvent _ _ x _ -> [ Left x ]
95 ImportEvent _ _ x _ -> [ Left x ]
89 ExportEvent _ _ _ -> []
96 ExportEvent _ _ _ -> []
@@ -125,10 +132,11 @@ stmtsToJS stmts = run $ do program <- mapM toJS (sortBy cmpStmt stmts)
125 valueOf s = case s of
132 valueOf s = case s of
126 Datatype _ _ _ -> 1
133 Datatype _ _ _ -> 1
127 ImportEvent _ _ _ _ -> 2
134 ImportEvent _ _ _ _ -> 2
128− Definition (FnDef f [] _) ->
135+ Definition (Def f (L _ _ (Lambda _ _))) -> 3
136+ Definition (Def (PVar name) _) ->
129− if derename f == "main" then 5 else 4
137+ if derename name == "main" then 5 else 4
138+ Definition (Def _ _) -> 4
130 Definition (TypeAnnotation _ _) -> 0
139 Definition (TypeAnnotation _ _) -> 0
132 ExportEvent _ _ _ -> 6
140 ExportEvent _ _ _ -> 6
133 TypeAlias _ _ _ -> 0
141 TypeAlias _ _ _ -> 0
@@ -136,8 +144,12 @@ class ToJS a where
136 toJS :: a -> Unique String
144 toJS :: a -> Unique String
138instance ToJS (Def t v) where
146instance ToJS (Def t v) where
148+ -- TODO: Make this handle patterns besides plain variables
139− toJS (FnDef x [] e) = assign x `liftM` toJS' e
150+ toJS (Def (PVar x) e) = assign x `liftM` toJS' e
140− toJS (FnDef f as e) = (assign f . wrapper . func) `liftM` toJS' e
152+ toJS (Def f e) = (assign f . wrapper . func) `liftM` toJS' e
142 func body = jsFunc (intercalate ", " as) (ret body)
154 func body = jsFunc (intercalate ", " as) (ret body)
143 wrapper e | length as == 1 = e
155 wrapper e | length as == 1 = e
@@ -146,6 +158,7 @@ instance ToJS (Def t v) where
146 do body <- toJS' e
158 do body <- toJS' e
147 let func = "F2" ++ parens (jsFunc (a1 ++ ", " ++ a2) (ret body))
159 let func = "F2" ++ parens (jsFunc (a1 ++ ", " ++ a2) (ret body))
148 return (globalAssign ("$op['" ++ op ++ "']") func)
160 return (globalAssign ("$op['" ++ op ++ "']") func)
149 toJS (TypeAnnotation _ _) = return ""
162 toJS (TypeAnnotation _ _) = return ""
@@ -155,9 +168,11 @@ instance ToJS (Declaration t v) where
155 Definition d -> toJS d
168 Definition d -> toJS d
156 Datatype _ _ tcs -> concat `liftM` mapM (toJS . toDef) tcs
169 Datatype _ _ tcs -> concat `liftM` mapM (toJS . toDef) tcs
157 where toDef (name,args) =
170 where toDef (name,args) =
158− let vars = map (('a':) . show) [1..length args] in
171+ let vars = map (('a':) . show) [1..length args]
159− Definition . FnDef name vars . none $
172+ body = Loc.none (Data (derename name) (map (Loc.none . Var) vars))
160− Data (derename name) (map (none . Var) vars)
173+ func = foldr (\x e -> Loc.none (Lambda (PVar x) e)) body vars
174+ in Definition $ Def (PVar name) func
161 ImportEvent js base elm _ ->
176 ImportEvent js base elm _ ->
162 do v <- toJS' base
177 do v <- toJS' base
163 return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal(elm).constant(" ++ v ++ ");"
178 return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal(elm).constant(" ++ v ++ ");"
@@ -188,8 +203,8 @@ makeRecord kvs = record `liftM` collect kvs
189 combine r (k,v) = Map.insertWith (++) k v r
204 combine r (k,v) = Map.insertWith (++) k v r
190 collect = liftM (foldl' combine Map.empty) . mapM prep
205 collect = liftM (foldl' combine Map.empty) . mapM prep
191− prep (k, as, e@(L t s _)) =
206+ prep (k, e) =
192− do v <- toJS' (foldr (\x e -> L t s $ Lambda x e) e as)
207+ do v <- toJS' e
193 return (k,[v])
208 return (k,[v])
194 fields fs =
209 fields fs =
195 brackets ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
210 brackets ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
@@ -222,7 +237,22 @@ instance ToJS (Expr t v) where
222 Record fs -> makeRecord fs
237 Record fs -> makeRecord fs
223 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
238 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
225− Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
240+ Lambda p e -> liftM (jsFunc (intercalate ", " args) . ret) (toJS' body)
242+ (args, body) = foldr depattern ([], innerBody) (zip patterns [1..])
244+ depattern (pattern,n) (args, body) =
246+ PVar x -> (x:args, body)
247+ _ -> let arg = "arg" ++ show n
248+ in (arg:args, Loc.none (Case (Loc.none (Var arg)) [(pattern, body)]))
250+ (patterns, innerBody) = collect [p] e
252+ collect patterns lexpr@(L a b expr) =
254+ Lambda p e -> collect (p:patterns) e
255+ _ -> (patterns, lexpr)
227 App e1 e2 -> jsApp e1 e2
257 App e1 e2 -> jsApp e1 e2
228 Let defs e -> jsLet defs e
258 Let defs e -> jsLet defs e
@@ -279,9 +309,8 @@ jsLet defs e' = do ds <- jsDefs defs
280 jsDefs defs = mapM toJS (sortBy f defs)
310 jsDefs defs = mapM toJS (sortBy f defs)
281 f a b = compare (valueOf a) (valueOf b)
311 f a b = compare (valueOf a) (valueOf b)
282− valueOf (FnDef _ [] _) = 2
312+ valueOf (Def _ (L _ _ (Lambda _ _))) = 1
283− valueOf (FnDef _ _ _) = 1
313+ valueOf (Def _ _) = 2
284− valueOf (OpDef _ _ _ _) = 1
285 valueOf (TypeAnnotation _ _) = 0
314 valueOf (TypeAnnotation _ _) = 0
287caseToJS span e ps = do
316caseToJS span e ps = do