@@ -5,13 +5,15 @@ import Control.Monad (liftM,(<=<),join,ap)
55import Data.Char (isAlpha,isDigit)
66import Data.List (intercalate,sortBy,inits,foldl')
77import qualified Data.Map as Map
8+import qualified Data.Set as Set
89import Data.Either (partitionEithers)
910import qualified Text.Pandoc as Pan
10−import Data.Maybe (maybeToList)
1111
1212import Unique
1313import Generate.Cases
1414import SourceSyntax.Everything hiding (parens)
15+import SourceSyntax.Location as Loc
16+import Transform.SortDefinitions
1517import Types.Types ( Type(RecordT) )
1618
1719showErr :: String -> String
@@ -80,10 +82,15 @@ getExports names stmts = "\n"++ intercalate ";\n" (op : map fnPair fns)
8082
8183 op = ("_.$op = "++) . jsObj $ map opPair ops
8284
83− get' (FnDef x _ _) = Just (Left x)
84− get' (OpDef op _ _ _) = Just (Right op)
85− get' (TypeAnnotation _ _) = Nothing
86− get s = case s of Definition d -> maybeToList (get' d)
85+ get' def =
86+ case def of
87+ TypeAnnotation _ _ -> []
88+ Def pattern _ ->
89+ case Set.toList (boundVars pattern) of
90+ [var@(c:_)] -> [if isOp c then Right var else Left var]
91+ vars -> map Left vars
92+
93+ get s = case s of Definition def -> get' def
8794 Datatype _ _ tcs -> map (Left . fst) tcs
8895 ImportEvent _ _ x _ -> [ Left x ]
8996 ExportEvent _ _ _ -> []
@@ -125,10 +132,11 @@ stmtsToJS stmts = run $ do program <- mapM toJS (sortBy cmpStmt stmts)
125132 valueOf s = case s of
126133 Datatype _ _ _ -> 1
127134 ImportEvent _ _ _ _ -> 2
128− Definition (FnDef f [] _) ->
129− if derename f == "main" then 5 else 4
135+ Definition (Def f (L _ _ (Lambda _ _))) -> 3
136+ Definition (Def (PVar name) _) ->
137+ if derename name == "main" then 5 else 4
138+ Definition (Def _ _) -> 4
130139 Definition (TypeAnnotation _ _) -> 0
131− Definition _ -> 3
132140 ExportEvent _ _ _ -> 6
133141 TypeAlias _ _ _ -> 0
134142
@@ -136,8 +144,12 @@ class ToJS a where
136144 toJS :: a -> Unique String
137145
138146instance ToJS (Def t v) where
139− toJS (FnDef x [] e) = assign x `liftM` toJS' e
140− toJS (FnDef f as e) = (assign f . wrapper . func) `liftM` toJS' e
147+
148+ -- TODO: Make this handle patterns besides plain variables
149+
150+ toJS (Def (PVar x) e) = assign x `liftM` toJS' e
151+{--
152+ toJS (Def f e) = (assign f . wrapper . func) `liftM` toJS' e
141153 where
142154 func body = jsFunc (intercalate ", " as) (ret body)
143155 wrapper e | length as == 1 = e
@@ -146,6 +158,7 @@ instance ToJS (Def t v) where
146158 do body <- toJS' e
147159 let func = "F2" ++ parens (jsFunc (a1 ++ ", " ++ a2) (ret body))
148160 return (globalAssign ("$op['" ++ op ++ "']") func)
161+--}
149162 toJS (TypeAnnotation _ _) = return ""
150163
151164
@@ -155,9 +168,11 @@ instance ToJS (Declaration t v) where
155168 Definition d -> toJS d
156169 Datatype _ _ tcs -> concat `liftM` mapM (toJS . toDef) tcs
157170 where toDef (name,args) =
158− let vars = map (('a':) . show) [1..length args] in
159− Definition . FnDef name vars . none $
160− Data (derename name) (map (none . Var) vars)
171+ let vars = map (('a':) . show) [1..length args]
172+ body = Loc.none (Data (derename name) (map (Loc.none . Var) vars))
173+ func = foldr (\x e -> Loc.none (Lambda (PVar x) e)) body vars
174+ in Definition $ Def (PVar name) func
175+
161176 ImportEvent js base elm _ ->
162177 do v <- toJS' base
163178 return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal(elm).constant(" ++ v ++ ");"
@@ -188,8 +203,8 @@ makeRecord kvs = record `liftM` collect kvs
188203 where
189204 combine r (k,v) = Map.insertWith (++) k v r
190205 collect = liftM (foldl' combine Map.empty) . mapM prep
191− prep (k, as, e@(L t s _)) =
192− do v <- toJS' (foldr (\x e -> L t s $ Lambda x e) e as)
206+ prep (k, e) =
207+ do v <- toJS' e
193208 return (k,[v])
194209 fields fs =
195210 brackets ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
@@ -222,7 +237,22 @@ instance ToJS (Expr t v) where
222237 Record fs -> makeRecord fs
223238 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
224239
225− Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
240+ Lambda p e -> liftM (jsFunc (intercalate ", " args) . ret) (toJS' body)
241+ where
242+ (args, body) = foldr depattern ([], innerBody) (zip patterns [1..])
243+
244+ depattern (pattern,n) (args, body) =
245+ case pattern of
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)]))
249+
250+ (patterns, innerBody) = collect [p] e
251+
252+ collect patterns lexpr@(L a b expr) =
253+ case expr of
254+ Lambda p e -> collect (p:patterns) e
255+ _ -> (patterns, lexpr)
226256
227257 App e1 e2 -> jsApp e1 e2
228258 Let defs e -> jsLet defs e
@@ -279,9 +309,8 @@ jsLet defs e' = do ds <- jsDefs defs
279309 where
280310 jsDefs defs = mapM toJS (sortBy f defs)
281311 f a b = compare (valueOf a) (valueOf b)
282− valueOf (FnDef _ [] _) = 2
283− valueOf (FnDef _ _ _) = 1
284− valueOf (OpDef _ _ _ _) = 1
312+ valueOf (Def _ (L _ _ (Lambda _ _))) = 1
313+ valueOf (Def _ _) = 2
285314 valueOf (TypeAnnotation _ _) = 0
286315
287316caseToJS span e ps = do