First steps in refinement

This commit is contained in:
Alejandro Serrano 2014-07-19 12:11:34 +02:00
parent 60e97d4579
commit ae49eab547
1 changed files with 41 additions and 15 deletions

View File

@ -108,13 +108,16 @@ initialBody :: FnArgsInfo ty name => DynFlags -> PprStyle -> ty -> name -> Strin
initialBody dflag style ty name = initialBody' (getFnName dflag style name) (getFnArgs ty)
initialBody' :: String -> [FnArg] -> String
initialBody' fname args =
initialBody' fname args = initialHead fname args ++ " = "
++ (if isSymbolName fname then "" else '_':fname) ++ "_body"
initialHead :: String -> [FnArg] -> String
initialHead fname args =
case initialBodyArgs args infiniteVars infiniteFns of
[] -> fname
arglist -> if isSymbolName fname
then head arglist ++ " " ++ fname ++ " " ++ unwords (tail arglist)
else fname ++ " " ++ unwords arglist
++ " = " ++ (if isSymbolName fname then "" else '_':fname) ++ "_body"
initialBodyArgs :: [FnArg] -> [String] -> [String] -> [String]
initialBodyArgs [] _ _ = []
@ -122,6 +125,17 @@ initialBodyArgs (FnArgFunction:xs) vs (f:fs) = f : initialBodyArgs xs vs fs
initialBodyArgs (FnArgNormal:xs) (v:vs) fs = v : initialBodyArgs xs vs fs
initialBodyArgs _ _ _ = error "This should never happen" -- Lists are infinite
initialHead1 :: String -> [FnArg] -> [String] -> String
initialHead1 fname args elts =
case initialBodyArgs1 args elts of
[] -> fname
arglist -> if isSymbolName fname
then head arglist ++ " " ++ fname ++ " " ++ unwords (tail arglist)
else fname ++ " " ++ unwords arglist
initialBodyArgs1 :: [FnArg] -> [String] -> [String]
initialBodyArgs1 args elts = take (length args) elts
-- Getting the initial body of function and instances differ
-- This is because for functions we only use the parsed file
-- (so the full file doesn't have to be type correct)
@ -194,21 +208,33 @@ refine file lineNo colNo expr = ghandle handler body
body = inModuleContext file $ \dflag style -> do
opt <- options
modSum <- Gap.fileModSummary file
-- ty <- G.exprType expr -- If involving local bindings, it's not useful
whenFound opt (findVar dflag style modSum lineNo colNo) $ \s -> case s of
(loc, name, ty) -> (fourInts loc, name)
p <- G.parseModule modSum
tcm@TypecheckedModule{tm_typechecked_source = tcs} <- G.typecheckModule p
ety <- G.exprType expr
whenFound opt (findVar dflag style tcm tcs lineNo colNo) $ \(loc, name, rty) ->
let eArgs = getFnArgs ety
rArgs = getFnArgs rty
diffArgs' = length eArgs - length rArgs
diffArgs = if diffArgs' < 0 then 0 else diffArgs'
iArgs = take diffArgs eArgs
in (fourInts loc, initialHead1 expr iArgs (infinitePrefixSupply name))
handler (SomeException _) = emptyResult =<< options
-- Look for the variable in the specified position
findVar :: GhcMonad m => DynFlags -> PprStyle -> G.ModSummary -> Int -> Int -> m (Maybe (SrcSpan, String, Type))
findVar dflag style modSum lineNo colNo = do
p <- G.parseModule modSum
tcm@TypecheckedModule{tm_typechecked_source = tcs} <- G.typecheckModule p
findVar :: GhcMonad m => DynFlags -> PprStyle
-> G.TypecheckedModule -> G.TypecheckedSource
-> Int -> Int -> m (Maybe (SrcSpan, String, Type))
findVar dflag style tcm tcs lineNo colNo =
case listifySpans tcs (lineNo, colNo) :: [G.LHsExpr Id] of
e@(L _ (G.HsVar i)):_ -> do tyInfo <- Gap.getType tcm e
let name = getFnName dflag style i
if isJust tyInfo && (name == "undefined" || head name == '_')
then let Just (s,t) = tyInfo in return $ Just (s, name, t)
else return Nothing
_ -> return Nothing
e@(L _ (G.HsVar i)):_ ->
do tyInfo <- Gap.getType tcm e
let name = getFnName dflag style i
if isJust tyInfo && (name == "undefined" || head name == '_')
then let Just (s,t) = tyInfo in return $ Just (s, name, t)
else return Nothing
_ -> return Nothing
infinitePrefixSupply :: String -> [String]
infinitePrefixSupply "undefined" = repeat "undefined"
infinitePrefixSupply p = map (\n -> p ++ "_" ++ show n) ([1 ..] :: [Integer])