2Module : IRTS.JavaScript.Codegen
3Description : The JavaScript common code generator.
6Maintainer : The Idris Community.
8{-# LANGUAGE CPP, OverloadedStrings #-}
10module IRTS.JavaScript.Codegen( codegenJs
16import IRTS.CodegenCommon
18import IRTS.JavaScript.AST
19import IRTS.JavaScript.LangTransforms
20import IRTS.JavaScript.Name
21import IRTS.JavaScript.PrimOp
22import IRTS.JavaScript.Specialize
26import Control.Applicative (pure, (<$>))
28import Control.Monad.Trans.State
29import Data.Foldable (foldMap)
30import Data.Generics.Uniplate.Data
32import Data.Map.Strict (Map)
33import qualified Data.Map.Strict as Map
35import qualified Data.Set as Set
36import Data.Text (Text)
37import qualified Data.Text as T
38import qualified Data.Text.IO as TIO
39import System.Directory (doesFileExist)
40import System.Environment
43-- | Code generation stats hold information about the generated user
44-- code. Based on that information we add additional code to make
46data CGStats = CGStats { usedBigInt :: Bool
47 , partialApplications :: Set Partial
48 , hiddenClasses :: Set HiddenClass
51#if (MIN_VERSION_base(4,11,0))
52instance Semigroup CGStats where
56-- If we generate code for two declarations we want to merge their code
58instance Monoid CGStats where
59 mempty = CGStats { partialApplications = Set.empty
60 , hiddenClasses = Set.empty
63 mappend x y = CGStats { partialApplications = partialApplications x `Set.union` partialApplications y
64 , hiddenClasses = hiddenClasses x `Set.union` hiddenClasses y
65 , usedBigInt = usedBigInt x || usedBigInt y
69data CGConf = CGConf { header :: Text
72 , extraRunTime :: String
76getInclude :: FilePath -> IO Text
79 libs <- getIdrisLibDir
80 let libPath = libs </> p
81 exitsInLib <- doesFileExist libPath
86getIncludes :: [FilePath] -> IO Text
88 incs <- mapM getInclude l
89 return $ T.intercalate "\n\n" incs
91includeLibs :: [String] -> String
100 concatMap (\lib -> "var " ++ (repl <$> lib) ++ " = require(\"" ++ lib ++"\");\n")
102isYes :: Maybe String -> Bool
103isYes (Just "Y") = True
104isYes (Just "y") = True
107makeExportDecls :: Map Name LDecl -> ExportIFace -> [Text]
108makeExportDecls defs (Export _ _ e) =
109 concatMap makeExport e
111 uncurryF name argTy (Just args) retTy =
112 if length argTy == length args then
113 case (retTy, length args) of
114 (FIO _, 0) -> T.concat ["function(){return ", name, "()()}"]
116 else T.concat [ "function(){ return "
118 , ".apply(this, Array.prototype.slice.call(arguments, 0,", T.pack $ show $ length args,"))"
119 , T.concat $ map (\x -> T.concat ["(arguments[", T.pack $ show x , "])"]) [length args .. (length argTy - 1)]
122 uncurryF name argTy Nothing retTy = name
124 makeExport (ExportData _) =
126 makeExport (ExportFun name (FStr exportname) retTy argTy) =
127 [T.concat [ T.pack $ exportname
129 , uncurryF (jsName name) argTy (getArgList' name defs) retTy
133codegenJs :: CGConf -> CodeGenerator
136 debug <- isYes <$> lookupEnv "IDRISJS_DEBUG"
137 let defs' = Map.fromList $ liftDecls ci
138 let defs = globlToCon defs'
139 let iface = interfaces ci
140 let used = if iface then
141 Map.elems $ removeDeadCode defs (getExpNames $ exportDecls ci)
142 else Map.elems $ removeDeadCode defs [sMN 0 "runMain"]
144 writeFile (outputFile ci ++ ".LDeclsDebug") $ (unlines $ intersperse "" $ map show used) ++ "\n\n\n"
145 putStrLn $ "Finished calculating used"
147 let (out, stats) = doCodegen defs used
149 path <- getIdrisJSRTSDir
150 jsbn <- if usedBigInt stats
151 then TIO.readFile $ path </> jsbnPath conf
154 runtimeCommon <- TIO.readFile $ path </> "Runtime-common.js"
155 extraRT <- TIO.readFile $ path </> (extraRunTime conf)
157 includes <- getIncludes $ includes ci
158 let libs = T.pack $ includeLibs $ compileLibs ci
159 TIO.writeFile (outputFile ci) $ T.concat [ header conf
160 , "\"use strict\";\n\n"
163 , runtimeCommon, "\n"
166 -- external libraries
170 , doPartials (partialApplications stats), "\n"
171 , doHiddenClasses (hiddenClasses stats), "\n"
173 , if iface then T.concat ["module.exports = {\n", T.intercalate ",\n" $ concatMap (makeExportDecls defs) (exportDecls ci), "\n};\n"]
174 else jsName (sMN 0 "runMain") `T.append` "();\n"
179doPartials :: Set Partial -> Text
181 T.intercalate "\n" (map f $ Set.toList x)
183 f p@(Partial n i j) =
184 let vars1 = map (T.pack . ("x"++) . show) [1..i]
185 vars2 = map (T.pack . ("x"++) . show) [(i+1)..j]
187 JsFun (jsNamePartial p) vars1 $ JsReturn $
188 jsCurryLam vars2 (jsAppN (jsName n) (map JsVar (vars1 ++ vars2)) )
190doHiddenClasses :: Set HiddenClass -> Text
192 T.intercalate "\n" (map f $ Set.toList x)
194 f p@(HiddenClass n id 0) = jsStmt2Text $ JsDecConst (jsNameHiddenClass p) $ JsObj [("type", JsInt id)]
195 f p@(HiddenClass n id arity) =
196 let vars = map dataPartName $ take arity [1..]
198 JsFun (jsNameHiddenClass p) vars $ JsSeq (JsSet (JsProp JsThis "type") (JsInt id)) $ seqJs
199 $ map (\tv -> JsSet (JsProp JsThis tv) (JsVar tv)) vars
202-- | Generate code for each declaration and collect stats.
203-- LFunctions are turned into JS function declarations. They are
204-- preceded by a comment that gives their name. Constructor
205-- declarations are ignored.
206doCodegen :: Map Name LDecl -> [LDecl] -> (Text, CGStats)
207doCodegen defs = foldMap (doCodegenDecl defs)
209 doCodegenDecl :: Map Name LDecl -> LDecl -> (Text, CGStats)
210 doCodegenDecl defs (LFun _ name args def) =
211 let (ast, stats) = cgFun defs name args def
212 fnComment = jsStmt2Text (JsComment $ T.pack $ show name)
213 in (T.concat [fnComment, "\n", jsStmt2Text ast, "\n"], stats)
214 doCodegenDecl defs (LConstructor n i sz) = ("", mempty)
217seqJs :: [JsStmt] -> JsStmt
219seqJs (x:xs) = JsSeq x (seqJs xs)
222data CGBodyState = CGBodyState { defs :: Map Name LDecl
224 , reWrittenNames :: Map.Map Name JsExpr
225 , currentFnNameAndArgs :: (Text, [Text])
226 , usedArgsTailCallOptim :: Set (Text, Text)
229 , partialApps :: Set Partial
230 , hiddenCls :: Set HiddenClass
233getNewCGName :: State CGBodyState Text
237 let v = lastIntName st + 1
238 put $ st {lastIntName = v}
239 return $ jsNameGenerated v
241addPartial :: Partial -> State CGBodyState ()
243 modify (\s -> s {partialApps = Set.insert p (partialApps s) })
245addHiddenClass :: HiddenClass -> State CGBodyState ()
247 modify (\s -> s {hiddenCls = Set.insert p (hiddenCls s) })
249addUsedArgsTailCallOptim :: Set (Text, Text) -> State CGBodyState ()
250addUsedArgsTailCallOptim p =
251 modify (\s -> s {usedArgsTailCallOptim = Set.union p (usedArgsTailCallOptim s) })
253getConsId :: Name -> State CGBodyState (Int, Int)
257 case Map.lookup n (defs st) of
258 Just (LConstructor _ conId arity) -> pure (conId, arity)
259 _ -> error $ "Internal JS Backend error " ++ showCG n ++ " is not a constructor."
261getArgList' :: Name -> Map Name LDecl -> Maybe [Name]
263 case Map.lookup n defs of
264 Just (LFun _ _ a _) -> Just a
267getArgList :: Name -> State CGBodyState (Maybe [Name])
271 pure $ getArgList' n (defs st)
273data BodyResTarget = ReturnBT
279cgFun :: Map Name LDecl -> Name -> [Name] -> LExp -> (JsStmt, CGStats)
280cgFun dfs n args def = do
281 let fnName = jsName n
282 let argNames = map jsName args
283 let ((decs, res),st) = runState
284 (cgBody ReturnBT def)
285 (CGBodyState { defs = dfs
287 , reWrittenNames = Map.empty
288 , currentFnNameAndArgs = (fnName, argNames)
289 , usedArgsTailCallOptim = Set.empty
292 , partialApps = Set.empty
293 , hiddenCls = Set.empty
296 let body = if isTailRec st then JsSeq (declareUsedOptimArgs $ usedArgsTailCallOptim st) (JsForever ((seqJs decs) `JsSeq` res)) else (seqJs decs) `JsSeq` res
297 let fn = JsFun fnName argNames body
298 let state' = CGStats { partialApplications = partialApps st
299 , hiddenClasses = hiddenCls st
300 , usedBigInt = usedITBig st
304addRT :: BodyResTarget -> JsExpr -> JsStmt
305addRT ReturnBT x = JsReturn x
306addRT (DecBT n) x = JsDecLet n x
307addRT (DecConstBT n) x = JsDecConst n x
308addRT (SetBT n) x = JsSet (JsVar n) x
309addRT GetExpBT x = JsExprStmt x
311declareUsedOptimArgs :: Set (Text, Text) -> JsStmt
312declareUsedOptimArgs x = seqJs $ map (\(x,y) -> JsDecLet x (JsVar y) ) (Set.toList x)
314tailCallOptimRefreshArgs :: [(Text, JsExpr)] -> Set Text -> ((JsStmt, JsStmt), Set (Text, Text))
315tailCallOptimRefreshArgs [] s = ((JsEmpty, JsEmpty), Set.empty)
316tailCallOptimRefreshArgs ((n,x):r) s =
317 let ((y1,y2), y3) = tailCallOptimRefreshArgs r (Set.insert n s) --
318 in if Set.null $ (Set.fromList [ z | z <- universeBi x ]) `Set.intersection` s then
319 ((y1, jsSetVar n x `JsSeq` y2), y3)
321 let n' = jsTailCallOptimName n
322 in ((jsSetVar n' x `JsSeq` y1, jsSetVar n (JsVar n') `JsSeq` y2), Set.insert (n',n) y3)
324cgName :: Name -> State CGBodyState JsExpr
327 case Map.lookup b (reWrittenNames st) of
329 _ -> pure $ JsVar $ jsName b
331cgBody :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
334 (LCase _ (LOp oper [x, y]) [LConstCase (I 0) (LCon _ _ ff []), LDefaultCase (LCon _ _ tt [])])
335 | (ff == qualifyN "Prelude.Bool" "False" &&
336 tt == qualifyN "Prelude.Bool" "True") ->
337 case (Map.lookup oper primDB) of
338 Just (needBI, pti, c) | pti == PTBool -> do
339 z <- mapM (cgBody GetExpBT) [x, y]
340 when needBI setUsedITBig
341 let res = jsPrimCoerce pti PTBool $ c $ map (jsStmt2Expr . snd) z
342 pure $ (concat $ map fst z, addRT rt res)
344 (LCase _ e [LConCase _ n _ (LCon _ _ tt []), LDefaultCase (LCon _ _ ff [])])
345 | (ff == qualifyN "Prelude.Bool" "False" &&
346 tt == qualifyN "Prelude.Bool" "True") -> do
347 (d, v) <- cgBody GetExpBT e
348 test <- formConTest n (jsStmt2Expr v)
349 pure $ (d, addRT rt $ JsUniOp (T.pack "!") $ JsUniOp (T.pack "!") test)
350 (LCase _ e [LConCase _ n _ (LCon _ _ tt []), LConCase _ _ _ (LCon _ _ ff [])])
351 | (ff == qualifyN "Prelude.Bool" "False" &&
352 tt == qualifyN "Prelude.Bool" "True") -> do
353 (d, v) <- cgBody GetExpBT e
354 test <- formConTest n (jsStmt2Expr v)
355 pure $ (d, addRT rt $ JsUniOp (T.pack "!") $ JsUniOp (T.pack "!") test)
356 (LCase _ e [LConCase _ n _ (LCon _ _ ff []), LDefaultCase (LCon _ _ tt [])])
357 | (ff == qualifyN "Prelude.Bool" "False" &&
358 tt == qualifyN "Prelude.Bool" "True") -> do
359 (d, v) <- cgBody GetExpBT e
360 test <- formConTest n (jsStmt2Expr v)
361 pure $ (d, addRT rt $ JsUniOp (T.pack "!") test)
362 (LCase _ e [LConCase _ n _ (LCon _ _ ff []), LConCase _ _ _ (LCon _ _ tt [])])
363 | (ff == qualifyN "Prelude.Bool" "False" &&
364 tt == qualifyN "Prelude.Bool" "True") -> do
365 (d, v) <- cgBody GetExpBT e
366 test <- formConTest n (jsStmt2Expr v)
367 pure $ (d, addRT rt $ JsUniOp (T.pack "!") test)
368 (LCase f e [LConCase nf ff [] alt, LConCase nt tt [] conseq])
369 | (ff == qualifyN "Prelude.Bool" "False" &&
370 tt == qualifyN "Prelude.Bool" "True") ->
371 cgBody' rt $ LCase f e [LConCase nt tt [] conseq, LConCase nf ff [] alt]
372 expr -> cgBody' rt expr
374cgBody' :: BodyResTarget -> LExp -> State CGBodyState ([JsStmt], JsStmt)
377 argsFn <- getArgList n
379 Just a -> cgBody' rt (LApp False (LV n) [])
382 pure $ ([], addRT rt n')
383cgBody' rt (LApp tailcall (LV fn) args) =
385 let fname = jsName fn
387 let (currFn, argN) = currentFnNameAndArgs st
388 z <- mapM (cgBody GetExpBT) args
389 let argVals = map (jsStmt2Expr . snd) z
390 let preDecs = concat $ map fst z
391 case (fname == currFn && (length args) == (length argN), rt) of
394 modify (\x-> x {isTailRec = True})
395 let ((y1,y2), y3) = tailCallOptimRefreshArgs (zip argN argVals) Set.empty
396 addUsedArgsTailCallOptim y3
397 pure (preDecs, y1 `JsSeq` y2)
399 app <- formApp fn argVals
400 pure (preDecs, addRT rt app)
402cgBody' rt (LForce (LLazyApp n args)) = cgBody rt (LApp False (LV n) args)
403cgBody' rt (LLazyApp n args) =
405 (d,v) <- cgBody ReturnBT (LApp False (LV n) args)
406 pure ([], addRT rt $ jsLazy $ jsStmt2Expr $ JsSeq (seqJs d) v)
407cgBody' rt (LForce e) =
409 (d,v) <- cgBody GetExpBT e
410 pure (d, addRT rt $ JsForce $ jsStmt2Expr v)
411cgBody' rt (LLet n v sc) =
413 (d1, v1) <- cgBody (DecConstBT $ jsName n) v
414 (d2, v2) <- cgBody rt sc
415 pure $ ((d1 ++ v1 : d2), v2)
416cgBody' rt (LProj e i) =
418 (d, v) <- cgBody GetExpBT e
419 pure $ (d, addRT rt $ JsArrayProj (JsInt $ i+1) $ jsStmt2Expr v)
420cgBody' rt (LCon _ conId n args) =
422 z <- mapM (cgBody GetExpBT) args
423 con <- formCon n (map (jsStmt2Expr . snd) z)
424 pure $ (concat $ map fst z, addRT rt con)
425cgBody' rt (LCase _ e alts) = do
426 (d, v) <- cgBody GetExpBT e
427 resName <- getNewCGName
429 case (all altHasNoProj alts && length alts <= 2, v) of
430 (True, _) -> pure (JsEmpty, jsStmt2Expr v)
431 (False, JsExprStmt (JsVar n)) -> pure (JsEmpty, jsStmt2Expr v)
433 swName <- getNewCGName
434 pure (JsDecConst swName $ jsStmt2Expr v, JsVar swName)
435 sw' <- cgIfTree rt resName entry alts
439 Nothing -> JsExprStmt JsNull
441 ReturnBT -> pure (d ++ [decSw], sw)
442 (DecBT nvar) -> pure (d ++ [decSw, JsDecLet nvar JsNull], sw)
443 (DecConstBT nvar) -> pure (d ++ [decSw, JsDecLet nvar JsNull], sw)
444 (SetBT nvar) -> pure (d ++ [decSw], sw)
447 (d ++ [decSw, JsDecLet resName JsNull, sw], JsExprStmt $ JsVar resName)
448cgBody' rt (LConst c) =
451 pure ([], (addRT rt) $ cst)
452cgBody' rt (LOp op args) =
454 z <- mapM (cgBody GetExpBT) args
455 res <- cgOp op (map (jsStmt2Expr . snd) z)
456 pure $ (concat $ map fst z, addRT rt $ res)
457cgBody' rt LNothing = pure ([], addRT rt JsNull)
458cgBody' rt (LError x) = pure ([], JsError $ JsStr x)
459cgBody' rt x@(LForeign dres (FStr code) args ) =
461 z <- mapM (cgBody GetExpBT) (map snd args)
462 jsArgs <- sequence $ map cgForeignArg (zip (map fst args) (map (jsStmt2Expr . snd) z))
463 jsDres <- cgForeignRes dres $ JsForeign (T.pack code) jsArgs
464 pure $ (concat $ map fst z, addRT rt $ jsDres)
465cgBody' _ x = error $ "Instruction " ++ show x ++ " not compilable yet"
467altsRT :: Text -> BodyResTarget -> BodyResTarget
468altsRT rn ReturnBT = ReturnBT
469altsRT rn (DecBT n) = SetBT n
470altsRT rn (SetBT n) = SetBT n
471altsRT rn (DecConstBT n) = SetBT n
472altsRT rn GetExpBT = SetBT rn
474altHasNoProj :: LAlt -> Bool
475altHasNoProj (LConCase _ _ args _) = args == []
478formApp :: Name -> [JsExpr] -> State CGBodyState JsExpr
479formApp fn argVals = case specialCall fn of
480 Just (arity, g) | arity == length argVals -> pure $ g argVals
482 argsFn <- getArgList fn
485 Nothing -> pure $ jsCurryApp fname argVals
487 let lenAgFn = length agFn
488 let lenArgs = length argVals
489 case compare lenAgFn lenArgs of
490 EQ -> pure $ JsApp fname argVals
491 LT -> pure $ jsCurryApp (JsApp fname (take lenAgFn argVals)) (drop lenAgFn argVals)
493 let part = Partial fn lenArgs lenAgFn
495 pure $ jsAppN (jsNamePartial part) argVals
497formCon :: Name -> [JsExpr] -> State CGBodyState JsExpr
499 case specialCased n of
500 Just (ctor, test, match) -> pure $ ctor args
502 (conId, arity) <- getConsId n
503 let hc = HiddenClass n conId arity
505 pure $ if (arity > 0)
506 then JsNew (JsVar $ jsNameHiddenClass hc) args
507 else JsVar $ jsNameHiddenClass hc
509formConTest :: Name -> JsExpr -> State CGBodyState JsExpr
511 case specialCased n of
512 Just (ctor, test, match) -> pure $ test x
514 (conId, arity) <- getConsId n
515 pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
517 -- then pure $ JsBinOp "===" (JsProp x (T.pack "type")) (JsInt conId)
518 -- else pure $ JsBinOp "===" x (JsInt conId)
520formProj :: Name -> JsExpr -> Int -> JsExpr
522 case specialCased n of
523 Just (ctor, test, proj) -> proj v i
524 Nothing -> JsProp v (dataPartName i)
526smartif :: JsExpr -> JsStmt -> Maybe JsStmt -> JsStmt
527smartif cond conseq (Just alt) = JsIf cond conseq (Just alt)
528smartif cond conseq Nothing = conseq
530formConstTest :: JsExpr -> Const -> State CGBodyState JsExpr
531formConstTest scrvar t = case t of
534 cgOp' PTBool (LEq (ATInt ITBig)) [scrvar, t']
537 pure $ JsBinOp "===" scrvar t'
539cgIfTree :: BodyResTarget
543 -> State CGBodyState (Maybe JsStmt)
544cgIfTree _ _ _ [] = pure Nothing
545cgIfTree rt resName scrvar ((LConstCase t exp):r) = do
546 (d, v) <- cgBody (altsRT resName rt) exp
547 alternatives <- cgIfTree rt resName scrvar r
548 test <- formConstTest scrvar t
550 smartif test (JsSeq (seqJs d) v) alternatives
551cgIfTree rt resName scrvar ((LDefaultCase exp):r) = do
552 (d, v) <- cgBody (altsRT resName rt) exp
553 pure $ Just $ JsSeq (seqJs d) v
554cgIfTree rt resName scrvar ((LConCase _ n args exp):r) = do
555 alternatives <- cgIfTree rt resName scrvar r
556 test <- formConTest n scrvar
558 let rwn = reWrittenNames st
563 (\m (n, j) -> Map.insert n (formProj n scrvar j) m)
567 (d, v) <- cgBody (altsRT resName rt) exp
569 put $ st1 {reWrittenNames = rwn}
570 let branchBody = JsSeq (seqJs d) v
571 pure $ Just $ smartif test branchBody alternatives
574cgForeignArg :: (FDesc, JsExpr) -> State CGBodyState JsExpr
575cgForeignArg (FApp (UN "JS_IntT") _, v) = pure v
576cgForeignArg (FCon (UN "JS_Str"), v) = pure v
577cgForeignArg (FCon (UN "JS_Ptr"), v) = pure v
578cgForeignArg (FCon (UN "JS_Unit"), v) = pure v
579cgForeignArg (FCon (UN "JS_Float"), v) = pure v
580cgForeignArg (FApp (UN "JS_FnT") [_,FApp (UN "JS_Fn") [_,_, a, FApp (UN "JS_FnBase") [_,b]]], f) =
582cgForeignArg (FApp (UN "JS_FnT") [_,FApp (UN "JS_Fn") [_,_, a, FApp (UN "JS_FnIO") [_,_, b]]], f) =
584 jsx <- cgForeignArg (a, JsVar "x")
585 jsres <- cgForeignRes b $ jsCurryApp (jsCurryApp f [jsx]) [JsNull]
586 pure $ JsLambda ["x"] $ JsReturn jsres
587cgForeignArg (desc, _) =
590 error $ "Foreign arg type " ++ show desc ++ " not supported. While generating function " ++ (show $ fst $ currentFnNameAndArgs st)
592cgForeignRes :: FDesc -> JsExpr -> State CGBodyState JsExpr
593cgForeignRes (FApp (UN "JS_IntT") _) x = pure x
594cgForeignRes (FCon (UN "JS_Unit")) x = pure x
595cgForeignRes (FCon (UN "JS_Str")) x = pure x
596cgForeignRes (FCon (UN "JS_Ptr")) x = pure x
597cgForeignRes (FCon (UN "JS_Float")) x = pure x
598cgForeignRes desc val =
601 error $ "Foreign return type " ++ show desc ++ " not supported. While generating function " ++ (show $ fst $ currentFnNameAndArgs st)
603setUsedITBig :: State CGBodyState ()
604setUsedITBig = modify (\s -> s {usedITBig = True})
607cgConst :: Const -> State CGBodyState JsExpr
608cgConst (I i) = pure $ JsInt i
612 pure $ JsForeign "new $JSRTS.jsbn.BigInteger(%0)" [JsStr $ show i]
613cgConst (Ch c) = pure $ JsStr [c]
614cgConst (Str s) = pure $ JsStr s
615cgConst (Fl f) = pure $ JsDouble f
616cgConst (B8 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFF") []
617cgConst (B16 x) = pure $ JsForeign (T.pack $ show x ++ " & 0xFFFF") []
618cgConst (B32 x) = pure $ JsForeign (T.pack $ show x ++ "|0" ) []
622 pure $ JsForeign "new $JSRTS.jsbn.BigInteger(%0).and(new $JSRTS.jsbn.BigInteger(%1))" [JsStr $ show x, JsStr $ show 0xFFFFFFFFFFFFFFFF]
623cgConst x | isTypeConst x = pure $ JsInt 0
624cgConst x = error $ "Constant " ++ show x ++ " not compilable yet"
626cgOp :: PrimFn -> [JsExpr] -> State CGBodyState JsExpr
629cgOp' :: JsPrimTy -> PrimFn -> [JsExpr] -> State CGBodyState JsExpr
630cgOp' pt (LExternal name) _ | name == sUN "prim__null" = pure JsNull
631cgOp' pt (LExternal name) [l,r] | name == sUN "prim__eqPtr" = pure $ JsBinOp "==" l r
632cgOp' pt op exps = case Map.lookup op primDB of
633 Just (useBigInt, pti, combinator) -> do
634 when useBigInt setUsedITBig
635 pure $ jsPrimCoerce pti pt $ combinator exps
636 Nothing -> error ("Operator " ++ show (op, exps) ++ " not implemented")
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list