on master help sign in
Added WHNF module
64df5f6Edwin Brady
idris.cabal+1
@@ -785,6 +785,7 @@ Library
785 , Idris.Core.TT
785 , Idris.Core.TT
786 , Idris.Core.Typecheck
786 , Idris.Core.Typecheck
787 , Idris.Core.Unify
787 , Idris.Core.Unify
788+ , Idris.Core.WHNF
788
789
789 , Idris.Elab.Utils
790 , Idris.Elab.Utils
790 , Idris.Elab.Type
791 , Idris.Elab.Type
src/Idris/AbsSyntaxTree.hs+1−1
@@ -387,7 +387,7 @@ data Command = Quit
387 | Universes
387 | Universes
388 | LogLvl Int
388 | LogLvl Int
389 | Spec PTerm
389 | Spec PTerm
390− | HNF PTerm
390+ | WHNF PTerm
391 | TestInline PTerm
391 | TestInline PTerm
392 | Defn Name
392 | Defn Name
393 | Missing Name
393 | Missing Name
src/Idris/Core/Evaluate.hs+1−1
@@ -13,7 +13,7 @@ module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC, normaliseAll,
13 lookupP, lookupP_all, lookupDef, lookupNameDef, lookupDefExact, lookupDefAcc, lookupDefAccExact, lookupVal,
13 lookupP, lookupP_all, lookupDef, lookupNameDef, lookupDefExact, lookupDefAcc, lookupDefAccExact, lookupVal,
14 mapDefCtxt,
14 mapDefCtxt,
15 lookupTotal, lookupNameTotal, lookupMetaInformation, lookupTyEnv, isTCDict, isDConName, canBeDConName, isTConName, isConName, isFnName,
15 lookupTotal, lookupNameTotal, lookupMetaInformation, lookupTyEnv, isTCDict, isDConName, canBeDConName, isTConName, isConName, isFnName,
16− Value(..), Quote(..), initEval, uniqueNameCtxt, uniqueBindersCtxt, definitions,
16+ Value(..), initEval, uniqueNameCtxt, uniqueBindersCtxt, definitions,
17 isUniverse) where
17 isUniverse) where
18
18
19import Debug.Trace
19import Debug.Trace
src/Idris/Core/TT.hs+1−1
@@ -41,7 +41,7 @@ module Idris.Core.TT(AppStatus(..), ArithTy(..), Binder(..), Const(..), Ctxt(..)
41 sInstanceN, sMN, sNS, spanFC, str, subst, substNames, substTerm,
41 sInstanceN, sMN, sNS, spanFC, str, subst, substNames, substTerm,
42 substV, sUN, tcname, termSmallerThan, tfail, thead, tnull,
42 substV, sUN, tcname, termSmallerThan, tfail, thead, tnull,
43 toAlist, traceWhen, txt, unApply, uniqueBinders, uniqueName,
43 toAlist, traceWhen, txt, unApply, uniqueBinders, uniqueName,
44− uniqueNameFrom, uniqueNameSet, unList, updateDef, vToP) where
44+ uniqueNameFrom, uniqueNameSet, unList, updateDef, vToP, weakenTm) where
45
45
46-- Work around AMP without CPP
46-- Work around AMP without CPP
47import Prelude (Eq(..), Show(..), Ord(..), Functor(..), Monad(..), String, Int,
47import Prelude (Eq(..), Show(..), Ord(..), Functor(..), Monad(..), String, Int,
src/Idris/Core/WHNF.hsnew file+109
@@ -0,0 +1,109 @@
1+{-# LANGUAGE PatternGuards #-}
2+{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
3+
4+-- Reduction to Weak Head Normal Form
5+module Idris.Core.WHNF(whnf, WEnv) where
6+
7+import Idris.Core.TT
8+import Idris.Core.CaseTree
9+import Idris.Core.Evaluate
10+
11+-- A stack entry consists of a term and the environment it is to be
12+-- evaluated in (i.e. it's a thunk)
13+type StackEntry = (Term, WEnv)
14+data WEnv = WEnv Int -- number of free variables
15+ [(Term, WEnv)]
16+
17+type Stack = [StackEntry]
18+
19+-- A WHNF is a top level term evaluated in the empty environment. It is
20+-- always headed by either an irreducible expression, i.e. a constructor,
21+-- a lambda, a constant, or a postulate
22+
23+-- Every 'Term' or 'Type' in this structure is associated with the
24+-- environment it was encountered in, so that when we quote back to a term
25+-- we get the substitutions right.
26+
27+data WHNF = WDCon Int Int Bool Name (Type, WEnv) -- data constructor
28+ | WTCon Int Int Name (Type, WEnv) -- type constructor
29+ | WPRef Name (Type, WEnv) -- irreducible global (e.g. a postulate)
30+ | WBind Name (Binder Term) (Term, WEnv)
31+ | WApp WHNF (Term, WEnv)
32+ | WConstant Const
33+ | WProj WHNF Int
34+ | WType UExp
35+ | WUType Universe
36+ | WErased
37+ | WImpossible
38+
39+-- Reduce a *closed* term to weak head normal form.
40+whnf :: Context -> Term -> Term
41+whnf ctxt tm = quote (do_whnf ctxt (WEnv 0 []) tm)
42+
43+do_whnf :: Context -> WEnv -> Term -> WHNF
44+do_whnf ctxt env tm = eval env [] tm
45+ where
46+ eval :: WEnv -> Stack -> Term -> WHNF
47+ eval wenv@(WEnv d env) stk (V i)
48+ | i < length env = let (tm, env') = env !! i in
49+ eval env' stk tm
50+ | otherwise = error "Can't happen: WHNF scope error"
51+ eval wenv@(WEnv d env) stk (Bind n (Let t v) sc)
52+ = eval (WEnv d ((v, wenv) : env)) stk sc
53+ eval (WEnv d env) [] (Bind n b sc) = WBind n b (sc, WEnv (d + 1) env)
54+ eval (WEnv d env) ((tm, tenv) : stk) (Bind n b sc)
55+ = eval (WEnv d ((tm, tenv) : env)) stk sc
56+
57+ eval env stk (P nt n ty) = apply env nt n ty stk
58+ eval env stk (App _ f a) = eval env ((a, env) : stk) f
59+ eval env stk (Constant c) = unload (WConstant c) stk
60+
61+ -- Should never happen in compile time code (for now...)
62+ eval env stk (Proj tm i) = unload (WProj (eval env [] tm) i) stk
63+
64+ eval env stk Erased = unload WErased stk
65+ eval env stk Impossible = unload WImpossible stk
66+ eval env stk (TType u) = unload (WType u) stk
67+ eval env stk (UType u) = unload (WUType u) stk
68+
69+ apply :: WEnv -> NameType -> Name -> Type -> Stack -> WHNF
70+ apply env nt n ty stk
71+ = let wp = case nt of
72+ DCon t a u -> WDCon t a u n (ty, env)
73+ TCon t a -> WTCon t a n (ty, env)
74+ _ -> WPRef n (ty, env)
75+ in
76+ unload wp stk
77+
78+ unload :: WHNF -> Stack -> WHNF
79+ unload f [] = f
80+ unload f (a : as) = unload (WApp f a) as
81+
82+quote :: WHNF -> Term
83+quote (WDCon t a u n (ty, env)) = P (DCon t a u) n (quoteEnv env ty)
84+quote (WTCon t a n (ty, env)) = P (TCon t a) n (quoteEnv env ty)
85+quote (WPRef n (ty, env)) = P Ref n (quoteEnv env ty)
86+quote (WBind n ty (sc, env)) = Bind n ty (quoteEnv env sc)
87+quote (WApp f (a, env)) = App Complete (quote f) (quoteEnv env a)
88+quote (WConstant c) = Constant c
89+quote (WProj t i) = Proj (quote t) i
90+quote (WType u) = TType u
91+quote (WUType u) = UType u
92+quote WErased = Erased
93+quote WImpossible = Impossible
94+
95+quoteEnv :: WEnv -> Term -> Term
96+quoteEnv (WEnv d ws) tm = qe' d ws tm
97+ where
98+ qe' d ts (V i)
99+ | i < d = V i
100+ | otherwise = let (tm, env) = ts !! (i - d) in
101+ quoteEnv env tm
102+ qe' d ts (Bind n b sc)
103+ = Bind n (fmap (qe' d ts) b) (qe' (d + 1) ts sc)
104+ qe' d ts (App c f a)
105+ = App c (qe' d ts f) (qe' d ts a)
106+ qe' d ts (P nt n ty) = P nt n (qe' d ts ty)
107+ qe' d ts (Proj tm i) = Proj (qe' d ts tm) i
108+ qe' d ts tm = tm
109+
src/Idris/REPL.hs+4−3
@@ -54,6 +54,7 @@ import Idris.Core.Evaluate
54import Idris.Core.Execute (execute)
54import Idris.Core.Execute (execute)
55import Idris.Core.TT
55import Idris.Core.TT
56import Idris.Core.Unify
56import Idris.Core.Unify
57+import Idris.Core.WHNF
57import Idris.Core.Constraints
58import Idris.Core.Constraints
58
59
59import IRTS.Compiler
60import IRTS.Compiler
@@ -595,7 +596,7 @@ idemodeProcess fn (Search ps t) = process fn (Search ps t)
595idemodeProcess fn (Spec t) = process fn (Spec t)
596idemodeProcess fn (Spec t) = process fn (Spec t)
596-- RmProof and AddProof not supported!
597-- RmProof and AddProof not supported!
597idemodeProcess fn (ShowProof n') = process fn (ShowProof n')
598idemodeProcess fn (ShowProof n') = process fn (ShowProof n')
598−idemodeProcess fn (HNF t) = process fn (HNF t)
599+idemodeProcess fn (WHNF t) = process fn (WHNF t)
599--idemodeProcess fn TTShell = process fn TTShell -- need some prove mode!
600--idemodeProcess fn TTShell = process fn TTShell -- need some prove mode!
600idemodeProcess fn (TestInline t) = process fn (TestInline t)
601idemodeProcess fn (TestInline t) = process fn (TestInline t)
601
602
@@ -1135,11 +1136,11 @@ process fn (Prove mode n')
1135 mapM_ checkDeclTotality (idris_totcheck i)
1136 mapM_ checkDeclTotality (idris_totcheck i)
1136 warnTotality
1137 warnTotality
1137
1138
1138−process fn (HNF t)
1139+process fn (WHNF t)
1139 = do (tm, ty) <- elabVal recinfo ERHS t
1140 = do (tm, ty) <- elabVal recinfo ERHS t
1140 ctxt <- getContext
1141 ctxt <- getContext
1141 ist <- getIState
1142 ist <- getIState
1142− let tm' = hnf ctxt [] tm
1143+ let tm' = whnf ctxt tm
1143 iPrintResult (show (delab ist tm'))
1144 iPrintResult (show (delab ist tm'))
1144process fn (TestInline t)
1145process fn (TestInline t)
1145 = do (tm, ty) <- elabVal recinfo ERHS t
1146 = do (tm, ty) <- elabVal recinfo ERHS t
src/Idris/REPLParser.hs+1−1
@@ -111,7 +111,7 @@ parserCommands =
111
111
112 , exprArgCmd ["patt"] Pattelab "(Debugging) Elaborate pattern expression"
112 , exprArgCmd ["patt"] Pattelab "(Debugging) Elaborate pattern expression"
113 , exprArgCmd ["spec"] Spec "?"
113 , exprArgCmd ["spec"] Spec "?"
114− , exprArgCmd ["hnf"] HNF "?"
114+ , exprArgCmd ["whnf"] WHNF "(Debugging) Show weak head normal form of an expression"
115 , exprArgCmd ["inline"] TestInline "?"
115 , exprArgCmd ["inline"] TestInline "?"
116 , proofArgCmd ["cs", "casesplit"] CaseSplitAt
116 , proofArgCmd ["cs", "casesplit"] CaseSplitAt
117 ":cs <line> <name> splits the pattern variable on the line"
117 ":cs <line> <name> splits the pattern variable on the line"