on master help sign in
Added WHNF module

Reduction to weak head normal form. Currently includes structure of the algorithm, but does not yet reduce function names. Also removed ':hnf' from REPL commands and replaced with ':whnf'.

commit64df5f649b97160b5741d2b8b609a3cfcbcb91b2 authorEdwin Brady <ecb10@st-andrews.ac.uk> dateThu 23 Jul 2015, 10:39 (11 years ago) parent570a452
7 files changed+118−7
idris.cabal+1 src/Idris/AbsSyntaxTree.hs+1−1 src/Idris/Core/Evaluate.hs+1−1 src/Idris/Core/TT.hs+1−1 src/Idris/Core/WHNF.hs+109 src/Idris/REPL.hs+4−3 src/Idris/REPLParser.hs+1−1
idris.cabal+1
@@ -785,6 +785,7 @@ Library
785785 , Idris.Core.TT
786786 , Idris.Core.Typecheck
787787 , Idris.Core.Unify
788+ , Idris.Core.WHNF
788789
789790 , Idris.Elab.Utils
790791 , Idris.Elab.Type
src/Idris/AbsSyntaxTree.hs+1−1
@@ -387,7 +387,7 @@ data Command = Quit
387387 | Universes
388388 | LogLvl Int
389389 | Spec PTerm
390− | HNF PTerm
390+ | WHNF PTerm
391391 | TestInline PTerm
392392 | Defn Name
393393 | Missing Name
src/Idris/Core/Evaluate.hs+1−1
@@ -13,7 +13,7 @@ module Idris.Core.Evaluate(normalise, normaliseTrace, normaliseC, normaliseAll,
1313 lookupP, lookupP_all, lookupDef, lookupNameDef, lookupDefExact, lookupDefAcc, lookupDefAccExact, lookupVal,
1414 mapDefCtxt,
1515 lookupTotal, lookupNameTotal, lookupMetaInformation, lookupTyEnv, isTCDict, isDConName, canBeDConName, isTConName, isConName, isFnName,
16− Value(..), Quote(..), initEval, uniqueNameCtxt, uniqueBindersCtxt, definitions,
16+ Value(..), initEval, uniqueNameCtxt, uniqueBindersCtxt, definitions,
1717 isUniverse) where
1818
1919import Debug.Trace
src/Idris/Core/TT.hs+1−1
@@ -41,7 +41,7 @@ module Idris.Core.TT(AppStatus(..), ArithTy(..), Binder(..), Const(..), Ctxt(..)
4141 sInstanceN, sMN, sNS, spanFC, str, subst, substNames, substTerm,
4242 substV, sUN, tcname, termSmallerThan, tfail, thead, tnull,
4343 toAlist, traceWhen, txt, unApply, uniqueBinders, uniqueName,
44− uniqueNameFrom, uniqueNameSet, unList, updateDef, vToP) where
44+ uniqueNameFrom, uniqueNameSet, unList, updateDef, vToP, weakenTm) where
4545
4646-- Work around AMP without CPP
4747import 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
5454import Idris.Core.Execute (execute)
5555import Idris.Core.TT
5656import Idris.Core.Unify
57+import Idris.Core.WHNF
5758import Idris.Core.Constraints
5859
5960import IRTS.Compiler
@@ -595,7 +596,7 @@ idemodeProcess fn (Search ps t) = process fn (Search ps t)
595596idemodeProcess fn (Spec t) = process fn (Spec t)
596597-- RmProof and AddProof not supported!
597598idemodeProcess 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)
599600--idemodeProcess fn TTShell = process fn TTShell -- need some prove mode!
600601idemodeProcess fn (TestInline t) = process fn (TestInline t)
601602
@@ -1135,11 +1136,11 @@ process fn (Prove mode n')
11351136 mapM_ checkDeclTotality (idris_totcheck i)
11361137 warnTotality
11371138
1138−process fn (HNF t)
1139+process fn (WHNF t)
11391140 = do (tm, ty) <- elabVal recinfo ERHS t
11401141 ctxt <- getContext
11411142 ist <- getIState
1142− let tm' = hnf ctxt [] tm
1143+ let tm' = whnf ctxt tm
11431144 iPrintResult (show (delab ist tm'))
11441145process fn (TestInline t)
11451146 = do (tm, ty) <- elabVal recinfo ERHS t
src/Idris/REPLParser.hs+1−1
@@ -111,7 +111,7 @@ parserCommands =
111111
112112 , exprArgCmd ["patt"] Pattelab "(Debugging) Elaborate pattern expression"
113113 , exprArgCmd ["spec"] Spec "?"
114− , exprArgCmd ["hnf"] HNF "?"
114+ , exprArgCmd ["whnf"] WHNF "(Debugging) Show weak head normal form of an expression"
115115 , exprArgCmd ["inline"] TestInline "?"
116116 , proofArgCmd ["cs", "casesplit"] CaseSplitAt
117117 ":cs <line> <name> splits the pattern variable on the line"