Added an initial crude implementation of name mangling for the main function

This commit is contained in:
Neil Brown 2007-08-22 22:40:50 +00:00
parent 1e06768c20
commit 0c28f6255c
2 changed files with 38 additions and 19 deletions

View File

@ -261,11 +261,20 @@ testRecordInfNames3 = testPassShouldFail "testRecordInfNames3" (recordInfNameTyp
(>>>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
(>>>) f0 f1 x = (f0 x) >>= f1
--Normally, process names in Rain are not mangled. And this should be fine in all cases - but not for the main process (which would
--result in a function called main. Therefore we must mangle main. Ideally into a nonce, but for now into ____main
--TODO check recursive main function works
testFindMain0 :: Test
testFindMain0 = testPassWithStateCheck "testFindMain0" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
testFindMain0 = testPassWithStateCheck "testFindMain0" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m []
check state = assertEqual "testFindMain0" [("main",(A.Name m A.ProcName "main"))] (csMainLocals state)
proc name = A.Spec m (A.Specification m (A.Name m A.ProcName name) $ A.Proc m A.PlainSpec [] (A.Skip m)) $ A.Several m []
orig = proc "main"
exp = proc "____main"
check state = do assertEqual "testFindMain0 A" [("____main",(A.Name m A.ProcName "____main"))] (csMainLocals state)
assertVarDef "testFindMain0 B" state "____main"
(tag7 A.NameDef DontCare "____main" "main" A.ProcName DontCare A.Original A.Unplaced)
testFindMain1 :: Test
testFindMain1 = testPassWithStateCheck "testFindMain1" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
@ -274,20 +283,24 @@ testFindMain1 = testPassWithStateCheck "testFindMain1" orig ((uniquifyAndResolve
check state = assertEqual "testFindMain1" [] (csMainLocals state)
testFindMain2 :: Test
testFindMain2 = testPassWithStateCheck "testFindMain2" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
testFindMain2 = testPassWithStateCheck "testFindMain2" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Several m []
check state = assertEqual "testFindMain2" [("main",(A.Name m A.ProcName "main"))] (csMainLocals state)
proc name = A.Spec m (A.Specification m (A.Name m A.ProcName name) $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Several m []
orig = proc "main"
exp = proc "____main"
check state = assertEqual "testFindMain2" [("____main",(A.Name m A.ProcName "____main"))] (csMainLocals state)
testFindMain3 :: Test
testFindMain3 = testPassWithStateCheck "testFindMain3" orig ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
testFindMain3 = testPassWithStateCheck "testFindMain3" exp ((uniquifyAndResolveVars >>> findMain) orig) (return ()) check
where
orig = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Spec m (A.Specification m (A.Name m A.ProcName "main") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Several m []
check state = assertEqual "testFindMain3" [("main",(A.Name m A.ProcName "main"))] (csMainLocals state)
proc name = A.Spec m (A.Specification m (A.Name m A.ProcName "foo") $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Spec m (A.Specification m (A.Name m A.ProcName name) $ A.Proc m A.PlainSpec [] (A.Skip m)) $
A.Several m []
orig = proc "main"
exp = proc "____main"
check state = assertEqual "testFindMain3" [("____main",(A.Name m A.ProcName "____main"))] (csMainLocals state)
--Returns the list of tests:

View File

@ -96,8 +96,9 @@ uniquifyAndResolveVars = everywhereM (mkM uniquifyAndResolveVars')
--Other:
uniquifyAndResolveVars' s = return s
replaceNameName :: String -> String -> A.Name -> A.Name
replaceNameName find replace n = if (A.nameName n) == find then n {A.nameName = replace} else n
--Helper function for a few of the passes:
replaceNameName :: String -> String -> A.Name -> A.Name
replaceNameName find replace n = if (A.nameName n) == find then n {A.nameName = replace} else n
recordInfNameTypes :: Data t => t -> PassM t
recordInfNameTypes = everywhereM (mkM recordInfNameTypes')
@ -121,14 +122,19 @@ findMain :: Data t => t -> PassM t
--Because findMain runs after uniquifyAndResolveVars, the types of all the process will have been recorded
--Therefore this pass doesn't actually need to walk the tree, it just has to look for a process named "main"
--in the CompState, and pull it out into csMainLocals
findMain x = do st <- get
put (findMain' st)
return x
findMain x = do modify findMain'
everywhereM (mkM $ return . (replaceNameName "main" "____main")) x
where
--We have to mangle the main name because otherwise it will cause problems on some backends (including C and C++)
findMain' :: CompState -> CompState
findMain' st = case (Map.lookup "main" (csNames st)) of
Just n -> st {csMainLocals = [("main",A.Name {A.nameName = "main", A.nameMeta = A.ndMeta n, A.nameType = A.ndNameType n})]}
Just n -> st {csNames = changeMainName (csNames st) , csMainLocals = [("____main",A.Name {A.nameName = "____main", A.nameMeta = A.ndMeta n, A.nameType = A.ndNameType n})]}
Nothing -> st
changeMainName :: Map.Map String A.NameDef -> Map.Map String A.NameDef
changeMainName m = case (Map.lookup "main" m) of
Nothing -> m
Just nd -> ((Map.insert "____main" (nd {A.ndName = "____main"})) . (Map.delete "main")) m
transformEach :: Data t => t -> PassM t
transformEach = everywhereM (mkM transformEach')