More inlining, fix issues in eval of case

This commit is contained in:
2025-09-23 20:22:50 -07:00
parent cc7d8b4968
commit 3143fa7b0a
5 changed files with 94 additions and 48 deletions

View File

@@ -63,12 +63,16 @@ Cont e = JSExp -> JSStmt e
record JSEnv where
constructor MkEnv
jsenv : List JSExp
-- This is not depth, it is incremented as we go down the tree to get fresh names
depth : Int
-- this was like this, are we not using depth?
push : JSEnv -> JSExp -> JSEnv
push (MkEnv env depth) exp = MkEnv (exp :: env) depth
incr : JSEnv JSEnv
incr env = MkEnv env.jsenv (1 + env.depth)
emptyJSEnv : JSEnv
emptyJSEnv = MkEnv Nil 0
@@ -78,7 +82,6 @@ litToJS (LChar c) = LitString $ pack (c :: Nil)
litToJS (LInt i) = LitInt i
-- Stuff nm.h1, nm.h2, ... into environment
-- TODO consider JSExp instead of nm, so we can have $foo.h1 instead of assigning a sc.
mkEnv : JSExp -> Int -> JSEnv -> List String -> JSEnv
mkEnv nm k env Nil = env
mkEnv nm k env (x :: xs) = mkEnv nm (1 + k) (push env (Dot nm "h\{show k}")) xs
@@ -173,7 +176,7 @@ termToJS env (CConstr nm args) f = go args 0 (\ args => f $ LitObject (("tag", L
go : e. List CExp -> Int -> (List (String × JSExp) -> JSStmt e) -> JSStmt e
go Nil ix k = k Nil
go (t :: ts) ix k = termToJS env t $ \ t' => go ts (ix + 1) $ \ args => k $ ("h\{show ix}", t') :: args
termToJS env (CAppRef nm args etas) f = termToJS env (CRef nm) (\ t' => (argsToJS t' args Lin f))
termToJS env (CAppRef nm args etas) f = termToJS env (CRef nm) (\ t' => (argsToJS env t' args Lin f))
where
etaExpand : JSEnv -> Nat -> SnocList JSExp -> JSExp -> JSExp
etaExpand env Z args tm = Apply tm (args <>> Nil)
@@ -182,31 +185,25 @@ termToJS env (CAppRef nm args etas) f = termToJS env (CRef nm) (\ t' => (argsToJ
env' = push env (Var nm')
in JLam (nm' :: Nil) $ JReturn $ etaExpand (push env (Var nm')) etas (args :< Var nm') tm
argsToJS : e. JSExp -> List CExp -> SnocList JSExp -> (JSExp -> JSStmt e) -> JSStmt e
argsToJS tm Nil acc k = k (etaExpand env (cast etas) acc tm)
-- k (acc <>> Nil)
argsToJS tm (x :: xs) acc k = termToJS env x (\ x' => argsToJS tm xs (acc :< x') k)
argsToJS : e. JSEnv -> JSExp -> List CExp -> SnocList JSExp -> (JSExp -> JSStmt e) -> JSStmt e
argsToJS env tm Nil acc k = k (etaExpand env (cast etas) acc tm)
argsToJS env tm (x :: xs) acc k = termToJS env x (\ x' => argsToJS (incr env) tm xs (acc :< x') k)
termToJS env (CApp t arg) f = termToJS env t (\ t' => termToJS env arg (\arg' => f (Apply t' (arg' :: Nil))))
termToJS {e} env (CCase t alts) f =
-- need to assign the scrutinee to a variable (unless it is a var already?)
-- and add (Bnd -> JSExpr map)
-- TODO default case, let's drop the extra field.
termToJS env t $ \case
(Var nm) => maybeCaseStmt env (Var nm) alts
t' => do
-- TODO refactor nm to be a JSExp with Var{} or Dot{}
-- FIXME sc$ seemed to shadow something else, lets get this straightened out
-- we need freshName names that are not in env (i.e. do not play in debruijn)
-- TODO with inlining, we hit cases where the let gets pulled forward more than once
-- two cases as separate args, se we need actual unique names. For now, we're calling
-- incr when processing App, as a stopgap, we probably need a fresh names state monad
let nm = "_sc$\{show env.depth}"
-- increment the bit that goes into the name
let env' = MkEnv env.jsenv (1 + env.depth)
let env' = incr env
if simpleJSExp t'
then (maybeCaseStmt env' t' alts)
else JSnoc (JConst nm t') (maybeCaseStmt env' (Var nm) alts)
where
termToJSAlt : JSEnv -> JSExp -> CAlt -> JAlt
termToJSAlt env nm (CConAlt name info args u) = JConAlt name (termToJS (mkEnv nm 0 env args) u f)
@@ -231,7 +228,7 @@ jsKeywords = (
"implements" :: "class" :: "let" :: "package" :: "private" :: "protected" :: "public" ::
"static" :: "yield" ::
"null" :: "true" :: "false" ::
-- might not be a big issue with namespaces on names now.
-- might not occur now that we have namespaces on the names
"String" :: "Number" :: "Array" :: "BigInt" :: Nil)
@@ -251,17 +248,13 @@ jsIdent id = if elem id jsKeywords then text ("$" ++ id) else text $ pack $ fix
else
'$' :: (toHex (cast x)) ++ fix xs
stmtToDoc : e. JSStmt e -> Doc
expToDoc : JSExp -> Doc
expToDoc (LitArray xs) = fatalError "TODO - LitArray to doc"
expToDoc (LitObject xs) = text "{" <+> folddoc (\ a e => a ++ text ", " <+/> e) (map entry xs) <+> text "}"
where
entry : (String × JSExp) -> Doc
-- TODO quote if needed
entry (nm, exp) = jsIdent nm ++ text ":" <+> expToDoc exp
expToDoc (LitString str) = text $ quoteString str
@@ -280,7 +273,6 @@ expToDoc (JPrimOp op t u) = parens 0 1 (expToDoc t) <+> text op <+> parens 0 1 (
caseBody : e. JSStmt e -> Doc
caseBody stmt@(JReturn x) = nest 2 (line ++ stmtToDoc stmt)
-- caseBody {e = Return} stmt@(JCase{}) = nest 2 (line ++ stmtToDoc stmt)
caseBody {e} stmt@(JCase _ _) = nest 2 (line ++ stmtToDoc stmt </> text "break;")
caseBody stmt = line ++ text "{" ++ nest 2 (line ++ stmtToDoc stmt </> text "break;") </> text "}"
@@ -472,5 +464,5 @@ compile = do
let exec = stmtToDoc $ JPlain $ Apply (Var $ show name) Nil
pure $ reverse (exec :: tmp)
Nothing =>
-- TODO maybe dump everything if there is no main
-- TODO maybe emit everything if there is no main
error emptyFC "No main function found"