diff --git a/RainPassTest.hs b/RainPassTest.hs index 1304909..f68088e 100644 --- a/RainPassTest.hs +++ b/RainPassTest.hs @@ -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: diff --git a/RainPasses.hs b/RainPasses.hs index a02c74c..9809da5 100644 --- a/RainPasses.hs +++ b/RainPasses.hs @@ -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')