More inlining, fix issues in eval of case
This commit is contained in:
@@ -63,12 +63,16 @@ Cont e = JSExp -> JSStmt e
|
|||||||
record JSEnv where
|
record JSEnv where
|
||||||
constructor MkEnv
|
constructor MkEnv
|
||||||
jsenv : List JSExp
|
jsenv : List JSExp
|
||||||
|
-- This is not depth, it is incremented as we go down the tree to get fresh names
|
||||||
depth : Int
|
depth : Int
|
||||||
|
|
||||||
-- this was like this, are we not using depth?
|
-- this was like this, are we not using depth?
|
||||||
push : JSEnv -> JSExp -> JSEnv
|
push : JSEnv -> JSExp -> JSEnv
|
||||||
push (MkEnv env depth) exp = MkEnv (exp :: env) depth
|
push (MkEnv env depth) exp = MkEnv (exp :: env) depth
|
||||||
|
|
||||||
|
incr : JSEnv → JSEnv
|
||||||
|
incr env = MkEnv env.jsenv (1 + env.depth)
|
||||||
|
|
||||||
emptyJSEnv : JSEnv
|
emptyJSEnv : JSEnv
|
||||||
emptyJSEnv = MkEnv Nil 0
|
emptyJSEnv = MkEnv Nil 0
|
||||||
|
|
||||||
@@ -78,7 +82,6 @@ litToJS (LChar c) = LitString $ pack (c :: Nil)
|
|||||||
litToJS (LInt i) = LitInt i
|
litToJS (LInt i) = LitInt i
|
||||||
|
|
||||||
-- Stuff nm.h1, nm.h2, ... into environment
|
-- 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 : JSExp -> Int -> JSEnv -> List String -> JSEnv
|
||||||
mkEnv nm k env Nil = env
|
mkEnv nm k env Nil = env
|
||||||
mkEnv nm k env (x :: xs) = mkEnv nm (1 + k) (push env (Dot nm "h\{show k}")) xs
|
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 : ∀ e. List CExp -> Int -> (List (String × JSExp) -> JSStmt e) -> JSStmt e
|
||||||
go Nil ix k = k Nil
|
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
|
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
|
where
|
||||||
etaExpand : JSEnv -> Nat -> SnocList JSExp -> JSExp -> JSExp
|
etaExpand : JSEnv -> Nat -> SnocList JSExp -> JSExp -> JSExp
|
||||||
etaExpand env Z args tm = Apply tm (args <>> Nil)
|
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')
|
env' = push env (Var nm')
|
||||||
in JLam (nm' :: Nil) $ JReturn $ etaExpand (push env (Var nm')) etas (args :< Var nm') tm
|
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 : ∀ e. JSEnv -> JSExp -> List CExp -> SnocList JSExp -> (JSExp -> JSStmt e) -> JSStmt e
|
||||||
argsToJS tm Nil acc k = k (etaExpand env (cast etas) acc tm)
|
argsToJS env tm Nil acc k = k (etaExpand env (cast etas) acc tm)
|
||||||
-- k (acc <>> Nil)
|
argsToJS env tm (x :: xs) acc k = termToJS env x (\ x' => argsToJS (incr env) tm xs (acc :< x') k)
|
||||||
argsToJS tm (x :: xs) acc k = termToJS env x (\ x' => argsToJS 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 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 =
|
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
|
termToJS env t $ \case
|
||||||
(Var nm) => maybeCaseStmt env (Var nm) alts
|
(Var nm) => maybeCaseStmt env (Var nm) alts
|
||||||
t' => do
|
t' => do
|
||||||
-- TODO refactor nm to be a JSExp with Var{} or Dot{}
|
-- TODO with inlining, we hit cases where the let gets pulled forward more than once
|
||||||
-- FIXME sc$ seemed to shadow something else, lets get this straightened out
|
-- two cases as separate args, se we need actual unique names. For now, we're calling
|
||||||
-- we need freshName names that are not in env (i.e. do not play in debruijn)
|
-- incr when processing App, as a stopgap, we probably need a fresh names state monad
|
||||||
let nm = "_sc$\{show env.depth}"
|
let nm = "_sc$\{show env.depth}"
|
||||||
-- increment the bit that goes into the name
|
-- increment the bit that goes into the name
|
||||||
let env' = MkEnv env.jsenv (1 + env.depth)
|
let env' = incr env
|
||||||
if simpleJSExp t'
|
if simpleJSExp t'
|
||||||
then (maybeCaseStmt env' t' alts)
|
then (maybeCaseStmt env' t' alts)
|
||||||
else JSnoc (JConst nm t') (maybeCaseStmt env' (Var nm) alts)
|
else JSnoc (JConst nm t') (maybeCaseStmt env' (Var nm) alts)
|
||||||
|
|
||||||
where
|
where
|
||||||
termToJSAlt : JSEnv -> JSExp -> CAlt -> JAlt
|
termToJSAlt : JSEnv -> JSExp -> CAlt -> JAlt
|
||||||
termToJSAlt env nm (CConAlt name info args u) = JConAlt name (termToJS (mkEnv nm 0 env args) u f)
|
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" ::
|
"implements" :: "class" :: "let" :: "package" :: "private" :: "protected" :: "public" ::
|
||||||
"static" :: "yield" ::
|
"static" :: "yield" ::
|
||||||
"null" :: "true" :: "false" ::
|
"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)
|
"String" :: "Number" :: "Array" :: "BigInt" :: Nil)
|
||||||
|
|
||||||
|
|
||||||
@@ -251,17 +248,13 @@ jsIdent id = if elem id jsKeywords then text ("$" ++ id) else text $ pack $ fix
|
|||||||
else
|
else
|
||||||
'$' :: (toHex (cast x)) ++ fix xs
|
'$' :: (toHex (cast x)) ++ fix xs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stmtToDoc : ∀ e. JSStmt e -> Doc
|
stmtToDoc : ∀ e. JSStmt e -> Doc
|
||||||
|
|
||||||
|
|
||||||
expToDoc : JSExp -> Doc
|
expToDoc : JSExp -> Doc
|
||||||
expToDoc (LitArray xs) = fatalError "TODO - LitArray to doc"
|
expToDoc (LitArray xs) = fatalError "TODO - LitArray to doc"
|
||||||
expToDoc (LitObject xs) = text "{" <+> folddoc (\ a e => a ++ text ", " <+/> e) (map entry xs) <+> text "}"
|
expToDoc (LitObject xs) = text "{" <+> folddoc (\ a e => a ++ text ", " <+/> e) (map entry xs) <+> text "}"
|
||||||
where
|
where
|
||||||
entry : (String × JSExp) -> Doc
|
entry : (String × JSExp) -> Doc
|
||||||
-- TODO quote if needed
|
|
||||||
entry (nm, exp) = jsIdent nm ++ text ":" <+> expToDoc exp
|
entry (nm, exp) = jsIdent nm ++ text ":" <+> expToDoc exp
|
||||||
|
|
||||||
expToDoc (LitString str) = text $ quoteString str
|
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 : ∀ e. JSStmt e -> Doc
|
||||||
caseBody stmt@(JReturn x) = nest 2 (line ++ stmtToDoc stmt)
|
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 {e} stmt@(JCase _ _) = nest 2 (line ++ stmtToDoc stmt </> text "break;")
|
||||||
caseBody stmt = line ++ text "{" ++ nest 2 (line ++ stmtToDoc stmt </> text "break;") </> text "}"
|
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
|
let exec = stmtToDoc $ JPlain $ Apply (Var $ show name) Nil
|
||||||
pure $ reverse (exec :: tmp)
|
pure $ reverse (exec :: tmp)
|
||||||
Nothing =>
|
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"
|
error emptyFC "No main function found"
|
||||||
|
|||||||
@@ -809,7 +809,7 @@ checkCase ctx prob scnm scty (dcName, arity, ty) = do
|
|||||||
_ => pure True
|
_ => pure True
|
||||||
|
|
||||||
-- ok, so this is a single constructor, CaseAlt
|
-- ok, so this is a single constructor, CaseAlt
|
||||||
-- return Nothing if dcon doesn't unify with scrut
|
-- return Nothing if dcon type doesn't unify with scrut
|
||||||
buildCase : Context -> Problem -> String -> Val -> (QName × Int × Tm) -> M (Maybe CaseAlt)
|
buildCase : Context -> Problem -> String -> Val -> (QName × Int × Tm) -> M (Maybe CaseAlt)
|
||||||
buildCase ctx prob scnm scty (dcName, arity, ty) = do
|
buildCase ctx prob scnm scty (dcName, arity, ty) = do
|
||||||
debug $ \ _ => "CASE \{scnm} match \{show dcName} ty \{rpprint (names ctx) ty}"
|
debug $ \ _ => "CASE \{scnm} match \{show dcName} ty \{rpprint (names ctx) ty}"
|
||||||
|
|||||||
@@ -98,24 +98,26 @@ forceType env x = do
|
|||||||
| _ => pure x
|
| _ => pure x
|
||||||
forceType env x'
|
forceType env x'
|
||||||
|
|
||||||
|
-- for cases applied to a value
|
||||||
|
-- TODO this does not handle CaseLit
|
||||||
evalCase : Env -> Val -> List CaseAlt -> M (Maybe Val)
|
evalCase : Env -> Val -> List CaseAlt -> M (Maybe Val)
|
||||||
evalCase env sc@(VRef _ nm sp) (cc@(CaseCons name nms t) :: xs) = do
|
evalCase env sc@(VRef _ nm sp) (cc@(CaseCons name nms t) :: xs) = do
|
||||||
top <- getTop
|
top <- getTop
|
||||||
if nm == name
|
if nm == name
|
||||||
then do
|
then do
|
||||||
debug $ \ _ => "ECase \{show nm} \{show sp} \{show nms} \{showTm t}"
|
debug $ \ _ => "ECase \{show nm} \{show sp} \{show nms} \{showTm t}"
|
||||||
go env (sp <>> Nil) nms
|
pushArgs env (sp <>> Nil) nms
|
||||||
else case lookup nm top of
|
else case lookup nm top of
|
||||||
(Just (MkEntry _ str type (DCon _ k str1) _)) => evalCase env sc xs
|
(Just (MkEntry _ str type (DCon _ k str1) _)) => evalCase env sc xs
|
||||||
-- bail for a stuck function
|
-- bail for a stuck function
|
||||||
_ => pure Nothing
|
_ => pure Nothing
|
||||||
where
|
where
|
||||||
go : Env -> List Val -> List String -> M (Maybe Val)
|
pushArgs : Env -> List Val -> List String -> M (Maybe Val)
|
||||||
go env (arg :: args) (nm :: nms) = go (arg :: env) args nms
|
pushArgs env (arg :: args) (nm :: nms) = pushArgs (arg :: env) args nms
|
||||||
go env args Nil = do
|
pushArgs env args Nil = do
|
||||||
t' <- eval env t
|
t' <- eval env t
|
||||||
Just <$> vappSpine t' (Lin <>< args)
|
Just <$> vappSpine t' (Lin <>< args)
|
||||||
go env Nil rest = pure Nothing
|
pushArgs env Nil rest = pure Nothing
|
||||||
-- REVIEW - this is handled in the caller already
|
-- REVIEW - this is handled in the caller already
|
||||||
evalCase env sc@(VVar fc k sp) alts = case lookupVar env k of
|
evalCase env sc@(VVar fc k sp) alts = case lookupVar env k of
|
||||||
Just tt@(VVar fc' k' sp') => do
|
Just tt@(VVar fc' k' sp') => do
|
||||||
@@ -131,12 +133,19 @@ evalCase env sc@(VVar fc k sp) alts = case lookupVar env k of
|
|||||||
Nothing => do
|
Nothing => do
|
||||||
debug $ \ _ => "lookup \{show k} is Nothing in env \{show env}"
|
debug $ \ _ => "lookup \{show k} is Nothing in env \{show env}"
|
||||||
pure Nothing
|
pure Nothing
|
||||||
evalCase env sc (CaseDefault u :: xs) = Just <$> eval (sc :: env) u
|
evalCase env sc (CaseDefault u :: xs) = Just <$> eval env u
|
||||||
evalCase env sc cc = do
|
evalCase env sc cc = do
|
||||||
debug $ \ _ => "CASE BAIL sc \{show sc} vs " -- \{show cc}"
|
debug $ \ _ => "CASE BAIL sc \{show sc} vs " -- \{show cc}"
|
||||||
debug $ \ _ => "env is \{show env}"
|
debug $ \ _ => "env is \{show env}"
|
||||||
pure Nothing
|
pure Nothing
|
||||||
|
|
||||||
|
-- neutral alts
|
||||||
|
evalAlt : Env → CaseAlt → M VCaseAlt
|
||||||
|
evalAlt env (CaseDefault tm) = VCaseDefault <$> eval env tm
|
||||||
|
evalAlt env (CaseLit lit tm) = VCaseLit lit <$> eval env tm
|
||||||
|
-- in the cons case, we're binding args
|
||||||
|
evalAlt env (CaseCons nm args tm) = pure $ VCaseCons nm args env tm
|
||||||
|
|
||||||
-- So smalltt says:
|
-- So smalltt says:
|
||||||
-- Smalltt has the following approach:
|
-- Smalltt has the following approach:
|
||||||
-- - Top-level and local definitions are lazy.
|
-- - Top-level and local definitions are lazy.
|
||||||
@@ -146,7 +155,6 @@ evalCase env sc cc = do
|
|||||||
|
|
||||||
-- TODO maybe add glueing
|
-- TODO maybe add glueing
|
||||||
|
|
||||||
|
|
||||||
eval env (Ref fc x) = pure $ VRef fc x Lin
|
eval env (Ref fc x) = pure $ VRef fc x Lin
|
||||||
eval env (App _ t u) = do
|
eval env (App _ t u) = do
|
||||||
t' <- eval env t
|
t' <- eval env t
|
||||||
@@ -165,7 +173,7 @@ eval env (Pi fc x icit rig a b) = do
|
|||||||
pure $ VPi fc x icit rig a' (MkClosure env b)
|
pure $ VPi fc x icit rig a' (MkClosure env b)
|
||||||
eval env (Let fc nm t u) = do
|
eval env (Let fc nm t u) = do
|
||||||
t' <- eval env t
|
t' <- eval env t
|
||||||
u' <- eval (VVar fc (cast $ length env) Lin :: env) u
|
u' <- eval (VVar fc (length' env) Lin :: env) u
|
||||||
pure $ VLet fc nm t' u'
|
pure $ VLet fc nm t' u'
|
||||||
eval env (LetRec fc nm ty t u) = do
|
eval env (LetRec fc nm ty t u) = do
|
||||||
ty' <- eval env ty
|
ty' <- eval env ty
|
||||||
@@ -184,10 +192,14 @@ eval env tm@(Case fc sc alts) = do
|
|||||||
-- TODO we need to be able to tell eval to expand aggressively here.
|
-- TODO we need to be able to tell eval to expand aggressively here.
|
||||||
sc' <- eval env sc
|
sc' <- eval env sc
|
||||||
sc' <- unlet env sc' -- try to expand lets from pattern matching
|
sc' <- unlet env sc' -- try to expand lets from pattern matching
|
||||||
|
-- possibly too aggressive?
|
||||||
sc' <- forceType env sc'
|
sc' <- forceType env sc'
|
||||||
|
Nothing <- evalCase env sc' alts
|
||||||
|
| Just v => pure v
|
||||||
|
|
||||||
vsc <- eval env sc
|
vsc <- eval env sc
|
||||||
vcase <- evalCase env sc' alts
|
alts' <- traverse (evalAlt env) alts
|
||||||
pure $ fromMaybe (VCase fc vsc alts) vcase
|
pure $ VCase fc vsc alts'
|
||||||
|
|
||||||
quote : (lvl : Int) -> Val -> M Tm
|
quote : (lvl : Int) -> Val -> M Tm
|
||||||
|
|
||||||
@@ -198,6 +210,18 @@ quoteSp lvl t (xs :< x) = do
|
|||||||
x' <- quote lvl x
|
x' <- quote lvl x
|
||||||
pure $ App emptyFC t' x'
|
pure $ App emptyFC t' x'
|
||||||
|
|
||||||
|
quoteAlt : Int → VCaseAlt → M CaseAlt
|
||||||
|
quoteAlt l (VCaseDefault val) = CaseDefault <$> quote l val
|
||||||
|
quoteAlt l (VCaseLit lit val) = CaseLit lit <$> quote l val
|
||||||
|
quoteAlt l (VCaseCons nm args env tm) = do
|
||||||
|
val <- eval (mkenv l env args) tm
|
||||||
|
tm <- quote (length' args + l) val
|
||||||
|
pure $ CaseCons nm args tm
|
||||||
|
where
|
||||||
|
mkenv : Int → Env → List String → Env
|
||||||
|
mkenv l env Nil = env
|
||||||
|
mkenv l env (n :: ns) = mkenv (l + 1) (VVar emptyFC l Lin :: env) ns
|
||||||
|
|
||||||
quote l (VVar fc k sp) = if k < l
|
quote l (VVar fc k sp) = if k < l
|
||||||
then quoteSp l (Bnd fc (lvl2ix l k )) sp -- level to index
|
then quoteSp l (Bnd fc (lvl2ix l k )) sp -- level to index
|
||||||
else error fc "Bad index in quote \{show k} depth \{show l}"
|
else error fc "Bad index in quote \{show k} depth \{show l}"
|
||||||
@@ -226,8 +250,9 @@ quote l (VLetRec fc nm ty t u) = do
|
|||||||
pure $ LetRec fc nm ty' t' u'
|
pure $ LetRec fc nm ty' t' u'
|
||||||
quote l (VU fc) = pure (UU fc)
|
quote l (VU fc) = pure (UU fc)
|
||||||
quote l (VRef fc n sp) = quoteSp l (Ref fc n) sp
|
quote l (VRef fc n sp) = quoteSp l (Ref fc n) sp
|
||||||
quote l (VCase fc sc alts) = do
|
quote l (VCase fc sc valts) = do
|
||||||
sc' <- quote l sc
|
sc' <- quote l sc
|
||||||
|
alts <- traverse (quoteAlt l) valts
|
||||||
pure $ Case fc sc' alts
|
pure $ Case fc sc' alts
|
||||||
quote l (VLit fc lit) = pure $ Lit fc lit
|
quote l (VLit fc lit) = pure $ Lit fc lit
|
||||||
quote l (VErased fc) = pure $ Erased fc
|
quote l (VErased fc) = pure $ Erased fc
|
||||||
@@ -312,6 +337,7 @@ zonkApp top l env t sp = do
|
|||||||
zonk top l env t')
|
zonk top l env t')
|
||||||
(\_ => pure $ appSpine t' sp)
|
(\_ => pure $ appSpine t' sp)
|
||||||
where
|
where
|
||||||
|
-- lookup name and return Def if flagged inline
|
||||||
inlineDef : Tm → Maybe Tm
|
inlineDef : Tm → Maybe Tm
|
||||||
inlineDef (Ref _ nm) = case lookup nm top of
|
inlineDef (Ref _ nm) = case lookup nm top of
|
||||||
Just (MkEntry _ _ ty (Fn tm) flags) => if elem Inline flags then Just tm else Nothing
|
Just (MkEntry _ _ ty (Fn tm) flags) => if elem Inline flags then Just tm else Nothing
|
||||||
@@ -327,16 +353,20 @@ zonkAlt top l env (CaseCons name args t) = CaseCons name args <$> go l env args
|
|||||||
go l env Nil tm = zonk top l env t
|
go l env Nil tm = zonk top l env t
|
||||||
go l env (x :: xs) tm = go (1 + l) (VVar (getFC tm) l Lin :: env) xs tm
|
go l env (x :: xs) tm = go (1 + l) (VVar (getFC tm) l Lin :: env) xs tm
|
||||||
|
|
||||||
zonk top l env t = case t of
|
zonk top l env t =
|
||||||
|
let env' = VVar emptyFC l Lin :: env in
|
||||||
|
case t of
|
||||||
(Meta fc k) => zonkApp top l env t Nil
|
(Meta fc k) => zonkApp top l env t Nil
|
||||||
(Lam fc nm icit rig u) => Lam fc nm icit rig <$> (zonk top (1 + l) (VVar fc l Lin :: env) u)
|
(Lam fc nm icit rig u) => Lam fc nm icit rig <$> (zonk top (1 + l) env' u)
|
||||||
(App fc t u) => do
|
(App fc _ _) => zonkApp top l env t Nil
|
||||||
u' <- zonk top l env u
|
(Pi fc nm icit rig a b) => Pi fc nm icit rig <$> zonk top l env a <*> zonkBind top (l + 1) env' b
|
||||||
zonkApp top l env t (u' :: Nil)
|
(Let fc nm t u) => Let fc nm <$> zonk top l env t <*> zonkBind top (l + 1) env' u
|
||||||
(Pi fc nm icit rig a b) => Pi fc nm icit rig <$> zonk top l env a <*> zonkBind top l env b
|
(LetRec fc nm ty t u) => LetRec fc nm <$> zonk top l env ty <*> zonkBind top (l + 1) env' t <*> zonkBind top (l + 1) env' u
|
||||||
(Let fc nm t u) => Let fc nm <$> zonk top l env t <*> zonkBind top l env u
|
(Case fc sc alts) => do
|
||||||
(LetRec fc nm ty t u) => LetRec fc nm <$> zonk top l env ty <*> zonkBind top l env t <*> zonkBind top l env u
|
sc' <- zonk top l env sc
|
||||||
(Case fc sc alts) => Case fc <$> zonk top l env sc <*> traverse (zonkAlt top l env) alts
|
alts' <- traverse (zonkAlt top l env) alts
|
||||||
|
pure $ Case fc sc' alts'
|
||||||
|
|
||||||
UU fc => pure $ UU fc
|
UU fc => pure $ UU fc
|
||||||
Lit fc lit => pure $ Lit fc lit
|
Lit fc lit => pure $ Lit fc lit
|
||||||
Bnd fc ix => pure $ Bnd fc ix
|
Bnd fc ix => pure $ Bnd fc ix
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ complexity (Ref _ _) = 1
|
|||||||
complexity (Lam _ _ _ _ sc) = 1 + complexity sc
|
complexity (Lam _ _ _ _ sc) = 1 + complexity sc
|
||||||
complexity (App _ t u) = complexity t + complexity u
|
complexity (App _ t u) = complexity t + complexity u
|
||||||
complexity (Bnd _ _) = 1
|
complexity (Bnd _ _) = 1
|
||||||
|
-- These turn into a projection
|
||||||
|
complexity (Case _ sc (CaseCons _ _ t :: Nil)) = 1 + complexity sc + complexity t
|
||||||
complexity _ = 100
|
complexity _ = 100
|
||||||
|
|
||||||
processDef : List String → FC → String → List (Raw × Raw) → M Unit
|
processDef : List String → FC → String → List (Raw × Raw) → M Unit
|
||||||
@@ -168,12 +170,18 @@ processDef ns fc nm clauses = do
|
|||||||
-- TODO - make nf that expands all metas and drop zonk
|
-- TODO - make nf that expands all metas and drop zonk
|
||||||
-- Idris2 doesn't expand metas for performance - a lot of these are dropped during erasure.
|
-- Idris2 doesn't expand metas for performance - a lot of these are dropped during erasure.
|
||||||
-- Day1.newt is a test case
|
-- Day1.newt is a test case
|
||||||
-- NOW - might not need this if we do it at compile time
|
-- This inlines metas and functions flagged Inline.
|
||||||
tm' <- zonk top 0 Nil tm
|
tm' <- zonk top 0 Nil tm
|
||||||
debug $ \ _ => "NF\n\{render 80 $ pprint Nil tm'}"
|
debug $ \ _ => "NF\n\{render 80 $ pprint Nil tm'}"
|
||||||
debug $ \ _ => "Add def \{nm} \{render 90 $ pprint Nil tm'} : \{render 90 $ pprint Nil ty}"
|
debug $ \ _ => "Add def \{nm} \{render 90 $ pprint Nil tm'} : \{render 90 $ pprint Nil ty}"
|
||||||
updateDef (QN ns nm) fc ty (Fn tm')
|
updateDef (QN ns nm) fc ty (Fn tm')
|
||||||
if complexity tm' < 10
|
-- putStrLn "complexity \{show (QN ns nm)} \{show $ complexity tm'}"
|
||||||
|
-- putStrLn $ show tm'
|
||||||
|
-- TODO we need some protection against inlining a function calling itself.
|
||||||
|
-- 14 gets us to 6.21s, higher than 11 breaks Zoo4eg.newt with a unification error (probably need to inline at the end instead)
|
||||||
|
-- But we need better heuristics, maybe fuel and deciding while inlining.
|
||||||
|
-- bind is explicit here because the complexity has a 100 in it.
|
||||||
|
if complexity tm' < 11 || show (QN ns nm) == "Prelude.Prelude.Monad Prelude.IO,bind"
|
||||||
then setFlag (QN ns nm) fc Inline
|
then setFlag (QN ns nm) fc Inline
|
||||||
else pure MkUnit
|
else pure MkUnit
|
||||||
|
|
||||||
|
|||||||
@@ -213,13 +213,24 @@ Val : U
|
|||||||
-- Yaffle is vars -> vars here
|
-- Yaffle is vars -> vars here
|
||||||
|
|
||||||
Closure : U
|
Closure : U
|
||||||
|
Env : U
|
||||||
|
|
||||||
|
data VCaseAlt : U where
|
||||||
|
-- Like a Closure, but with a lot of args
|
||||||
|
VCaseCons : (name : QName) -> (args : List String) -> Env -> Tm -> VCaseAlt
|
||||||
|
VCaseLit : Literal -> Val -> VCaseAlt
|
||||||
|
VCaseDefault : Val -> VCaseAlt
|
||||||
|
-- VCaseCons : (name : QName) -> (args : List String) -> Tm -> VCaseAlt
|
||||||
|
-- VCaseLit : Literal -> Tm -> VCaseAlt
|
||||||
|
-- VCaseDefault : Tm -> VCaseAlt
|
||||||
|
|
||||||
|
|
||||||
data Val : U where
|
data Val : U where
|
||||||
-- This will be local / flex with spine.
|
-- This will be local / flex with spine.
|
||||||
VVar : FC -> (k : Int) -> (sp : SnocList Val) -> Val
|
VVar : FC -> (k : Int) -> (sp : SnocList Val) -> Val
|
||||||
VRef : FC -> (nm : QName) -> (sp : SnocList Val) -> Val
|
VRef : FC -> (nm : QName) -> (sp : SnocList Val) -> Val
|
||||||
-- neutral case
|
-- neutral case
|
||||||
VCase : FC -> (sc : Val) -> List CaseAlt -> Val
|
VCase : FC -> (sc : Val) -> List VCaseAlt -> Val
|
||||||
-- we'll need to look this up in ctx with IO
|
-- we'll need to look this up in ctx with IO
|
||||||
VMeta : FC -> QName -> (sp : SnocList Val) -> Val
|
VMeta : FC -> QName -> (sp : SnocList Val) -> Val
|
||||||
VLam : FC -> Name -> Icit -> Quant -> Closure -> Val
|
VLam : FC -> Name -> Icit -> Quant -> Closure -> Val
|
||||||
@@ -230,7 +241,7 @@ data Val : U where
|
|||||||
VErased : FC -> Val
|
VErased : FC -> Val
|
||||||
VLit : FC -> Literal -> Val
|
VLit : FC -> Literal -> Val
|
||||||
|
|
||||||
Env : U
|
|
||||||
Env = List Val
|
Env = List Val
|
||||||
|
|
||||||
data Closure = MkClosure Env Tm
|
data Closure = MkClosure Env Tm
|
||||||
@@ -262,7 +273,12 @@ instance Show Val where
|
|||||||
show (VPi fc str Implicit rig x y) = "(%pi {\{show rig} \{str} : \{show x}}. \{showClosure y})"
|
show (VPi fc str Implicit rig x y) = "(%pi {\{show rig} \{str} : \{show x}}. \{showClosure y})"
|
||||||
show (VPi fc str Explicit rig x y) = "(%pi (\{show rig} \{str} : \{show x}). \{showClosure y})"
|
show (VPi fc str Explicit rig x y) = "(%pi (\{show rig} \{str} : \{show x}). \{showClosure y})"
|
||||||
show (VPi fc str Auto rig x y) = "(%pi {{\{show rig} \{str} : \{show x}}}. \{showClosure y})"
|
show (VPi fc str Auto rig x y) = "(%pi {{\{show rig} \{str} : \{show x}}}. \{showClosure y})"
|
||||||
show (VCase fc sc alts) = "(%case \{show sc} ...)"
|
show (VCase fc sc alts) = "(%case \{show sc} \{unwords $ map showAlt alts})"
|
||||||
|
where
|
||||||
|
showAlt : VCaseAlt → String
|
||||||
|
showAlt (VCaseDefault v) = "(%cdef \{show v})"
|
||||||
|
showAlt (VCaseLit lit v) = "(%clit \{show v})"
|
||||||
|
showAlt (VCaseCons nm args env v) = "(%ccon \{show nm} \{unwords $ map show args} [\{show $ length env} env] \{show v}"
|
||||||
show (VU _) = "U"
|
show (VU _) = "U"
|
||||||
show (VLit _ lit) = show lit
|
show (VLit _ lit) = show lit
|
||||||
show (VLet _ nm a b) = "(%let \{show nm} = \{show a} in \{show b}"
|
show (VLet _ nm a b) = "(%let \{show nm} = \{show a} in \{show b}"
|
||||||
|
|||||||
Reference in New Issue
Block a user