@@ -16,10 +16,14 @@ import Idris.Core.TT
16import IRTS.CodegenCommon
16import IRTS.CodegenCommon
17import IRTS.JavaScript.AST
17import IRTS.JavaScript.AST
18import IRTS.JavaScript.LangTransforms
18import IRTS.JavaScript.LangTransforms
19+import IRTS.JavaScript.Name
20+import IRTS.JavaScript.PrimOp
21+import IRTS.JavaScript.Specialize
19import IRTS.Lang
22import IRTS.Lang
20import IRTS.LangOpts
23import IRTS.LangOpts
21import IRTS.System
24import IRTS.System
23import Control.Monad.Trans.State
27import Control.Monad.Trans.State
24import Data.List (nub)
28import Data.List (nub)
25import Data.Map.Strict (Map)
29import Data.Map.Strict (Map)
@@ -41,22 +45,20 @@ import Data.Generics.Uniplate.Data
41import Data.List
45import Data.List
42import GHC.Generics (Generic)
46import GHC.Generics (Generic)
44−data Partial = Partial Name Int Int deriving (Eq, Ord)
46−data CGStats = CGStats { usedWriteStr :: Bool
47− , usedReadStr :: Bool
48− , usedBigInt :: Bool
48+data CGStats = CGStats { usedBigInt :: Bool
49 , partialApplications :: Set Partial
49 , partialApplications :: Set Partial
50+ , hiddenClasses :: Set HiddenClass
52emptyStats :: CGStats
53emptyStats :: CGStats
53−emptyStats = CGStats {usedWriteStr = False, partialApplications = Set.empty, usedBigInt = False, usedReadStr = False}
54+emptyStats = CGStats { partialApplications = Set.empty
55+ , hiddenClasses = Set.empty
55data CGConf = CGConf { header :: Text
59data CGConf = CGConf { header :: Text
56 , footer :: Text
60 , footer :: Text
57− , initialization :: CGStats -> Text
61+ , jsbnPath :: String
58− , writeStrTemplate :: Text
59− , readStrTemplate :: Text
60 , extraRunTime :: String
62 , extraRunTime :: String
@@ -96,7 +98,7 @@ codegenJs conf ci =
97 path <- getIdrisJSRTSDir
99 path <- getIdrisJSRTSDir
98 jsbn <- if usedBigInt stats
100 jsbn <- if usedBigInt stats
99− then TIO.readFile $ path </> "jsbn/jsbn.js"
101+ then TIO.readFile $ path </> jsbnPath conf
100 else return ""
102 else return ""
102 runtimeCommon <- TIO.readFile $ path </> "Runtime-common.js"
104 runtimeCommon <- TIO.readFile $ path </> "Runtime-common.js"
@@ -106,30 +108,18 @@ codegenJs conf ci =
106 TIO.writeFile (outputFile ci) $ T.concat [ header conf
108 TIO.writeFile (outputFile ci) $ T.concat [ header conf
107 , "\"use strict\";\n\n"
109 , "\"use strict\";\n\n"
108 , "(function(){\n\n"
110 , "(function(){\n\n"
110− , initialization conf stats
111− , doPartials (partialApplications stats)
113 , runtimeCommon, "\n"
111 , runtimeCommon, "\n"
114 , extraRT, "\n"
112 , extraRT, "\n"
114+ , doPartials (partialApplications stats), "\n"
115+ , doHiddenClasses (hiddenClasses stats), "\n"
115 , out, "\n"
117 , out, "\n"
117− , jsName (sMN 0 "runMain"), "();\n\n"
118+ , jsName (sMN 0 "runMain"), "();\n"
118− , "\n}.call(this))"
119+ , "}.call(this))"
119 , footer conf
120 , footer conf
122−jsName :: Name -> Text
123−jsName n = T.pack $ "idris_" ++ concatMap jschar (showCG n)
124− where jschar x | isAlpha x || isDigit x = [x]
125− | otherwise = "_" ++ show (fromEnum x) ++ "_"
127−jsPartialName :: Partial -> Text
128−jsPartialName (Partial n i j) = T.concat ["partial_", T.pack $ show i, "_", T.pack $ show j, "_" , jsName n]
130−jsTailCallOptimName :: Text -> Text
131−jsTailCallOptimName x = T.concat ["tailCallOptim_cgIdris_", x]
133doPartials :: Set Partial -> Text
123doPartials :: Set Partial -> Text
134doPartials x =
124doPartials x =
135 T.intercalate "\n" (map f $ Set.toList x)
125 T.intercalate "\n" (map f $ Set.toList x)
@@ -137,41 +127,50 @@ doPartials x =
137 f p@(Partial n i j) =
127 f p@(Partial n i j) =
138 let vars1 = map (T.pack . ("x"++) . show) [1..i]
128 let vars1 = map (T.pack . ("x"++) . show) [1..i]
139 vars2 = map (T.pack . ("x"++) . show) [(i+1)..j]
129 vars2 = map (T.pack . ("x"++) . show) [(i+1)..j]
140− in jsAst2Text $
130+ in jsStmt2Text $
131+ JsFun (jsNamePartial p) vars1 $ JsReturn $
141− JsFun (jsPartialName p) vars1 $ JsReturn $ JsCurryLambda vars2 (JsApp (jsName n) (map JsVar (vars1 ++ vars2)) )
132+ jsCurryLam vars2 (jsAppN (jsName n) (map JsVar (vars1 ++ vars2)) )
134+doHiddenClasses :: Set HiddenClass -> Text
136+ T.intercalate "\n" (map f $ Set.toList x)
138+ f p@(HiddenClass n id arity) =
139+ let vars = map dataPartName $ take arity [1..]
141+ JsFun (jsNameHiddenClass p) vars $ JsSeq (JsSet (JsProp JsThis "type") (JsInt id)) $ seqJs
142+ $ map (\tv -> JsSet (JsProp JsThis tv) (JsVar tv)) vars
143doCodegen :: CGConf -> Map Name LDecl -> [LDecl] -> (Text, CGStats)
144doCodegen :: CGConf -> Map Name LDecl -> [LDecl] -> (Text, CGStats)
144doCodegen conf defs decls =
145doCodegen conf defs decls =
145 let xs = map (doCodegenDecl conf defs) decls
146 let xs = map (doCodegenDecl conf defs) decls
146− groupCGStats x y = CGStats {usedWriteStr = usedWriteStr x || usedWriteStr y
147+ groupCGStats x y = CGStats { partialApplications = partialApplications x `Set.union` partialApplications y
147− , partialApplications = partialApplications x `Set.union` partialApplications y
148+ , hiddenClasses = hiddenClasses x `Set.union` hiddenClasses y
148 , usedBigInt = usedBigInt x || usedBigInt y
149 , usedBigInt = usedBigInt x || usedBigInt y
149− , usedReadStr = usedReadStr x || usedReadStr y
151 in (T.intercalate "\n" $ map fst xs, foldl' groupCGStats emptyStats (map snd xs) )
151 in (T.intercalate "\n" $ map fst xs, foldl' groupCGStats emptyStats (map snd xs) )
153doCodegenDecl :: CGConf -> Map Name LDecl -> LDecl -> (Text, CGStats)
153doCodegenDecl :: CGConf -> Map Name LDecl -> LDecl -> (Text, CGStats)
154doCodegenDecl conf defs (LFun _ n args def) =
154doCodegenDecl conf defs (LFun _ n args def) =
155 let (ast, stats) = cgFun conf defs n args def
155 let (ast, stats) = cgFun conf defs n args def
156− in (jsAst2Text $ ast, stats)
156+ in (T.concat [jsStmt2Text (JsComment $ T.pack $ show n), "\n", jsStmt2Text ast], stats)
157−doCodegenDecl conf defs (LConstructor n i sz) =
157+doCodegenDecl conf defs (LConstructor n i sz) = ("", emptyStats)
160−seqJs :: [JsAST] -> JsAST
159+seqJs :: [JsStmt] -> JsStmt
161seqJs [] = JsEmpty
160seqJs [] = JsEmpty
162seqJs (x:xs) = JsSeq x (seqJs xs)
161seqJs (x:xs) = JsSeq x (seqJs xs)
165data CGBodyState = CGBodyState { defs :: Map Name LDecl
164data CGBodyState = CGBodyState { defs :: Map Name LDecl
166 , lastIntName :: Int
165 , lastIntName :: Int
166+ , reWrittenNames :: Map.Map Name JsExpr
167 , currentFnNameAndArgs :: (Text, [Text])
167 , currentFnNameAndArgs :: (Text, [Text])
168 , usedArgsTailCallOptim :: Set (Text, Text)
168 , usedArgsTailCallOptim :: Set (Text, Text)
169 , isTailRec :: Bool
169 , isTailRec :: Bool
170 , conf :: CGConf
170 , conf :: CGConf
173 , usedITBig :: Bool
171 , usedITBig :: Bool
174 , partialApps :: Set Partial
172 , partialApps :: Set Partial
173+ , hiddenCls :: Set HiddenClass
177getNewCGName :: State CGBodyState Text
176getNewCGName :: State CGBodyState Text
@@ -180,12 +179,16 @@ getNewCGName =
180 st <- get
179 st <- get
181 let v = lastIntName st + 1
180 let v = lastIntName st + 1
182 put $ st {lastIntName = v}
181 put $ st {lastIntName = v}
183− return $ T.pack $ "cgIdris_" ++ show v
182+ return $ jsNameGenerated v
185addPartial :: Partial -> State CGBodyState ()
184addPartial :: Partial -> State CGBodyState ()
186addPartial p =
185addPartial p =
187 modify (\s -> s {partialApps = Set.insert p (partialApps s) })
186 modify (\s -> s {partialApps = Set.insert p (partialApps s) })
188+addHiddenClass :: HiddenClass -> State CGBodyState ()
190+ modify (\s -> s {hiddenCls = Set.insert p (hiddenCls s) })
189addUsedArgsTailCallOptim :: Set (Text, Text) -> State CGBodyState ()
192addUsedArgsTailCallOptim :: Set (Text, Text) -> State CGBodyState ()
190addUsedArgsTailCallOptim p =
193addUsedArgsTailCallOptim p =
191 modify (\s -> s {usedArgsTailCallOptim = Set.union p (usedArgsTailCallOptim s) })
194 modify (\s -> s {usedArgsTailCallOptim = Set.union p (usedArgsTailCallOptim s) })
@@ -194,12 +197,12 @@ getNewCGNames :: Int -> State CGBodyState [Text]
194getNewCGNames n =
197getNewCGNames n =
195 mapM (\_ -> getNewCGName) [1..n]
198 mapM (\_ -> getNewCGName) [1..n]
197−getConsId :: Name -> State CGBodyState Int
200+getConsId :: Name -> State CGBodyState (Int, Int)
198getConsId n =
201getConsId n =
200 st <- get
203 st <- get
201 case Map.lookup n (defs st) of
204 case Map.lookup n (defs st) of
202− Just (LConstructor _ conId _) -> pure conId
205+ Just (LConstructor _ conId arity) -> pure (conId, arity)
203 _ -> error $ "Internal JS Backend error " ++ showCG n ++ " is not a constructor."
206 _ -> error $ "Internal JS Backend error " ++ showCG n ++ " is not a constructor."
205getArgList :: Name -> State CGBodyState (Maybe [Name])
208getArgList :: Name -> State CGBodyState (Maybe [Name])
@@ -216,49 +219,33 @@ data BodyResTarget = ReturnBT
216 | DecConstBT Text
219 | DecConstBT Text
217 | GetExpBT
220 | GetExpBT
219−replaceVarsByProj :: JsAST -> Map Text Int -> JsAST -> JsAST
220−replaceVarsByProj n d z =
225− case Map.lookup x d of
226− Nothing -> (JsVar x)
227− Just i -> JsArrayProj (JsInt i) n
230−cgFun :: CGConf -> Map Name LDecl -> Name -> [Name] -> LExp -> (JsAST, CGStats)
222+cgFun :: CGConf -> Map Name LDecl -> Name -> [Name] -> LExp -> (JsStmt, CGStats)
231−cgFun cnf dfs n args def =
223+cgFun cnf dfs n args def = do
233− fnName = jsName n
224+ let fnName = jsName n
234− argNames = map jsName args
225+ let argNames = map jsName args
235− ((decs, res),st) = runState
226+ let ((decs, res),st) = runState
236 (cgBody ReturnBT def)
227 (cgBody ReturnBT def)
237− (CGBodyState { defs=dfs
228+ (CGBodyState { defs = dfs
238 , lastIntName = 0
229 , lastIntName = 0
230+ , reWrittenNames = Map.empty
239 , currentFnNameAndArgs = (fnName, argNames)
231 , currentFnNameAndArgs = (fnName, argNames)
240 , usedArgsTailCallOptim = Set.empty
232 , usedArgsTailCallOptim = Set.empty
241 , isTailRec = False
233 , isTailRec = False
242 , conf = cnf
234 , conf = cnf
245 , usedITBig = False
235 , usedITBig = False
246 , partialApps = Set.empty
236 , partialApps = Set.empty
237+ , hiddenCls = Set.empty
249− body = if isTailRec st then
251− (declareUsedOptimArgs $ usedArgsTailCallOptim st)
240+ let body = if isTailRec st then JsSeq (declareUsedOptimArgs $ usedArgsTailCallOptim st) (JsForever ((seqJs decs) `JsSeq` res)) else (seqJs decs) `JsSeq` res
252− (JsWhileTrue ((seqJs decs) `JsSeq` res))
253− else (seqJs decs) `JsSeq` res
254− in (JsFun fnName argNames $ body, CGStats { usedWriteStr = usedWrite st
241+ let fn = JsFun fnName argNames body
255− , partialApplications = partialApps st
242+ let state' = CGStats { partialApplications = partialApps st
243+ , hiddenClasses = hiddenCls st
256− , usedBigInt = usedITBig st
244+ , usedBigInt = usedITBig st
257− , usedReadStr = usedRead st
261−getSwitchJs :: JsAST -> [LAlt] -> JsAST
248+getSwitchJs :: JsExpr -> [LAlt] -> JsExpr
262getSwitchJs x alts =
249getSwitchJs x alts =
263 if any conCase alts then JsArrayProj (JsInt 0) x
250 if any conCase alts then JsArrayProj (JsInt 0) x
264 else if any constBigIntCase alts then JsForeign "%0.toString()" [x]
251 else if any constBigIntCase alts then JsForeign "%0.toString()" [x]
@@ -268,48 +255,92 @@ getSwitchJs x alts =
268 constBigIntCase (LConstCase (BI _) _) = True
255 constBigIntCase (LConstCase (BI _) _) = True
269 constBigIntCase _ = False
256 constBigIntCase _ = False
271−addRT :: BodyResTarget -> JsAST -> JsAST
258+addRT :: BodyResTarget -> JsExpr -> JsStmt
272addRT ReturnBT x = JsReturn x
259addRT ReturnBT x = JsReturn x
273−addRT (DecBT n) x = JsLet n x
260+addRT (DecBT n) x = JsDecLet n x
261+addRT (DecConstBT n) x = JsDecConst n x
274−addRT (SetBT n) x = JsSetVar n x
262+addRT (SetBT n) x = JsSet (JsVar n) x
275−addRT (DecConstBT n) x = JsConst n x
276−addRT GetExpBT x = x
263+addRT GetExpBT x = JsExprStmt x
278−declareUsedOptimArgs :: Set (Text, Text) -> JsAST
265+declareUsedOptimArgs :: Set (Text, Text) -> JsStmt
279−declareUsedOptimArgs x = seqJs $ map (\(x,y) -> JsLet x (JsVar y) ) (Set.toList x)
266+declareUsedOptimArgs x = seqJs $ map (\(x,y) -> JsDecLet x (JsVar y) ) (Set.toList x)
281−tailCallOptimRefreshArgs :: [(Text, JsAST)] -> Set Text -> ((JsAST, JsAST), Set (Text, Text))
268+tailCallOptimRefreshArgs :: [(Text, JsExpr)] -> Set Text -> ((JsStmt, JsStmt), Set (Text, Text))
282tailCallOptimRefreshArgs [] s = ((JsEmpty, JsEmpty), Set.empty)
269tailCallOptimRefreshArgs [] s = ((JsEmpty, JsEmpty), Set.empty)
283tailCallOptimRefreshArgs ((n,x):r) s =
270tailCallOptimRefreshArgs ((n,x):r) s =
284 let ((y1,y2), y3) = tailCallOptimRefreshArgs r (Set.insert n s) --
271 let ((y1,y2), y3) = tailCallOptimRefreshArgs r (Set.insert n s) --
285 in if Set.null $ (Set.fromList [ z | z <- universeBi x ]) `Set.intersection` s then
272 in if Set.null $ (Set.fromList [ z | z <- universeBi x ]) `Set.intersection` s then
286− ((y1, JsSetVar n x `JsSeq` y2), y3)
273+ ((y1, jsSetVar n x `JsSeq` y2), y3)
288 let n' = jsTailCallOptimName n
275 let n' = jsTailCallOptimName n
289− in ((JsSetVar n' x `JsSeq` y1, JsSetVar n (JsVar n') `JsSeq` y2), Set.insert (n',n) y3)
276+ in ((jsSetVar n' x `JsSeq` y1, jsSetVar n (JsVar n') `JsSeq` y2), Set.insert (n',n) y3)
291−
278+cgName :: Name -> State CGBodyState JsExpr
281+ case Map.lookup b (reWrittenNames st) of
283+ _ -> pure $ JsVar $ jsName b
292−cgBody :: BodyResTarget -> LExp -> State CGBodyState ([JsAST], JsAST)
285+cgBody :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
293−cgBody rt (LV (Glob n)) =
286+cgBody rt expr =
288+ (LCase _ (LOp oper [x, y]) [LConstCase (I 0) (LCon _ _ ff []), LDefaultCase (LCon _ _ tt [])])
289+ | (ff == qualifyN "Prelude.Bool" "False" &&
290+ tt == qualifyN "Prelude.Bool" "True") ->
291+ case (Map.lookup oper primDB) of
292+ Just (needBI, pti, c) | pti == PTBool -> do
293+ z <- mapM (cgBody GetExpBT) [x, y]
294+ when needBI setUsedITBig
295+ let res = jsPrimCoerce pti PTBool $ c $ map (jsStmt2Expr . snd) z
296+ pure $ (concat $ map fst z, addRT rt res)
297+ _ -> cgBody' rt expr
298+ (LCase _ e [LConCase _ n _ (LCon _ _ tt []), LDefaultCase (LCon _ _ ff [])])
299+ | (ff == qualifyN "Prelude.Bool" "False" &&
300+ tt == qualifyN "Prelude.Bool" "True") -> do
301+ (d, v) <- cgBody GetExpBT e
302+ test <- formConTest n (jsStmt2Expr v)
303+ pure $ (d, addRT rt $ JsUniOp (T.pack "!") $ JsUniOp (T.pack "!") test)
304+ (LCase _ e [LConCase _ n _ (LCon _ _ tt []), LConCase _ _ _ (LCon _ _ ff [])])
305+ | (ff == qualifyN "Prelude.Bool" "False" &&
306+ tt == qualifyN "Prelude.Bool" "True") -> do
307+ (d, v) <- cgBody GetExpBT e
308+ test <- formConTest n (jsStmt2Expr v)
309+ pure $ (d, addRT rt $ JsUniOp (T.pack "!") $ JsUniOp (T.pack "!") test)
310+ (LCase _ e [LConCase _ n _ (LCon _ _ ff []), LDefaultCase (LCon _ _ tt [])])
311+ | (ff == qualifyN "Prelude.Bool" "False" &&
312+ tt == qualifyN "Prelude.Bool" "True") -> do
313+ (d, v) <- cgBody GetExpBT e
314+ test <- formConTest n (jsStmt2Expr v)
315+ pure $ (d, addRT rt $ JsUniOp (T.pack "!") test)
316+ (LCase _ e [LConCase _ n _ (LCon _ _ ff []), LConCase _ _ _ (LCon _ _ tt [])])
317+ | (ff == qualifyN "Prelude.Bool" "False" &&
318+ tt == qualifyN "Prelude.Bool" "True") -> do
319+ (d, v) <- cgBody GetExpBT e
320+ test <- formConTest n (jsStmt2Expr v)
321+ pure $ (d, addRT rt $ JsUniOp (T.pack "!") test)
322+ (LCase f e [LConCase nf ff [] alt, LConCase nt tt [] conseq])
323+ | (ff == qualifyN "Prelude.Bool" "False" &&
324+ tt == qualifyN "Prelude.Bool" "True") ->
325+ cgBody' rt $ LCase f e [LConCase nt tt [] conseq, LConCase nf ff [] alt]
326+ expr -> cgBody' rt expr
328+cgBody' :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
329+cgBody' rt (LV (Glob n)) =
295 argsFn <- getArgList n
331 argsFn <- getArgList n
296 case argsFn of
332 case argsFn of
297− Just [] ->
333+ Just a -> cgBody' rt (LApp False (LV (Glob n)) [])
298− pure $ ([], addRT rt $ JsApp (jsName n) [])
301− let part = Partial n 0 (length a)
303− pure ([], addRT rt $ JsApp (jsPartialName part) [])
304− Nothing ->
334+ Nothing -> do
305− pure $ ([], addRT rt $ JsVar $ jsName n)
336+ pure $ ([], addRT rt n')
306−cgBody rt (LApp tailcall (LV (Glob fn)) args) =
337+cgBody' rt (LApp tailcall (LV (Glob fn)) args) =
308 let fname = jsName fn
339 let fname = jsName fn
309 st <- get
340 st <- get
310 let (currFn, argN) = currentFnNameAndArgs st
341 let (currFn, argN) = currentFnNameAndArgs st
311 z <- mapM (cgBody GetExpBT) args
342 z <- mapM (cgBody GetExpBT) args
312− let argVals = map snd z
343+ let argVals = map (jsStmt2Expr . snd) z
313 let preDecs = concat $ map fst z
344 let preDecs = concat $ map fst z
314 case (fname == currFn && (length args) == (length argN), rt) of
345 case (fname == currFn && (length args) == (length argN), rt) of
315 (True, ReturnBT) ->
346 (True, ReturnBT) ->
@@ -322,82 +353,88 @@ cgBody rt (LApp tailcall (LV (Glob fn)) args) =
323 argsFn <- getArgList fn
354 argsFn <- getArgList fn
324 case argsFn of
355 case argsFn of
325− Nothing ->
356+ Nothing -> do
326− pure (preDecs, addRT rt $ JsCurryApp (JsVar fname) argVals )
358+ pure (preDecs, addRT rt $ jsCurryApp fn' argVals )
327 Just agFn ->
359 Just agFn ->
329 let lenAgFn = length agFn
361 let lenAgFn = length agFn
330 let lenArgs = length args
362 let lenArgs = length args
331 case compare lenAgFn lenArgs of
363 case compare lenAgFn lenArgs of
333− pure (preDecs, addRT rt $ JsApp fname argVals)
365+ pure (preDecs, addRT rt $ jsAppN fname argVals)
335− pure (preDecs, addRT rt $ JsCurryApp (JsApp fname (take lenAgFn argVals )) (drop lenAgFn argVals) )
367+ pure (preDecs, addRT rt $ jsCurryApp (jsAppN fname (take lenAgFn argVals)) (drop lenAgFn argVals) )
338 let part = Partial fn lenArgs lenAgFn
370 let part = Partial fn lenArgs lenAgFn
339 addPartial part
371 addPartial part
340− pure (preDecs, addRT rt $ JsApp (jsPartialName part) argVals )
372+ pure (preDecs, addRT rt $ jsAppN (jsNamePartial part) argVals )
342−cgBody rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV (Glob n)) args)
374+cgBody' rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV (Glob n)) args)
343−cgBody rt (LLazyApp n args) =
375+cgBody' rt (LLazyApp n args) =
345 (d,v) <- cgBody ReturnBT (LApp False (LV (Glob n)) args)
377 (d,v) <- cgBody ReturnBT (LApp False (LV (Glob n)) args)
346− pure ([], addRT rt $ JsLazy $ JsSeq (seqJs d) v)
378+ pure ([], addRT rt $ jsLazy $ jsStmt2Expr $ JsSeq (seqJs d) v)
347−cgBody rt (LForce e) =
379+cgBody' rt (LForce e) =
349 (d,v) <- cgBody GetExpBT e
381 (d,v) <- cgBody GetExpBT e
350− pure (d, addRT rt $ JsForce v)
382+ pure (d, addRT rt $ JsForce $ jsStmt2Expr v)
351−cgBody rt (LLet n v sc) =
383+cgBody' rt (LLet n v sc) =
353 (d1, v1) <- cgBody (DecConstBT $ jsName n) v
385 (d1, v1) <- cgBody (DecConstBT $ jsName n) v
354 (d2, v2) <- cgBody rt sc
386 (d2, v2) <- cgBody rt sc
355− pure $ ((d1 ++ v1 : d2), v2 )
387+ pure $ ((d1 ++ v1 : d2), v2)
356−cgBody rt (LProj e i) =
388+cgBody' rt (LProj e i) =
358 (d, v) <- cgBody GetExpBT e
390 (d, v) <- cgBody GetExpBT e
359− pure $ (d, addRT rt $ JsArrayProj (JsInt $ i+1) $ v)
391+ pure $ (d, addRT rt $ JsArrayProj (JsInt $ i+1) $ jsStmt2Expr v)
360−cgBody rt (LCon _ conId n args) =
392+cgBody' rt (LCon _ conId n args) =
362 z <- mapM (cgBody GetExpBT) args
394 z <- mapM (cgBody GetExpBT) args
395+ con <- formCon n (map (jsStmt2Expr . snd) z)
363− pure $ (concat $ map fst z, addRT rt $ JsArray (JsInt conId : map snd z))
396+ pure $ (concat $ map fst z, addRT rt con)
364−cgBody rt (LCase _ e alts) =
397+cgBody' rt (LCase _ e alts) = do
366− (d,v) <- cgBody GetExpBT e
398+ (d, v) <- cgBody GetExpBT e
367− resName <- getNewCGName
399+ resName <- getNewCGName
368− swName <- getNewCGName
400+ (decSw, entry) <-
369− (altsJs,def) <- cgAlts rt resName (JsVar swName) alts
401+ case (all altHasNoProj alts && length alts <= 2, v) of
370− let decSw = JsConst swName v
402+ (True, _) -> pure (JsEmpty, jsStmt2Expr v)
371− let sw = JsSwitchCase (getSwitchJs (JsVar swName) alts) altsJs def
403+ (False, JsExprStmt (JsVar n)) -> pure (JsEmpty, jsStmt2Expr v)
405+ swName <- getNewCGName
406+ pure (JsDecConst swName $ jsStmt2Expr v, JsVar swName)
407+ sw' <- cgIfTree rt resName entry alts
411+ Nothing -> JsExprStmt JsNull
372− case rt of
412+ case rt of
374− pure (d ++ [decSw], sw)
413+ ReturnBT -> pure (d ++ [decSw], sw)
375− (DecBT nvar) ->
414+ (DecBT nvar) -> pure (d ++ [decSw, JsDecLet nvar JsNull], sw)
376− pure (d ++ [decSw, JsLet nvar JsNull], sw)
415+ (DecConstBT nvar) -> pure (d ++ [decSw, JsDecLet nvar JsNull], sw)
378− pure (d ++ [decSw], sw)
416+ (SetBT nvar) -> pure (d ++ [decSw], sw)
379− GetExpBT ->
417+ GetExpBT ->
380− pure (d ++ [decSw, JsLet resName JsNull, sw], JsVar resName)
419+ (d ++ [decSw, JsDecLet resName JsNull, sw], JsExprStmt $ JsVar resName)
381− (DecConstBT nvar) ->
382− pure (d ++ [decSw, JsLet nvar JsNull], sw)
383−cgBody rt (LConst c) =
420+cgBody' rt (LConst c) =
385 cst <- cgConst c
422 cst <- cgConst c
386 pure ([], (addRT rt) $ cst)
423 pure ([], (addRT rt) $ cst)
387−cgBody rt (LOp op args) =
424+cgBody' rt (LOp op args) =
389 z <- mapM (cgBody GetExpBT) args
426 z <- mapM (cgBody GetExpBT) args
390− res <- cgOp op (map snd z)
427+ res <- cgOp op (map (jsStmt2Expr . snd) z)
391 pure $ (concat $ map fst z, addRT rt $ res)
428 pure $ (concat $ map fst z, addRT rt $ res)
392−cgBody rt LNothing = pure ([], addRT rt JsNull)
429+cgBody' rt LNothing = pure ([], addRT rt JsNull)
393−cgBody rt (LError x) = pure ([], JsError $ JsStr x)
430+cgBody' rt (LError x) = pure ([], JsError $ JsStr x)
394−cgBody rt x@(LForeign dres (FStr code) args ) =
431+cgBody' rt x@(LForeign dres (FStr code) args ) =
396 z <- mapM (cgBody GetExpBT) (map snd args)
433 z <- mapM (cgBody GetExpBT) (map snd args)
397− jsArgs <- sequence $ map cgForeignArg (zip (map fst args) (map snd z))
434+ jsArgs <- sequence $ map cgForeignArg (zip (map fst args) (map (jsStmt2Expr . snd) z))
398 jsDres <- cgForeignRes dres $ JsForeign (T.pack code) jsArgs
435 jsDres <- cgForeignRes dres $ JsForeign (T.pack code) jsArgs
399 pure $ (concat $ map fst z, addRT rt $ jsDres)
436 pure $ (concat $ map fst z, addRT rt $ jsDres)
400−cgBody _ x = error $ "Instruction " ++ show x ++ " not compilable yet"
437+cgBody' _ x = error $ "Instruction " ++ show x ++ " not compilable yet"
402altsRT :: Text -> BodyResTarget -> BodyResTarget
439altsRT :: Text -> BodyResTarget -> BodyResTarget
403altsRT rn ReturnBT = ReturnBT
440altsRT rn ReturnBT = ReturnBT
@@ -406,36 +443,88 @@ altsRT rn (SetBT n) = SetBT n
406altsRT rn (DecConstBT n) = SetBT n
443altsRT rn (DecConstBT n) = SetBT n
407altsRT rn GetExpBT = SetBT rn
444altsRT rn GetExpBT = SetBT rn
409−cgAlts :: BodyResTarget -> Text -> JsAST -> [LAlt] -> State CGBodyState ([(JsAST, JsAST)], Maybe JsAST)
446+altHasNoProj :: LAlt -> Bool
447+altHasNoProj (LConCase _ _ args _) = args == []
448+altHasNoProj _ = True
450+formCon :: Name -> [JsExpr] -> State CGBodyState JsExpr
452+ case specialCased n of
453+ Just (ctor, test, match) -> pure $ ctor args
455+ (conId, arity) <- getConsId n
458+ let hc = HiddenClass n conId arity
460+ pure $ JsNew (JsVar $ jsNameHiddenClass hc) args
461+ else pure $ JsInt conId
463+formConTest :: Name -> JsExpr -> State CGBodyState JsExpr
465+ case specialCased n of
466+ Just (ctor, test, match) -> pure $ test x
468+ (conId, arity) <- getConsId n
470+ then pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
471+ else pure $ JsBinOp "===" x (JsInt conId)
473+formProj :: Name -> JsExpr -> Int -> JsExpr
475+ case specialCased n of
476+ Just (ctor, test, proj) -> proj v i
477+ Nothing -> JsProp v (dataPartName i)
479+smartif :: JsExpr -> JsStmt -> Maybe JsStmt -> JsStmt
480+smartif cond conseq (Just alt) = JsIf cond conseq (Just alt)
481+smartif cond conseq Nothing = conseq
483+formConstTest :: JsExpr -> Const -> State CGBodyState JsExpr
484+formConstTest scrvar t = case t of
487+ cgOp' PTBool (LEq (ATInt ITBig)) [scrvar, t']
490+ pure $ JsBinOp "===" scrvar t'
492+cgIfTree :: BodyResTarget
496+ -> State CGBodyState (Maybe JsStmt)
497+cgIfTree _ _ _ [] = pure Nothing
410−cgAlts rt resName scrvar ((LConstCase t exp):r) =
498+cgIfTree rt resName scrvar ((LConstCase t exp):r) = do
412− (d, v) <- cgBody (altsRT resName rt) exp
499+ (d, v) <- cgBody (altsRT resName rt) exp
413− (ar, def) <- cgAlts rt resName scrvar r
500+ alternatives <- cgIfTree rt resName scrvar r
414− cst <- case t of
501+ test <- formConstTest scrvar t
415− BI _ ->
502+ pure $ Just $
419− pure $ JsForeign "%0.toString()" [c']
421− pure ((cst, JsSeq (seqJs d) v) : ar, def)
503+ smartif test (JsSeq (seqJs d) v) alternatives
422−cgAlts rt resName scrvar ((LDefaultCase exp):r) =
504+cgIfTree rt resName scrvar ((LDefaultCase exp):r) = do
424− (d, v) <- cgBody (altsRT resName rt) exp
505+ (d, v) <- cgBody (altsRT resName rt) exp
425− pure ([], Just $ JsSeq (seqJs d) v)
506+ pure $ Just $ JsSeq (seqJs d) v
426−cgAlts rt resName scrvar ((LConCase _ n args exp):r) =
507+cgIfTree rt resName scrvar ((LConCase _ n args exp):r) = do
427− do
508+ alternatives <- cgIfTree rt resName scrvar r
428− (d, v) <- cgBody (altsRT resName rt) exp
509+ test <- formConTest n scrvar
429− (ar, def) <- cgAlts rt resName scrvar r
510+ st <- get
430− conId <- getConsId n
511+ let rwn = reWrittenNames st
431− let replace = replaceVarsByProj scrvar (Map.fromList $ zip (map jsName args) [1..])
512+ put $
432− let branchBody = JsSeq (seqJs $ map replace d) (replace v)
513+ st
433− pure ((JsInt conId, branchBody) : ar, def)
514+ { reWrittenNames =
434−cgAlts _ _ _ [] =
515+ foldl
435− pure ([],Nothing)
516+ (\m (n, j) -> Map.insert n (formProj n scrvar j) m)
437−
518+ (zip args [1 ..])
520+ (d, v) <- cgBody (altsRT resName rt) exp
522+ put $ st1 {reWrittenNames = rwn}
523+ let branchBody = JsSeq (seqJs d) v
524+ pure $ Just $ smartif test branchBody alternatives
438−cgForeignArg :: (FDesc, JsAST) -> State CGBodyState JsAST
527+cgForeignArg :: (FDesc, JsExpr) -> State CGBodyState JsExpr
439cgForeignArg (FApp (UN "JS_IntT") _, v) = pure v
528cgForeignArg (FApp (UN "JS_IntT") _, v) = pure v
440cgForeignArg (FCon (UN "JS_Str"), v) = pure v
529cgForeignArg (FCon (UN "JS_Str"), v) = pure v
441cgForeignArg (FCon (UN "JS_Ptr"), v) = pure v
530cgForeignArg (FCon (UN "JS_Ptr"), v) = pure v
@@ -446,14 +535,14 @@ cgForeignArg (FApp (UN "JS_FnT") [_,FApp (UN "JS_Fn") [_,_, a, FApp (UN "JS_FnBa
446cgForeignArg (FApp (UN "JS_FnT") [_,FApp (UN "JS_Fn") [_,_, a, FApp (UN "JS_FnIO") [_,_, b]]], f) =
535cgForeignArg (FApp (UN "JS_FnT") [_,FApp (UN "JS_Fn") [_,_, a, FApp (UN "JS_FnIO") [_,_, b]]], f) =
448 jsx <- cgForeignArg (a, JsVar "x")
537 jsx <- cgForeignArg (a, JsVar "x")
449− jsres <- cgForeignRes b $ JsCurryApp (JsCurryApp f [jsx]) [JsNull]
538+ jsres <- cgForeignRes b $ jsCurryApp (jsCurryApp f [jsx]) [JsNull]
450 pure $ JsLambda ["x"] $ JsReturn jsres
539 pure $ JsLambda ["x"] $ JsReturn jsres
451cgForeignArg (desc, _) =
540cgForeignArg (desc, _) =
453 st <- get
542 st <- get
454 error $ "Foreign arg type " ++ show desc ++ " not supported. While generating function " ++ (show $ fst $ currentFnNameAndArgs st)
543 error $ "Foreign arg type " ++ show desc ++ " not supported. While generating function " ++ (show $ fst $ currentFnNameAndArgs st)
456−cgForeignRes :: FDesc -> JsAST -> State CGBodyState JsAST
545+cgForeignRes :: FDesc -> JsExpr -> State CGBodyState JsExpr
457cgForeignRes (FApp (UN "JS_IntT") _) x = pure x
546cgForeignRes (FApp (UN "JS_IntT") _) x = pure x
458cgForeignRes (FCon (UN "JS_Unit")) x = pure x
547cgForeignRes (FCon (UN "JS_Unit")) x = pure x
459cgForeignRes (FCon (UN "JS_Str")) x = pure x
548cgForeignRes (FCon (UN "JS_Str")) x = pure x
@@ -468,359 +557,33 @@ setUsedITBig :: State CGBodyState ()
468setUsedITBig = modify (\s -> s {usedITBig = True})
557setUsedITBig = modify (\s -> s {usedITBig = True})
471−cgConst :: Const -> State CGBodyState JsAST
560+cgConst :: Const -> State CGBodyState JsExpr
472cgConst (I i) = pure $ JsInt i
561cgConst (I i) = pure $ JsInt i
473cgConst (BI i) =
562cgConst (BI i) =
475 setUsedITBig
564 setUsedITBig
476− pure $ JsForeign "new jsbn.BigInteger(%0)" [JsStr $ show i]
565+ pure $ JsForeign "new $JSRTS.jsbn.BigInteger(%0)" [JsStr $ show i]
477cgConst (Ch c) = pure $ JsStr [c]
566cgConst (Ch c) = pure $ JsStr [c]
478cgConst (Str s) = pure $ JsStr s
567cgConst (Str s) = pure $ JsStr s
479−cgConst (Fl f) = pure $ JsNum f
568+cgConst (Fl f) = pure $ JsDouble f
480cgConst (B8 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFF") []
569cgConst (B8 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFF") []
481cgConst (B16 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFFFF") []
570cgConst (B16 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFFFF") []
482cgConst (B32 x) = pure $ JsForeign (T.pack $ show x ++ "|0" ) []
571cgConst (B32 x) = pure $ JsForeign (T.pack $ show x ++ "|0" ) []
483cgConst (B64 x) =
572cgConst (B64 x) =
485 setUsedITBig
574 setUsedITBig
486− pure $ JsForeign "new jsbn.BigInteger(%0).and(new jsbn.BigInteger(%1))" [JsStr $ show x, JsStr $ show 0xFFFFFFFFFFFFFFFF]
575+ pure $ JsForeign "new $JSRTS.jsbn.BigInteger(%0).and(new $JSRTS.jsbn.BigInteger(%1))" [JsStr $ show x, JsStr $ show 0xFFFFFFFFFFFFFFFF]
487cgConst x | isTypeConst x = pure $ JsInt 0
576cgConst x | isTypeConst x = pure $ JsInt 0
488cgConst x = error $ "Constant " ++ show x ++ " not compilable yet"
577cgConst x = error $ "Constant " ++ show x ++ " not compilable yet"
490−jsB2I :: JsAST -> JsAST
579+cgOp :: PrimFn -> [JsExpr] -> State CGBodyState JsExpr
491−jsB2I x = JsForeign "%0 ? 1|0 : 0|0" [x]
580+cgOp = cgOp' PTAny
493−cgOp :: PrimFn -> [JsAST] -> State CGBodyState JsAST
582+cgOp' :: JsPrimTy -> PrimFn -> [JsExpr] -> State CGBodyState JsExpr
494−cgOp (LPlus ATFloat) [l, r] = pure $ JsBinOp "+" l r
583+cgOp' pt (LExternal name) _ | name == sUN "prim__null" = pure JsNull
495−cgOp (LPlus (ATInt ITChar)) [l, r] = pure $ JsForeign "String.fromCharCode(%0.charCodeAt(0) + %1.charCodeAt(0))" [l,r]
584+cgOp' pt (LExternal name) [l,r] | name == sUN "prim__eqPtr" = pure $ JsBinOp "==" l r
496−cgOp (LPlus (ATInt ITNative)) [l, r] = pure $ JsForeign "%0+%1|0" [l,r]
585+cgOp' pt op exps = case Map.lookup op primDB of
497−cgOp (LPlus (ATInt (ITFixed IT8))) [l, r] = pure $ JsForeign "%0 + %1 & 0xFF" [l,r]
586+ Just (useBigInt, pti, combinator) -> do
498−cgOp (LPlus (ATInt (ITFixed IT16))) [l, r] = pure $ JsForeign "%0 + %1 & 0xFFFF" [l,r]
587+ when useBigInt setUsedITBig
499−cgOp (LPlus (ATInt (ITFixed IT32))) [l, r] = pure $ JsForeign "%0+%1|0" [l,r]
588+ pure $ jsPrimCoerce pti pt $ combinator exps
500−cgOp (LPlus (ATInt ITBig)) [l, r] =
589+ Nothing -> error ("Operator " ++ show (op, exps) ++ " not implemented")
503− pure $ JsMethod l "add" [r]
504−cgOp (LPlus (ATInt (ITFixed IT64))) [l, r] =
507− pure $ JsForeign "%0.add(%1).and(new jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
508−cgOp (LMinus ATFloat) [l, r] = pure $ JsBinOp "-" l r
509−cgOp (LMinus (ATInt ITChar)) [l, r] = pure $ JsForeign "String.fromCharCode(%0.charCodeAt(0) - %1.charCodeAt(0))" [l,r]
510−cgOp (LMinus (ATInt ITNative)) [l, r] = pure $ JsForeign "%0-%1|0" [l,r]
511−cgOp (LMinus (ATInt (ITFixed IT8))) [l, r] = pure $ JsForeign "%0 - %1 & 0xFF" [l,r]
512−cgOp (LMinus (ATInt (ITFixed IT16))) [l, r] = pure $ JsForeign "%0 - %1 & 0xFFFF" [l,r]
513−cgOp (LMinus (ATInt (ITFixed IT32))) [l, r] = pure $ JsForeign "%0-%1|0" [l,r]
514−cgOp (LMinus (ATInt ITBig)) [l, r] =
517− pure $ JsMethod l "subtract" [r]
518−cgOp (LMinus (ATInt (ITFixed IT64))) [l, r] =
521− pure $ JsForeign "%0.subtract(%1).and(new jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
522−cgOp (LTimes ATFloat) [l, r] = pure $ JsBinOp "*" l r
523−cgOp (LTimes (ATInt ITChar)) [l, r] = pure $ JsForeign "String.fromCharCode(%0.charCodeAt(0) * %1.charCodeAt(0))" [l,r]
524−cgOp (LTimes (ATInt ITNative)) [l, r] = pure $ JsForeign "%0*%1|0" [l,r]
525−cgOp (LTimes (ATInt (ITFixed IT8))) [l, r] = pure $ JsForeign "%0 * %1 & 0xFF" [l,r]
526−cgOp (LTimes (ATInt (ITFixed IT16))) [l, r] = pure $ JsForeign "%0 * %1 & 0xFFFF" [l,r]
527−cgOp (LTimes (ATInt (ITFixed IT32))) [l, r] = pure $ JsForeign "%0*%1|0" [l,r]
528−cgOp (LTimes (ATInt ITBig)) [l, r] =
531− pure $ JsMethod l "multiply" [r]
532−cgOp (LTimes (ATInt (ITFixed IT64))) [l, r] =
535− pure $ JsForeign "%0.multiply(%1).and(new jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
536−cgOp (LUDiv (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 / %1" [l,r]
537−cgOp (LUDiv (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 / %1" [l,r]
538−cgOp (LUDiv (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) / (%1>>>0) |0" [l,r]
539−cgOp (LUDiv (ITFixed IT64)) [l, r] =
542− pure $ JsForeign "%0.divide(%1)" [l,r]
543−cgOp (LSDiv ATFloat) [l,r] = pure $ JsBinOp "/" l r
544−cgOp (LSDiv (ATInt (ITFixed IT8))) [l, r] = pure $ JsForeign "%0 / %1" [l,r]
545−cgOp (LSDiv (ATInt (ITFixed IT16))) [l, r] = pure $ JsForeign "%0 / %1" [l,r]
546−cgOp (LSDiv (ATInt (ITFixed IT32))) [l, r] = pure $ JsForeign "%0 / %1 |0" [l,r]
547−cgOp (LSDiv (ATInt (ITFixed IT64))) [l, r] =
550− pure $ JsForeign "%0.divide(%1)" [l,r]
551−cgOp (LSDiv (ATInt ITNative)) [l,r] = pure $ JsForeign "%0/%1|0" [l, r]
552−cgOp (LSDiv (ATInt ITBig)) [l,r] =
555− pure $ JsMethod l "divide" [r]
556−cgOp (LURem (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 % %1" [l,r]
557−cgOp (LURem (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 % %1" [l,r]
558−cgOp (LURem (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) % (%1>>>0) |0" [l,r]
559−cgOp (LURem (ITFixed IT64)) [l,r] =
562− pure $ JsMethod l "remainder" [r]
563−cgOp (LSRem ATFloat) [l,r] = pure $ JsBinOp "%" l r
564−cgOp (LSRem (ATInt ITNative)) [l,r] = pure $ JsForeign "%0 % %1 |0" [l,r]
565−cgOp (LSRem (ATInt (ITFixed IT8))) [l, r] = pure $ JsForeign "%0 % %1" [l,r]
566−cgOp (LSRem (ATInt (ITFixed IT16))) [l, r] = pure $ JsForeign "%0 % %1" [l,r]
567−cgOp (LSRem (ATInt (ITFixed IT32))) [l, r] = pure $ JsForeign "%0 % %1 |0" [l,r]
568−cgOp (LSRem (ATInt (ITFixed IT64))) [l, r] =
571− pure $ JsMethod l "remainder" [r]
572−cgOp (LSRem (ATInt ITBig)) [l,r] =
575− pure $ JsMethod l "remainder" [r]
576−cgOp (LAnd ITNative) [l, r] = pure $ JsForeign "%0 & %1" [l,r]
577−cgOp (LAnd (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 & %1" [l,r]
578−cgOp (LAnd (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 & %1" [l,r]
579−cgOp (LAnd (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 & %1" [l,r]
580−cgOp (LAnd (ITFixed IT64)) [l,r] =
583− pure $ JsMethod l "and" [r]
584−cgOp (LAnd ITBig) [l,r] =
587− pure $ JsMethod l "and" [r]
588−cgOp (LOr ITNative) [l, r] = pure $ JsForeign "%0 | %1" [l,r]
589−cgOp (LOr (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 | %1" [l,r]
590−cgOp (LOr (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 | %1" [l,r]
591−cgOp (LOr (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 | %1" [l,r]
592−cgOp (LOr (ITFixed IT64)) [l,r] =
595− pure $ JsMethod l "or" [r]
596−cgOp (LOr ITBig) [l,r] =
599− pure $ JsMethod l "or" [r]
600−cgOp (LXOr ITNative) [l, r] = pure $ JsForeign "%0 ^ %1" [l,r]
601−cgOp (LXOr (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 ^ %1" [l,r]
602−cgOp (LXOr (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 ^ %1" [l,r]
603−cgOp (LXOr (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 ^ %1" [l,r]
604−cgOp (LXOr (ITFixed IT64)) [l,r] =
607− pure $ JsMethod l "xor" [r]
608−cgOp (LXOr ITBig) [l,r] =
611− pure $ JsMethod l "xor" [r]
612−cgOp (LSHL ITNative) [l, r] = pure $ JsForeign "%0 << %1 |0" [l,r]
613−cgOp (LSHL (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 << %1 & 0xFF" [l,r]
614−cgOp (LSHL (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 << %1 & 0xFFFF" [l,r]
615−cgOp (LSHL (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 << %1 |0" [l,r]
616−cgOp (LSHL (ITFixed IT64)) [l, r] =
619− pure $ JsForeign "%0.shiftLeft(%1).and(new jsbn.BigInteger(%2))" [l,r, JsStr $ show 0xFFFFFFFFFFFFFFFF]
620−cgOp (LSHL ITBig) [l,r] =
623− pure $ JsMethod l "shiftLeft" [r]
624−cgOp (LLSHR ITNative) [l, r] = pure $ JsForeign "%0 >> %1 |0" [l,r]
625−cgOp (LLSHR (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 >> %1" [l,r]
626−cgOp (LLSHR (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 >> %1" [l,r]
627−cgOp (LLSHR (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 >> %1|0" [l,r]
628−cgOp (LLSHR (ITFixed IT64)) [l, r] =
631− pure $ JsForeign "%0.shiftRight(%1)" [l,r]
632−cgOp (LASHR ITNative) [l, r] = pure $ JsForeign "%0 >> %1 |0" [l,r]
633−cgOp (LASHR (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 >> %1" [l,r]
634−cgOp (LASHR (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 >> %1" [l,r]
635−cgOp (LASHR (ITFixed IT32)) [l, r] = pure $ JsForeign "%0 >> %1|0" [l,r]
636−cgOp (LASHR (ITFixed IT64)) [l, r] =
639− pure $ JsForeign "%0.shiftRight(%1)" [l,r]
640−cgOp (LEq ATFloat) [l, r] = pure $ jsB2I $ JsBinOp "==" l r
641−cgOp (LEq (ATInt ITNative)) [l, r] = pure $ jsB2I $ JsBinOp "==" l r
642−cgOp (LEq (ATInt ITChar)) [l,r] = pure $ jsB2I $ JsBinOp "==" l r
643−cgOp (LEq (ATInt ITBig)) [l, r] =
646− pure $ jsB2I $ JsMethod l "equals" [r]
647−cgOp (LEq (ATInt (ITFixed IT8))) [l, r] = pure $ jsB2I $ JsBinOp "==" l r
648−cgOp (LEq (ATInt (ITFixed IT16))) [l, r] = pure $ jsB2I $ JsBinOp "==" l r
649−cgOp (LEq (ATInt (ITFixed IT32))) [l, r] = pure $ jsB2I $ JsBinOp "==" l r
650−cgOp (LEq (ATInt (ITFixed IT64))) [l, r] =
653− pure $ jsB2I $ JsMethod l "equals" [r]
654−cgOp (LLt (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 < %1" [l,r]
655−cgOp (LLt (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 < %1" [l,r]
656−cgOp (LLt (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) < (%1>>>0)" [l,r]
657−cgOp (LLt (ITFixed IT64)) [l, r] =
660− pure $ jsB2I $ JsForeign "%0.compareTo(%1) < 0" [l,r]
661−cgOp (LLe (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 <= %1" [l,r]
662−cgOp (LLe (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 <= %1" [l,r]
663−cgOp (LLe (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) <= (%1>>>0)" [l,r]
664−cgOp (LLe (ITFixed IT64)) [l, r] =
667− pure $ jsB2I $ JsForeign "%0.compareTo(%1) <= 0" [l,r]
668−cgOp (LGt (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 > %1" [l,r]
669−cgOp (LGt (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 > %1" [l,r]
670−cgOp (LGt (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) > (%1>>>0)" [l,r]
671−cgOp (LGt (ITFixed IT64)) [l, r] =
674− pure $ jsB2I $ JsForeign "%0.compareTo(%1) > 0" [l,r]
675−cgOp (LGe (ITFixed IT8)) [l, r] = pure $ JsForeign "%0 >= %1" [l,r]
676−cgOp (LGe (ITFixed IT16)) [l, r] = pure $ JsForeign "%0 >= %1" [l,r]
677−cgOp (LGe (ITFixed IT32)) [l, r] = pure $ JsForeign "(%0>>>0) >= (%1>>>0)" [l,r]
678−cgOp (LGe (ITFixed IT64)) [l, r] =
681− pure $ jsB2I $ JsForeign "%0.compareTo(%1) >= 0" [l,r]
682−cgOp (LSLt ATFloat) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
683−cgOp (LSLt (ATInt ITChar)) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
684−cgOp (LSLt (ATInt ITNative)) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
685−cgOp (LSLt (ATInt ITBig)) [l, r] =
688− pure $ jsB2I $ JsForeign "%0.compareTo(%1) < 0" [l,r]
689−cgOp (LSLt (ATInt (ITFixed IT8))) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
690−cgOp (LSLt (ATInt (ITFixed IT16))) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
691−cgOp (LSLt (ATInt (ITFixed IT32))) [l, r] = pure $ jsB2I $ JsBinOp "<" l r
692−cgOp (LSLt (ATInt (ITFixed IT64))) [l, r] =
695− pure $ jsB2I $ JsForeign "%0.compareTo(%1) < 0" [l,r]
696−cgOp (LSLe ATFloat) [l, r] = pure $ jsB2I $ JsBinOp "<=" l r
697−cgOp (LSLe (ATInt ITNative)) [l, r] = pure $ jsB2I $ JsBinOp "<=" l r
698−cgOp (LSLe (ATInt ITBig)) [l, r] =
701− pure $ jsB2I $ JsForeign "%0.compareTo(%1) <= 0" [l,r]
702−cgOp (LSLe (ATInt (ITFixed IT8))) [l, r] = pure $ jsB2I $ JsBinOp "<=" l r
703−cgOp (LSLe (ATInt (ITFixed IT16))) [l, r] = pure $ jsB2I $ JsBinOp "<=" l r
704−cgOp (LSLe (ATInt (ITFixed IT32))) [l, r] = pure $ jsB2I $ JsBinOp "<=" l r
705−cgOp (LSLe (ATInt (ITFixed IT64))) [l, r] =
708− pure $ jsB2I $ JsForeign "%0.compareTo(%1) <= 0" [l,r]
709−cgOp (LSGt ATFloat) [l, r] = pure $ jsB2I $ JsBinOp ">" l r
710−cgOp (LSGt (ATInt ITNative)) [l, r] = pure $ jsB2I $ JsBinOp ">" l r
711−cgOp (LSGt (ATInt ITBig)) [l, r] =
714− pure $ jsB2I $ JsForeign "%0.compareTo(%1) > 0" [l,r]
715−cgOp (LSGt (ATInt (ITFixed IT8))) [l, r] = pure $ jsB2I $ JsBinOp ">" l r
716−cgOp (LSGt (ATInt (ITFixed IT16))) [l, r] = pure $ jsB2I $ JsBinOp ">" l r
717−cgOp (LSGt (ATInt (ITFixed IT32))) [l, r] = pure $ jsB2I $ JsBinOp ">" l r
718−cgOp (LSGt (ATInt (ITFixed IT64))) [l, r] =
721− pure $ jsB2I $ JsForeign "%0.compareTo(%1) > 0" [l,r]
722−cgOp (LSGe ATFloat) [l, r] = pure $ jsB2I $ JsBinOp ">=" l r
723−cgOp (LSGe (ATInt ITNative)) [l, r] = pure $ jsB2I $ JsBinOp ">=" l r
724−cgOp (LSGe (ATInt ITBig)) [l, r] =
727− pure $ jsB2I $ JsForeign "%0.compareTo(%1) >= 0" [l,r]
728−cgOp (LSGe (ATInt (ITFixed IT8))) [l, r] = pure $ jsB2I $ JsBinOp ">=" l r
729−cgOp (LSGe (ATInt (ITFixed IT16))) [l, r] = pure $ jsB2I $ JsBinOp ">=" l r
730−cgOp (LSGe (ATInt (ITFixed IT32))) [l, r] = pure $ jsB2I $ JsBinOp ">=" l r
731−cgOp (LSGe (ATInt (ITFixed IT64))) [l, r] =
734− pure $ jsB2I $ JsForeign "%0.compareTo(%1) >= 0" [l,r]
735−cgOp (LSExt ITNative ITBig) [x] =
738− pure $ JsForeign "new jsbn.BigInteger(String(%0))" [x]
739−cgOp (LZExt (ITFixed IT8) ITNative) [x] = pure x
740−cgOp (LZExt (ITFixed IT16) ITNative) [x] = pure x
741−cgOp (LZExt (ITFixed IT32) ITNative) [x] = pure x
742−cgOp (LZExt ITNative ITBig) [x] =
745− pure $ JsForeign "new jsbn.BigInteger(String(%0))" [x]
746−cgOp (LTrunc ITBig ITNative) [x] =
749− pure $ JsForeign "%0.intValue()|0" [x]
750−cgOp (LTrunc (ITFixed IT16) (ITFixed IT8)) [x] = pure $ JsForeign "%0 & 0xFF" [x]
751−cgOp (LTrunc (ITFixed IT32) (ITFixed IT8)) [x] = pure $ JsForeign "%0 & 0xFF" [x]
752−cgOp (LTrunc (ITFixed IT64) (ITFixed IT8)) [x] =
755− pure $ JsForeign "%0.intValue() & 0xFF" [x]
756−cgOp (LTrunc (ITFixed IT32) (ITFixed IT16)) [x] = pure $ JsForeign "%0 & 0xFFFF" [x]
757−cgOp (LTrunc (ITFixed IT64) (ITFixed IT16)) [x] =
760− pure $ JsForeign "%0.intValue() & 0xFFFF" [x]
761−cgOp (LTrunc (ITFixed IT64) (ITFixed IT32)) [x] =
764− pure $ JsForeign "%0.intValue() & 0xFFFFFFFF" [x]
765−cgOp (LTrunc ITBig (ITFixed IT64)) [x] =
768− pure $ JsForeign "%0.and(new jsbn.BigInteger(%1))" [x, JsStr $ show 0xFFFFFFFFFFFFFFFF]
769−cgOp LStrConcat [l,r] = pure $ JsBinOp "+" l r
770−cgOp LStrLt [l, r] = pure $ jsB2I $ JsBinOp "<" l r
771−cgOp LStrEq [l,r] = pure $ jsB2I $ JsBinOp "==" l r
772−cgOp LStrLen [x] = pure $ JsForeign "%0.length" [x]
773−cgOp (LIntFloat ITNative) [x] = pure $ x
774−cgOp (LIntFloat ITBig) [x] =
777− pure $ JsForeign "%0.intValue()" [x]
778−cgOp (LFloatInt ITNative) [x] = pure $ JsForeign "%0|0" [x]
779−cgOp (LIntStr ITNative) [x] = pure $ JsApp "String" [x]
780−cgOp (LIntStr ITBig) [x] =
783− pure $ JsForeign "%0.toString()" [x]
784−cgOp (LStrInt ITNative) [x] = pure $ JsForeign "parseInt(%0)|0" [x]
785−cgOp (LStrInt ITBig) [x] =
788− pure $ JsForeign "new jsbn.BigInteger(%0)" [x]
789−cgOp (LFloatStr) [x] = pure $ JsApp "String" [x]
790−cgOp (LStrFloat) [x] = pure $ JsApp "parseFloat" [x]
791−cgOp (LChInt ITNative) [x] = pure $ JsForeign "%0.charCodeAt(0)|0" [x]
792−cgOp (LIntCh ITNative) [x] = pure $ JsApp "String.fromCharCode" [x]
793−cgOp LFExp [x] = pure $ JsApp "Math.exp" [x]
794−cgOp LFLog [x] = pure $ JsApp "Math.log" [x]
795−cgOp LFSin [x] = pure $ JsApp "Math.sin" [x]
796−cgOp LFCos [x] = pure $ JsApp "Math.cos" [x]
797−cgOp LFTan [x] = pure $ JsApp "Math.tan" [x]
798−cgOp LFASin [x] = pure $ JsApp "Math.asin" [x]
799−cgOp LFACos [x] = pure $ JsApp "Math.acos" [x]
800−cgOp LFATan [x] = pure $ JsApp "Math.atan" [x]
801−cgOp LFSqrt [x] = pure $ JsApp "Math.sqrt" [x]
802−cgOp LFFloor [x] = pure $ JsApp "Math.floor" [x]
803−cgOp LFCeil [x] = pure $ JsApp "Math.ceil" [x]
804−cgOp LFNegate [x] = pure $ JsForeign "-%0" [x]
805−cgOp LStrHead [x] = pure $ JsArrayProj (JsInt 0) x
806−cgOp LStrTail [x] = pure $ JsMethod x "slice" [JsInt 1]
807−cgOp LStrCons [l,r] = pure $ JsForeign "%0+%1" [l,r]
808−cgOp LStrIndex [x, y] = pure $ JsArrayProj y x
809−cgOp LStrRev [x] = pure $ JsForeign "%0.split('').reverse().join('')" [x]
810−cgOp LStrSubstr [offset,len,str] = pure $ JsForeign "%0.substr(Math.max(0,%1), Math.max(0, %2))" [str, offset, len]
814− put $ s {usedRead = True}
815− pure $ JsForeign (readStrTemplate $ conf s) []
816−cgOp LWriteStr [_,str] =
819− put $ s {usedWrite = True}
820− pure $ JsForeign (writeStrTemplate $ conf s) [str]
821−cgOp LSystemInfo [x] = pure $ JsApp "js_idris_systemInfo" [x]
822−cgOp (LExternal name) _ | name == sUN "prim__null" = pure JsNull
823−cgOp (LExternal name) [l,r] | name == sUN "prim__eqPtr" = pure $ JsBinOp "==" l r
824−cgOp LCrash [l] = pure $ JsErrorExp l
825−cgOp LNoOp [x] = pure x
826−cgOp op exps = error ("Operator " ++ show (op, exps) ++ " not implemented")