X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=clash%2FCLasH%2FNormalize.hs;h=11212f943df0678a4b9cef09fb52657ba06bc2dd;hb=ef7d876bddac1ebf8ae72dfac9aff33023650f53;hp=c27e93eb7803c0c4604492308cbccd9fadbc2864;hpb=04f836932ad17dd557af0ba388a12d2b74c1e7d7;p=matthijs%2Fmaster-project%2Fc%CE%BBash.git diff --git a/clash/CLasH/Normalize.hs b/clash/CLasH/Normalize.hs index c27e93e..11212f9 100644 --- a/clash/CLasH/Normalize.hs +++ b/clash/CLasH/Normalize.hs @@ -216,10 +216,15 @@ needsInline f = do -- body consisting of a bunch of nested lambdas containing a -- non-function value (e.g., a complete application). eta :: Transform -eta c expr | is_fun expr && not (is_lam expr) && all (== LambdaBody) c = do - let arg_ty = (fst . Type.splitFunTy . CoreUtils.exprType) expr - id <- Trans.lift $ mkInternalVar "param" arg_ty - change (Lam id (App expr (Var id))) +eta (AppFirst:_) expr = return expr +-- Also don't apply to arguments, since this can cause loops with +-- funextract. This isn't the proper solution, but due to an +-- implementation bug in notappargs, this is how it used to work so far. +eta (AppSecond:_) expr = return expr +eta c expr | is_fun expr && not (is_lam expr) = do + let arg_ty = (fst . Type.splitFunTy . CoreUtils.exprType) expr + id <- Trans.lift $ mkInternalVar "param" arg_ty + change (Lam id (App expr (Var id))) -- Leave all other expressions unchanged eta c e = return e @@ -375,7 +380,7 @@ funextract c expr@(App _ _) | is_var fexpr = do -- We could use is_applicable here instead of is_fun, but I think -- arguments to functions could only have forall typing when existential -- typing is enabled. Not sure, though. - doarg arg | not (is_simple arg) && is_fun arg = do + doarg arg | not (is_simple arg) && is_fun arg && not (has_free_tyvars arg) = do -- Create a new top level binding that binds the argument. Its body will -- be extended with lambda expressions, to take any free variables used -- by the argument expression. @@ -405,15 +410,14 @@ funextract c expr = return expr -- Make sure the scrutinee of a case expression is a local variable -- reference. scrutsimpl :: Transform --- Don't touch scrutinees that are already simple -scrutsimpl c expr@(Case (Var _) _ _ _) = return expr --- Replace all other cases with a let that binds the scrutinee and a new +-- Replace a case expression with a let that binds the scrutinee and a new -- simple scrutinee, but only when the scrutinee is representable (to prevent -- loops with inlinenonrep, though I don't think a non-representable scrutinee --- will be supported anyway...) +-- will be supported anyway...) and is not a local variable already. scrutsimpl c expr@(Case scrut b ty alts) = do repr <- isRepr scrut - if repr + local_var <- Trans.lift $ is_local_var scrut + if repr && not local_var then do id <- Trans.lift $ mkBinderFor scrut "scrut" change $ Let (NonRec id scrut) (Case (Var id) b ty alts) @@ -748,7 +752,7 @@ inlinenonrepresult :: Transform -- that is fully applied (i.e., dos not have a function type) but is not -- representable. We apply in any context, since non-representable -- expressions are generally left alone and can occur anywhere. -inlinenonrepresult context expr | not (is_fun expr) = +inlinenonrepresult context expr | not (is_applicable expr) && not (has_free_tyvars expr) = case collectArgs expr of (Var f, args) | not (Id.isDictId f) -> do repr <- isRepr expr @@ -816,6 +820,10 @@ inlinenonrepresult context expr | not (is_fun expr) = -- Leave all other expressions unchanged inlinenonrepresult c expr = return expr +---------------------------------------------------------------- +-- Type-class transformations +---------------------------------------------------------------- + -------------------------------- -- ClassOp resolution --------------------------------