@@ -11,6 +11,7 @@ import Data.List
1111data DExp = DV LVar
1212 | DApp Bool Name [DExp] -- True = tail call
1313 | DLet Name DExp DExp -- name just for pretty printing
14+ | DUpdate Name DExp -- eval expression, then update var with it
1415 | DProj DExp Int
1516 | DC Int Name [DExp]
1617 | DCase DExp [DAlt]
@@ -87,6 +88,8 @@ addApps defs (n, LFun _ args e) = (n, DFun n args (aa args e))
8788 aa env (LForce e) = eEVAL (aa env e)
8889 aa env (LLet n v sc) = DLet n (aa env v) (aa (n : env) sc)
8990 aa env (LCon i n args) = DC i n (map (aa env) args)
91+ aa env (LProj t@(LV (Glob n)) i)
92+ = DProj (DUpdate n (eEVAL (aa env t))) i
9093 aa env (LProj t i) = DProj (eEVAL (aa env t)) i
9194 aa env (LCase e alts) = DCase (eEVAL (aa env e)) (map (aaAlt env) alts)
9295 aa env (LConst c) = DConst c
@@ -115,11 +118,33 @@ addApps defs (n, LFun _ args e) = (n, DFun n args (aa args e))
115118 chainAPPLY f [] = f
116119 chainAPPLY f (a : as) = chainAPPLY (DApp False (MN 0 "APPLY") [f, a]) as
117120
121+ -- if anything in the DExp is projected from, we'll need to evaluate it,
122+ -- but we only want to do it once, rather than every time we project.
123+
124+ preEval [] t = t
125+ preEval (x : xs) t
126+ | needsEval x t = DLet x (eEVAL (DV (Glob x))) (preEval xs t)
127+ | otherwise = preEval xs t
128+
129+ needsEval x (DApp _ _ args) = or (map (needsEval x) args)
130+ needsEval x (DC _ _ args) = or (map (needsEval x) args)
131+ needsEval x (DCase e alts) = needsEval x e || or (map nec alts)
132+ where nec (DConCase _ _ _ e) = needsEval x e
133+ nec (DConstCase _ e) = needsEval x e
134+ nec (DDefaultCase e) = needsEval x e
135+ needsEval x (DLet n v e)
136+ | x == n = needsEval x v
137+ | otherwise = needsEval x v || needsEval x e
138+ needsEval x (DForeign _ _ _ args) = or (map (needsEval x) (map snd args))
139+ needsEval x (DOp op args) = or (map (needsEval x) args)
140+ needsEval x (DProj (DV (Glob x')) _) = x == x'
141+ needsEval x _ = False
142+
118143eEVAL x = DApp False (MN 0 "EVAL") [x]
119144
120−data EvalApply a = EvalCase a
145+data EvalApply a = EvalCase (Name -> a)
121146 | ApplyCase a
122− deriving Show
147+-- deriving Show
123148
124149-- For a function name, generate a list of
125150-- data constuctors, and whether to handle them in EVAL or APPLY
@@ -127,26 +152,29 @@ data EvalApply a = EvalCase a
127152toCons :: (Name, Int) -> [(Name, Int, EvalApply DAlt)]
128153toCons (n, i)
129154 = (mkFnCon n, i,
130− EvalCase (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
131− (eEVAL (DApp False n (map (DV . Glob) (take i (genArgs 0)))))))
132− : mkApplyCase n 0 i
155+ EvalCase (\tlarg ->
156+ (DConCase (-1) (mkFnCon n) (take i (genArgs 0))
157+ (dupdate tlarg
158+ (eEVAL (DApp False n (map (DV . Glob) (take i (genArgs 0)))))))))
159+ : mkApplyCase n 0 i
160+ where dupdate tlarg x = x
133161
134162mkApplyCase fname n ar | n == ar = []
135163mkApplyCase fname n ar
136164 = let nm = mkUnderCon fname (ar - n) in
137165 (nm, n, ApplyCase (DConCase (-1) nm (take n (genArgs 0))
138− (DApp False (mkUnderCon fname (ar - (n + 1)))
139− (map (DV . Glob) (take n (genArgs 0) ++
140− [MN 0 "arg"])))))
166+ (DApp False (mkUnderCon fname (ar - (n + 1)))
167+ (map (DV . Glob) (take n (genArgs 0) ++
168+ [MN 0 "arg"])))))
141169 : mkApplyCase fname (n + 1) ar
142170
143171mkEval :: [(Name, Int, EvalApply DAlt)] -> (Name, DDecl)
144172mkEval xs = (MN 0 "EVAL", DFun (MN 0 "EVAL") [MN 0 "arg"]
145− (mkBigCase (MN 0 "EVAL") 256 (DV (Glob (MN 0 "arg")))
146− (mapMaybe evalCase xs ++
147− [DDefaultCase (DV (Glob (MN 0 "arg")))])))
173+ (mkBigCase (MN 0 "EVAL") 256 (DV (Glob (MN 0 "arg")))
174+ (mapMaybe evalCase xs ++
175+ [DDefaultCase (DV (Glob (MN 0 "arg")))])))
148176 where
149− evalCase (n, t, EvalCase x) = Just x
177+ evalCase (n, t, EvalCase x) = Just (x (MN 0 "arg"))
150178 evalCase _ = Nothing
151179
152180mkApply :: [(Name, Int, EvalApply DAlt)] -> (Name, DDecl)
@@ -180,6 +208,7 @@ instance Show DExp where
180208 showSep ", " (map (show' env) args) ++")"
181209 show' env (DLet n v e) = "let " ++ show n ++ " = " ++ show' env v ++ " in " ++
182210 show' (env ++ [show n]) e
211+ show' env (DUpdate n e) = "!update " ++ show n ++ "(" ++ show' env e ++ ")"
183212 show' env (DC i n args) = show n ++ ")" ++ showSep ", " (map (show' env) args) ++ ")"
184213 show' env (DProj t i) = show t ++ "!" ++ show i
185214 show' env (DCase e alts) = "case " ++ show' env e ++ " of {\n\t" ++