diff --git a/LANGUAGE b/LANGUAGE index 20d6968..693cd60 100644 --- a/LANGUAGE +++ b/LANGUAGE @@ -20,6 +20,6 @@ CHAN for CHAN OF, and PLACE for PLACE AT. PLACE IN WORKSPACE and PLACE IN VECSPACE, both currently ignored. -INITIAL variables. +INITIAL and RESULT abbreviations. Array constructors. diff --git a/Makefile.am b/Makefile.am index 1794f82..b14854d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ tock_SOURCES_hs += pass/PassList.hs tock_SOURCES_hs += pass/Properties.hs tock_SOURCES_hs += pass/Traversal.hs tock_SOURCES_hs += transformations/ImplicitMobility.hs +tock_SOURCES_hs += transformations/SimplifyAbbrevs.hs tock_SOURCES_hs += transformations/SimplifyComms.hs tock_SOURCES_hs += transformations/SimplifyExprs.hs tock_SOURCES_hs += transformations/SimplifyProcs.hs diff --git a/TestMain.hs b/TestMain.hs index 2a6d6f5..9d0fab8 100644 --- a/TestMain.hs +++ b/TestMain.hs @@ -64,7 +64,7 @@ import qualified CommonTest (tests) import qualified FlowGraphTest (qcTests) import qualified GenerateCTest (tests) import qualified OccamPassesTest (tests) -import qualified OccamTypesTest (tests) +import qualified OccamTypesTest (ioTests) import qualified ParseRainTest (tests) import qualified PassTest (tests) import qualified PreprocessOccamTest (tests) @@ -181,7 +181,7 @@ main = do (opts, nonOpts, errs) <- getArgs >>* getOpt RequireOrder options ,return FlowGraphTest.qcTests ,noqc GenerateCTest.tests ,noqc OccamPassesTest.tests - ,noqc OccamTypesTest.tests + ,noqcButIO OccamTypesTest.ioTests ,noqc ParseRainTest.tests ,noqc PassTest.tests ,noqc PreprocessOccamTest.tests @@ -195,4 +195,4 @@ main = do (opts, nonOpts, errs) <- getArgs >>* getOpt RequireOrder options noqc t = return (t,[]) noqcButIO :: IO Test -> IO (Test, [LabelledQuickCheckTest]) - noqcButIO t = t >>* \x -> (x,[]) \ No newline at end of file + noqcButIO t = t >>* \x -> (x,[]) diff --git a/data/AST.hs b/data/AST.hs index b0a0fb7..d94e021 100644 --- a/data/AST.hs +++ b/data/AST.hs @@ -456,6 +456,10 @@ data AbbrevMode = | Abbrev -- | An abbreviation by value. | ValAbbrev + -- | An abbreviation by value that can be modified. + | InitialAbbrev + -- | An abbreviation by reference that is initially undefined. + | ResultAbbrev deriving (Show, Eq, Typeable, Data) -- | Anything that introduces a new name. diff --git a/frontends/OccamTypes.hs b/frontends/OccamTypes.hs index 54d4e35..689fd63 100644 --- a/frontends/OccamTypes.hs +++ b/frontends/OccamTypes.hs @@ -311,6 +311,7 @@ checkAbbrev m orig new = case (orig, new) of (_, A.Original) -> bad (A.ValAbbrev, A.ValAbbrev) -> ok + (A.ValAbbrev, A.InitialAbbrev) -> ok (A.ValAbbrev, _) -> bad _ -> ok where @@ -320,7 +321,9 @@ checkAbbrev m orig new showAM :: A.AbbrevMode -> String showAM A.Original = "an original declaration" showAM A.Abbrev = "a reference abbreviation" - showAM A.ValAbbrev = "a value abbreviation" + showAM A.ValAbbrev = "a VAL abbreviation" + showAM A.InitialAbbrev = "an INITIAL abbreviation" + showAM A.ResultAbbrev = "a RESULT abbreviation" -- | Check a list of actuals is the right length for a list of formals. checkActualCount :: Meta -> A.Name -> [A.Formal] -> [a] -> PassM () @@ -1102,13 +1105,13 @@ checkSpecTypes = checkDepthM doSpecType doSpecType (A.Is m am t v) = do tv <- astTypeOf v checkType (findMeta v) t tv - when (am /= A.Abbrev) $ unexpectedAM m + checkRefAM m am amv <- abbrevModeOfVariable v checkAbbrev m amv am doSpecType (A.IsExpr m am t e) = do te <- astTypeOf e checkType (findMeta e) t te - when (am /= A.ValAbbrev) $ unexpectedAM m + checkValAM m am checkAbbrev m A.ValAbbrev am doSpecType (A.IsChannelArray m rawT cs) = do t <- resolveUserType m rawT @@ -1159,12 +1162,31 @@ checkSpecTypes = checkDepthM doSpecType doFunctionBody rs (Left s) = checkStructured (checkExpressionList rs) s -- FIXME: Need to know the name of the function to do this doFunctionBody rs (Right p) = dieP m "Cannot check function process body" - doSpecType (A.Retypes m _ t v) + doSpecType (A.Retypes m am t v) = do fromT <- astTypeOf v checkRetypes m fromT t - doSpecType (A.RetypesExpr m _ t e) + checkRefAM m am + amv <- abbrevModeOfVariable v + checkAbbrev m amv am + doSpecType (A.RetypesExpr m am t e) = do fromT <- astTypeOf e checkRetypes m fromT t + checkValAM m am + checkAbbrev m A.ValAbbrev am + + checkValAM :: Meta -> A.AbbrevMode -> PassM () + checkValAM m am + = case am of + A.ValAbbrev -> ok + A.InitialAbbrev -> ok + _ -> unexpectedAM m + + checkRefAM :: Meta -> A.AbbrevMode -> PassM () + checkRefAM m am + = case am of + A.Abbrev -> ok + A.ResultAbbrev -> ok + _ -> unexpectedAM m unexpectedAM :: Check Meta unexpectedAM m = dieP m "Unexpected abbreviation mode" diff --git a/frontends/OccamTypesTest.hs b/frontends/OccamTypesTest.hs index b020430..6b02b2b 100644 --- a/frontends/OccamTypesTest.hs +++ b/frontends/OccamTypesTest.hs @@ -19,7 +19,7 @@ with this program. If not, see . -- #ignore-exports -- | Tests for 'OccamTypes'. -module OccamTypesTest (tests) where +module OccamTypesTest (ioTests) where import Control.Monad.State import Data.Generics @@ -29,6 +29,7 @@ import qualified AST as A import CompState import Metadata import qualified OccamTypes +import TestHarness import TestUtils m :: Meta @@ -606,7 +607,7 @@ testOccamTypes = TestList returnOne = Left $ A.Only m $ A.ExpressionList m [intE] returnTwo = Left $ A.Only m $ A.ExpressionList m [intE, intE] - retypesV = A.Retypes m A.ValAbbrev + retypesV = A.Retypes m A.Abbrev retypesE = A.RetypesExpr m A.ValAbbrev known1 = A.Array [dimension 4] A.Byte known2 = A.Array [dimension 2, dimension 2] A.Byte @@ -616,7 +617,12 @@ testOccamTypes = TestList --}}} -tests :: Test -tests = TestLabel "OccamTypesTest" $ TestList - [ testOccamTypes - ] +ioTests :: IO Test +ioTests = liftM (TestLabel "OccamTypesTest" . TestList) $ sequence $ + map return + [ testOccamTypes + ] + ++ map (automaticTest FrontendOccam) + [ "testcases/automatic/initial-result-1.occ.test" + , "testcases/automatic/initial-result-2.occ.test" + ] diff --git a/frontends/ParseOccam.hs b/frontends/ParseOccam.hs index 3fb8a44..9b9af8b 100644 --- a/frontends/ParseOccam.hs +++ b/frontends/ParseOccam.hs @@ -254,6 +254,12 @@ tryVVXX a b c d = try (do { av <- a; bv <- b; c; d; return (av, bv) }) tryVVXV :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (a, b, d) tryVVXV a b c d = try (do { av <- a; bv <- b; c; dv <- d; return (av, bv, dv) }) + +tryVVVX :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser (a, b, c) +tryVVVX a b c d = try (do { av <- a; bv <- b; cv <- c; d; return (av, bv, cv) }) + +tryVVVXV :: OccParser a -> OccParser b -> OccParser c -> OccParser d -> OccParser e -> OccParser (a, b, c, e) +tryVVVXV a b c d e = try (do { av <- a; bv <- b; cv <- c; d; ev <- e; return (av, bv, cv, ev) }) --}}} --{{{ subscripts @@ -949,62 +955,60 @@ declOf spec nt abbreviation :: OccParser NameSpec abbreviation - = valIsAbbrev - <|> initialIsAbbrev - <|> isAbbrev variable VariableName - <|> isAbbrev channel ChannelName + = valAbbrev + <|> refAbbrev variable VariableName + <|> refAbbrev channel ChannelName <|> chanArrayAbbrev - <|> isAbbrev timer TimerName - <|> isAbbrev port PortName + <|> refAbbrev timer TimerName + <|> refAbbrev port PortName "abbreviation" -valIsAbbrev :: OccParser NameSpec -valIsAbbrev +maybeInfer :: OccParser A.Type -> OccParser A.Type +maybeInfer spec + = try spec + <|> return A.Infer + "optional specifier" + +valAbbrevMode :: OccParser A.AbbrevMode +valAbbrevMode + = (sVAL >> return A.ValAbbrev) + <|> (sINITIAL >> return A.InitialAbbrev) + +valAbbrev :: OccParser NameSpec +valAbbrev = do m <- md - (n, t, e) <- do { n <- tryXVX sVAL newVariableName sIS; e <- expression; sColon; eol; return (n, A.Infer, e) } - <|> do { (s, n) <- tryXVVX sVAL dataSpecifier newVariableName sIS; e <- expression; sColon; eol; return (n, s, e) } - return (A.Specification m n $ A.IsExpr m A.ValAbbrev t e, VariableName) - "VAL IS abbreviation" + (am, t, n) <- + tryVVVX valAbbrevMode (maybeInfer dataSpecifier) newVariableName sIS + e <- expression + sColon + eol + return (A.Specification m n $ A.IsExpr m am t e, VariableName) + "abbreviation by value" -initialIsAbbrev :: OccParser NameSpec -initialIsAbbrev - = do m <- md - (t, n) <- tryXVVX sINITIAL dataSpecifier newVariableName sIS - e <- expression - sColon - eol - return (A.Specification m n $ A.IsExpr m A.Original t e, VariableName) - "INITIAL IS abbreviation" +refAbbrevMode :: OccParser A.AbbrevMode +refAbbrevMode + = (sRESULT >> return A.ResultAbbrev) + <|> return A.Abbrev -isAbbrev :: OccParser A.Variable -> NameType -> OccParser NameSpec -isAbbrev oldVar nt - = do m <- md - (n, v) <- tryVXV (newName nt) sIS oldVar - sColon - eol - return (A.Specification m n $ A.Is m A.Abbrev A.Infer v, nt) - <|> do m <- md - (s, n, v) <- tryVVXV specifier (newName nt) sIS oldVar - sColon - eol - return (A.Specification m n $ A.Is m A.Abbrev s v, nt) - "IS abbreviation" +refAbbrev :: OccParser A.Variable -> NameType -> OccParser NameSpec +refAbbrev oldVar nt + = do m <- md + (am, t, n, v) <- + tryVVVXV refAbbrevMode (maybeInfer specifier) (newName nt) sIS oldVar + sColon + eol + return (A.Specification m n $ A.Is m am t v, nt) + "abbreviation by reference" chanArrayAbbrev :: OccParser NameSpec chanArrayAbbrev - = do m <- md - (n, cs) <- tryVXXV newChannelName sIS sLeft (sepBy1 channel sComma) - sRight - sColon - eol - return (A.Specification m n $ A.IsChannelArray m A.Infer cs, ChannelName) - <|> do m <- md - (s, n) <- tryVVXX channelSpecifier newChannelName sIS sLeft - cs <- sepBy1 channel sComma - sRight - sColon - eol - return (A.Specification m n $ A.IsChannelArray m s cs, ChannelName) + = do m <- md + (t, n, cs) <- + tryVVXV (maybeInfer channelSpecifier) newChannelName (sIS >> sLeft) (sepBy1 channel sComma) + sRight + sColon + eol + return (A.Specification m n $ A.IsChannelArray m t cs, ChannelName) "channel array abbreviation" specMode :: OccParser () -> OccParser A.SpecMode @@ -1049,18 +1053,14 @@ definition <|> retypesAbbrev "definition" -retypesReshapes :: OccParser () -retypesReshapes - = sRETYPES <|> sRESHAPES - retypesAbbrev :: OccParser NameSpec retypesAbbrev = do m <- md - (s, n) <- tryVVX dataSpecifier newVariableName retypesReshapes + (am, s, n) <- tryVVVX refAbbrevMode dataSpecifier newVariableName retypesReshapes v <- variable sColon eol - return (A.Specification m n $ A.Retypes m A.Abbrev s v, VariableName) + return (A.Specification m n $ A.Retypes m am s v, VariableName) <|> do m <- md (s, n) <- tryVVX channelSpecifier newChannelName retypesReshapes c <- channel @@ -1068,12 +1068,16 @@ retypesAbbrev eol return (A.Specification m n $ A.Retypes m A.Abbrev s c, ChannelName) <|> do m <- md - (s, n) <- tryXVVX sVAL dataSpecifier newVariableName retypesReshapes + (am, s, n) <- tryVVVX valAbbrevMode dataSpecifier newVariableName retypesReshapes e <- expression sColon eol - return (A.Specification m n $ A.RetypesExpr m A.ValAbbrev s e, VariableName) + return (A.Specification m n $ A.RetypesExpr m am s e, VariableName) "RETYPES/RESHAPES abbreviation" + where + retypesReshapes :: OccParser () + retypesReshapes + = sRETYPES <|> sRESHAPES dataSpecifier :: OccParser A.Type dataSpecifier @@ -1151,11 +1155,13 @@ formalArgSet formalVariableType :: OccParser (A.AbbrevMode, A.Type) formalVariableType - = do sVAL - s <- dataSpecifier - return (A.ValAbbrev, s) - <|> do s <- dataSpecifier - return (A.Abbrev, s) + = do am <- + (sVAL >> return A.ValAbbrev) + <|> (sINITIAL >> return A.InitialAbbrev) + <|> (sRESULT >> return A.ResultAbbrev) + <|> return A.Abbrev + s <- dataSpecifier + return (am, s) "formal variable type" valueProcess :: OccParser (A.Structured A.ExpressionList) diff --git a/pass/PassList.hs b/pass/PassList.hs index ead6f6e..83c1df9 100644 --- a/pass/PassList.hs +++ b/pass/PassList.hs @@ -1,6 +1,6 @@ {- Tock: a compiler for parallel languages -Copyright (C) 2007 University of Kent +Copyright (C) 2007, 2008 University of Kent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -37,6 +37,7 @@ import OccamPasses import Pass import qualified Properties as Prop import RainPasses +import SimplifyAbbrevs import SimplifyComms import SimplifyExprs import SimplifyProcs @@ -55,6 +56,7 @@ commonPasses opts = concat $ , enablePassesWhen (not . csUsageChecking) [pass "Usage checking turned OFF" Prop.agg_namesDone [Prop.parUsageChecked] return] + , simplifyAbbrevs , simplifyComms , simplifyExprs , simplifyProcs diff --git a/pass/Properties.hs b/pass/Properties.hs index 855225e..fc44d75 100644 --- a/pass/Properties.hs +++ b/pass/Properties.hs @@ -42,6 +42,7 @@ module Properties , functionsRemoved , functionTypesChecked , inferredTypesRecorded + , initialRemoved , inputCaseRemoved , intLiteralsInBounds , listsGivenType @@ -55,6 +56,7 @@ module Properties , processTypesChecked , rainParDeclarationsPulledUp , rangeTransformed + , resultRemoved , retypesChecked , seqInputsFlattened , slicesSimplified @@ -402,3 +404,14 @@ slicesSimplified = Property "slicesSimplified" $ listsGivenType :: Property listsGivenType = Property "listsGivenType" checkTODO + +initialRemoved :: Property +initialRemoved + = Property "initialRemoved" $ + checkNull "initialRemoved" . listify (== A.InitialAbbrev) + +resultRemoved :: Property +resultRemoved + = Property "resultRemoved" $ + checkNull "resultRemoved" . listify (== A.ResultAbbrev) + diff --git a/testcases/automatic/initial-result-1.occ.test b/testcases/automatic/initial-result-1.occ.test new file mode 100644 index 0000000..30ed432 --- /dev/null +++ b/testcases/automatic/initial-result-1.occ.test @@ -0,0 +1,81 @@ +-- This file tests INITIAL and RESULT abbreviations. + +PROC main () + INT var: + REAL32 var.r: + BYTE var.b: + VAL INT const IS 42: + VAL REAL32 const.r IS 9.8: + VAL BYTE const.b IS 'x': +%% + SKIP +: + +%PASS Normal kinds of abbreviations + INT abbrev IS var: + inferred.abbrev IS var: + VAL INT val IS var: + VAL inferred.val IS var: + VAL INT val.const IS const: + VAL inferred.val.const IS const: + +%PASS Initial-abbreviate var + INITIAL INT init IS var: + +%PASS Initial-abbreviate const + INITIAL INT init IS const: + +%FAIL Initial-abbreviate wrong type + INITIAL INT init IS const.r: + +%PASS Initial-abbreviate inferred type + INITIAL init IS const: + +%PASS Result-abbreviate var + RESULT INT result IS var: + +%FAIL Result-abbreviate const + RESULT INT result IS const: + +%FAIL Result-abbreviate wrong type + RESULT INT result IS var.r: + +%PASS Result-abbreviate inferred type from var + RESULT result IS var: + +%FAIL Result-abbreviate inferred type from const + RESULT result IS const: + +%PASS Normal kinds of retypings + INT32 retyped RETYPES var.r: + VAL INT32 val.retypes RETYPES var.r: + VAL INT32 val.retypes.const RETYPES const.r: + +%FAIL Normal kind of retyping from wrong size var + INT32 retyped RETYPES var.b: + +%FAIL Normal kind of retyping from wrong size const + VAL INT32 retyped RETYPES const.b: + +%PASS Initial retyping from var + INITIAL INT32 retyped RETYPES var.r: + +%PASS Initial retyping from const + INITIAL INT32 retyped RETYPES const.r: + +%FAIL Initial retyping from wrong size var + INITIAL INT32 retyped RETYPES var.b: + +%FAIL Initial retyping from wrong size const + INITIAL INT32 retyped RETYPES const.b: + +%PASS Result retyping from var + RESULT INT32 retyped RETYPES var.r: + +%FAIL Result retyping from const + RESULT INT32 retyped RETYPES const.r: + +%FAIL Result retyping from wrong size + RESULT INT32 retyped RETYPES var.b: + +% diff --git a/testcases/automatic/initial-result-2.occ.test b/testcases/automatic/initial-result-2.occ.test new file mode 100644 index 0000000..87d2be6 --- /dev/null +++ b/testcases/automatic/initial-result-2.occ.test @@ -0,0 +1,46 @@ +-- This file tests INITIAL and RESULT formals and actuals. + +PROC main () + INT var: + REAL32 var.r: + VAL INT const IS 42: + VAL REAL32 const.r IS 9.8: + + PROC on.init (INITIAL INT init) + init := init + 1 + : + PROC on.result (RESULT INT result) + result := 42 + : + +%% +: + +%PASS Just the PROCs + SKIP + +%PASS Initial actual from var + on.init (var) + +%PASS Initial actual from const + on.init (const) + +%FAIL Initial actual from wrong type + on.init (const.r) + +%PASS Result actual from var + on.result (var) + +%FAIL Result actual from const + on.result (const) + +%FAIL Result actual from wrong type + on.result (var.r) + +%FAIL Initial formal in FUNCTION + INT FUNCTION function (INITIAL INT arg) IS 42: + +%FAIL Result formal in FUNCTION + INT FUNCTION function (RESULT INT arg) IS 42: + +% diff --git a/transformations/SimplifyAbbrevs.hs b/transformations/SimplifyAbbrevs.hs new file mode 100644 index 0000000..f438f56 --- /dev/null +++ b/transformations/SimplifyAbbrevs.hs @@ -0,0 +1,53 @@ +{- +Tock: a compiler for parallel languages +Copyright (C) 2008 University of Kent + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation, either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +-} + +-- | Simplify abbreviations. +module SimplifyAbbrevs (simplifyAbbrevs) where + +import qualified AST as A +import Pass +import qualified Properties as Prop +import Traversal + +simplifyAbbrevs :: [Pass] +simplifyAbbrevs = + [ removeInitial + , removeResult + ] + +-- | Rewrite 'InitialAbbrev' into a variable and an assignment. +removeInitial :: Pass +removeInitial + = pass "Remove INITIAL abbreviations" + [] + [Prop.initialRemoved] + -- FIXME: Implement this + return + +-- | Rewrite 'ResultAbbrev' into just 'Abbrev'. +removeResult :: Pass +removeResult + = pass "Remove RESULT abbreviations" + [] + [Prop.resultRemoved] + (applyDepthM (return . doAbbrevMode)) + where + doAbbrevMode :: A.AbbrevMode -> A.AbbrevMode + doAbbrevMode A.ResultAbbrev = A.Abbrev + doAbbrevMode s = s +