-- doesn't seem to set all those names as "system names", we apply some
-- guessing here.
inlinetoplevel, inlinetopleveltop :: Transform
+-- HACK: Don't inline == and /=. The default (derived) implementation
+-- for /= uses the polymorphic version of ==, which gets a dictionary
+-- for Eq passed in, which contains a reference to itself, resulting in
+-- an infinite loop in transformation. Not inlining == is really a hack,
+-- but for now it keeps things working with the most common symptom of
+-- this problem.
+inlinetoplevel expr@(Var f) | Name.getOccString f `elem` ["==", "/="] = return expr
-- Any system name is candidate for inlining. Never inline user-defined
-- functions, to preserve structure.
inlinetoplevel expr@(Var f) | not $ isUserDefined f = do
- norm_maybe <- Trans.lift $ getNormalized_maybe f
- case norm_maybe of
- -- No body or not normalizeable.
- Nothing -> return expr
- Just norm -> if needsInline norm then do
+ body_maybe <- needsInline f
+ case body_maybe of
+ Just body -> do
-- Regenerate all uniques in the to-be-inlined expression
- norm_uniqued <- Trans.lift $ genUniques norm
+ body_uniqued <- Trans.lift $ genUniques body
-- And replace the variable reference with the unique'd body.
- change norm_uniqued
- else
+ change body_uniqued
-- No need to inline
- return expr
+ Nothing -> return expr
+
-- Leave all other expressions unchanged
inlinetoplevel expr = return expr
inlinetopleveltop = everywhere ("inlinetoplevel", inlinetoplevel)
-
-needsInline :: CoreExpr -> Bool
-needsInline expr = case splitNormalized expr of
- -- Inline any function that only has a single definition, it is probably
- -- simple enough. This might inline some stuff that it shouldn't though it
- -- will never inline user-defined functions (inlinetoplevel only tries
- -- system names) and inlining should never break things.
- (args, [bind], res) -> True
- _ -> False
-
-
+
+-- | Does the given binder need to be inlined? If so, return the body to
+-- be used for inlining.
+needsInline :: CoreBndr -> TransformMonad (Maybe CoreExpr)
+needsInline f = do
+ body_maybe <- Trans.lift $ getGlobalBind f
+ case body_maybe of
+ -- No body available?
+ Nothing -> return Nothing
+ Just body -> case CoreSyn.collectArgs body of
+ -- The body is some (top level) binder applied to 0 or more
+ -- arguments. That should be simple enough to inline.
+ (Var f, args) -> return $ Just body
+ -- Body is more complicated, try normalizing it
+ _ -> do
+ norm_maybe <- Trans.lift $ getNormalized_maybe f
+ case norm_maybe of
+ -- Noth normalizeable
+ Nothing -> return Nothing
+ Just norm -> case splitNormalized norm of
+ -- The function has just a single binding, so that's simple
+ -- enough to inline.
+ (args, [bind], res) -> return $ Just norm
+ -- More complicated function, don't inline
+ _ -> return Nothing
+
--------------------------------
-- Dictionary inlining
--------------------------------
Just cls -> case collectArgs dict of
(_, []) -> return expr -- Dict is not an application (e.g., not inlined yet)
(Var dictdc, (ty':selectors)) | not (Maybe.isJust (Id.isDataConId_maybe dictdc)) -> return expr -- Dictionary is not a datacon yet (but e.g., a top level binder)
- | tyargs_neq ty ty' -> error $ "Applying class selector to dictionary without matching type?\n" ++ pprString expr
+ | tyargs_neq ty ty' -> error $ "Normalize.classopresolution: Applying class selector to dictionary without matching type?\n" ++ pprString expr
| otherwise ->
let selector_ids = Class.classSelIds cls in
-- Find the selector used in the class' list of selectors
case List.elemIndex sel selector_ids of
- Nothing -> error $ "Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids
+ Nothing -> error $ "Normalize.classopresolution: Selector not found in class' selector list? This should not happen!\nExpression: " ++ pprString expr ++ "\nClass: " ++ show cls ++ "\nSelectors: " ++ show selector_ids
-- Get the corresponding argument from the dictionary
Just n -> change (selectors!!n)
(_, _) -> return expr -- Not applying a variable? Don't touch