Turned *EXTERNAL pragmas into specifications in the occam parser

There was a bug where things scoped in via pragmas were never scoped out again, which was screwing up the local names stack.  I then realised/decided that pragmas were really specifications, and decided to put them there in the parser.

The rest of this patch is just some rewiring to allow the special name munging involved in pragmas (they have already got a munged version of their name) and to stop the scoped in pragmas appearing in the AST.
This commit is contained in:
Neil Brown 2009-04-03 21:06:24 +00:00
parent 4a36d578c0
commit f755458545

View File

@ -358,7 +358,6 @@ maybeIndentedList :: Meta -> String -> OccParser t -> OccParser [t]
maybeIndentedList m msg inner
= do try indent
vs <- many1 inner
optional $ many1 pragma
outdent
return vs
<|> do warnP m WarnParserOddity msg
@ -372,7 +371,8 @@ handleSpecs specs inner specMarker
v <- inner
mapM scopeOutSpec (reverse ss')
after
return $ foldl (\e s -> specMarker m s e) v ss'
return $ foldl (\e s -> specMarker m s e) v
[s | (s,(_,_,(_,A.NameUser))) <- zip ss' ss]
-- | Run several different parsers with a separator between them.
-- If you give it [a, b, c] and s, it'll parse [a, s, b, s, c] then
@ -403,17 +403,16 @@ findName thisN thisNT
then dieP (A.nameMeta thisN) $ "expected " ++ show thisNT ++ " (" ++ A.nameName origN ++ " is " ++ show origNT ++ ")"
else return $ thisN { A.nameName = A.nameName origN }
scopeIn :: A.Name -> NameType -> A.SpecType -> A.AbbrevMode -> OccParser A.Name
scopeIn n@(A.Name m s) nt specType am
= do s' <- makeUniqueName m s
let n' = n { A.nameName = s' }
scopeIn :: A.Name -> NameType -> A.SpecType -> A.AbbrevMode -> (Maybe A.Name, A.NameSource) -> OccParser A.Name
scopeIn n@(A.Name m s) nt specType am (munged, ns)
= do n' <- maybe (makeUniqueName m s >>* A.Name m) return munged
let nd = A.NameDef {
A.ndMeta = m,
A.ndName = s',
A.ndName = A.nameName n',
A.ndOrigName = s,
A.ndSpecType = specType,
A.ndAbbrevMode = am,
A.ndNameSource = A.NameUser,
A.ndNameSource = ns,
A.ndPlacement = A.Unplaced
}
defineName n' nd
@ -433,22 +432,25 @@ scopeOut n@(A.Name m _)
scopeInRep :: A.Name -> OccParser A.Name
scopeInRep n
= scopeIn n VariableName (A.Declaration (A.nameMeta n) A.Int) A.ValAbbrev
= scopeIn n VariableName (A.Declaration (A.nameMeta n) A.Int) A.ValAbbrev normalName
scopeOutRep :: A.Name -> OccParser ()
scopeOutRep n = scopeOut n
-- | A specification, along with the 'NameType' of the name it defines.
type NameSpec = (A.Specification, NameType)
type NameSpec = (A.Specification, NameType, (Maybe A.Name, A.NameSource))
normalName :: (Maybe A.Name, A.NameSource)
normalName = (Nothing, A.NameUser)
scopeInSpec :: NameSpec -> OccParser A.Specification
scopeInSpec (spec@(A.Specification m n st), nt)
scopeInSpec (spec@(A.Specification m n st), nt, ns)
-- If it's recursive, the spec has already been defined:
| isRecursive st
= do modifyName n $ \nd -> nd {A.ndSpecType = st}
return spec
| otherwise
= do n' <- scopeIn n nt st (abbrevModeOfSpec st)
= do n' <- scopeIn n nt st (abbrevModeOfSpec st) ns
return $ A.Specification m n' st
where
isRecursive (A.Function _ (_, A.Recursive) _ _ _) = True
@ -464,7 +466,7 @@ type NameFormal = (A.Formal, NameType)
scopeInFormal :: NameFormal -> OccParser A.Formal
scopeInFormal (A.Formal am t n, nt)
= do n' <- scopeIn n nt (A.Declaration (A.nameMeta n) t) am
= do n' <- scopeIn n nt (A.Declaration (A.nameMeta n) t) am normalName
return (A.Formal am t n')
scopeInFormals :: [NameFormal] -> OccParser [A.Formal]
@ -1032,9 +1034,10 @@ specification :: OccParser ([NameSpec], OccParser ())
specification
= do m <- md
(ns, d, nt) <- declaration
return ([(A.Specification m n d, nt) | n <- ns], return ())
return ([(A.Specification m n d, nt, normalName) | n <- ns], return ())
<|> do { a <- abbreviation; return ([a], return ()) }
<|> do { d <- definition; return ([d], return ()) }
<|> do { n <- pragma ; return (maybeToList n, return ()) }
<?> "specification"
declaration :: OccParser ([A.Name], A.SpecType, NameType)
@ -1081,7 +1084,7 @@ valAbbrev
e <- expression
sColon
eol
return (A.Specification m n $ A.Is m am t (A.ActualExpression e), VariableName)
return (A.Specification m n $ A.Is m am t (A.ActualExpression e), VariableName, normalName)
<?> "abbreviation by value"
refAbbrevMode :: OccParser A.AbbrevMode
@ -1101,7 +1104,7 @@ refAbbrev oldVar nt
sColon
eol
t' <- direct t
return (A.Specification m n $ A.Is m am t' $ A.ActualVariable v, nt)
return (A.Specification m n $ A.Is m am t' $ A.ActualVariable v, nt, normalName)
<?> "abbreviation by reference"
chanArrayAbbrev :: OccParser NameSpec
@ -1116,7 +1119,7 @@ chanArrayAbbrev
sColon
eol
t' <- direct t
return (A.Specification m n $ A.Is m A.Abbrev t' $ A.ActualChannelArray cs, ChannelName)
return (A.Specification m n $ A.Is m A.Abbrev t' $ A.ActualChannelArray cs, ChannelName, normalName)
<?> "channel array abbreviation"
specMode :: OccParser a -> OccParser (A.SpecMode, a)
@ -1141,9 +1144,9 @@ definition
sDATA
sTYPE
do { n <- tryVX newDataTypeName sIS; t <- dataType; sColon; eol;
return (A.Specification m n (A.DataType m t), DataTypeName) }
return (A.Specification m n (A.DataType m t), DataTypeName, normalName) }
<|> do { n <- newRecordName; eol; indent; rec <- structuredType; outdent; sColon; eol;
return (A.Specification m n rec, RecordName) }
return (A.Specification m n rec, RecordName, normalName) }
<|> do m <- md
rm <- tryVX (recMode sCHAN) sTYPE >>* fst
n <- newChanBundleName
@ -1155,19 +1158,19 @@ definition
indent
n' <- if rm == A.Recursive
then scopeIn n ChanBundleName
(A.ChanBundleType m rm []) A.Original
(A.ChanBundleType m rm []) A.Original normalName
else return n
fs <- many1 chanInBundle
outdent
outdent
sColon
eol
return (A.Specification m n' $ A.ChanBundleType m rm fs, ChanBundleName)
return (A.Specification m n' $ A.ChanBundleType m rm fs, ChanBundleName, normalName)
<|> do m <- md
sPROTOCOL
n <- newProtocolName
do { sIS; p <- sequentialProtocol; sColon; eol; return (A.Specification m n $ A.Protocol m p, ProtocolName) }
<|> do { eol; indent; sCASE; eol; ps <- maybeIndentedList m "empty CASE protocol" taggedProtocol; outdent; sColon; eol; return (A.Specification m n $ A.ProtocolCase m ps, ProtocolName) }
do { sIS; p <- sequentialProtocol; sColon; eol; return (A.Specification m n $ A.Protocol m p, ProtocolName, normalName) }
<|> do { eol; indent; sCASE; eol; ps <- maybeIndentedList m "empty CASE protocol" taggedProtocol; outdent; sColon; eol; return (A.Specification m n $ A.ProtocolCase m ps, ProtocolName, normalName) }
<|> do m <- md
(sm, (rm, _)) <- specMode $ recMode sPROC
n <- newProcName
@ -1176,7 +1179,7 @@ definition
indent
n' <- if rm == A.Recursive
then scopeIn n ProcName
(A.Proc m (sm, rm) (map fst fs) (A.Skip m)) A.Original
(A.Proc m (sm, rm) (map fst fs) (A.Skip m)) A.Original normalName
else return n
fs' <- scopeInFormals fs
p <- process
@ -1184,7 +1187,7 @@ definition
outdent
sColon
eol
return (A.Specification m n' $ A.Proc m (sm, rm) fs' p, ProcName)
return (A.Specification m n' $ A.Proc m (sm, rm) fs' p, ProcName, normalName)
<|> do m <- md
(rs, (sm, (rm, _))) <- tryVV (sepBy1 dataType sComma) (specMode $ recMode sFUNCTION)
n <- newFunctionName
@ -1193,16 +1196,16 @@ definition
= do n' <- if rm == A.Recursive
then scopeIn n FunctionName
(A.Function m (sm, rm) rs (map fst fs) (Left $ A.Several m []))
A.Original
A.Original normalName
else return n
fs' <- scopeInFormals fs
x <- body
scopeOutFormals fs'
return (x, fs', n')
do { sIS; (el, fs', n') <- addScope expressionList; sColon; eol;
return (A.Specification m n' $ A.Function m (sm, rm) rs fs' (Left $ A.Only m el), FunctionName) }
return (A.Specification m n' $ A.Function m (sm, rm) rs fs' (Left $ A.Only m el), FunctionName, normalName) }
<|> do { eol; indent; (vp, fs', n') <- addScope valueProcess; outdent; sColon; eol;
return (A.Specification m n' $ A.Function m (sm, rm) rs fs' (Left vp), FunctionName) }
return (A.Specification m n' $ A.Function m (sm, rm) rs fs' (Left vp), FunctionName, normalName) }
<|> retypesAbbrev
<?> "definition"
where
@ -1222,19 +1225,19 @@ retypesAbbrev
v <- variable
sColon
eol
return (A.Specification m n $ A.Retypes m am s v, VariableName)
return (A.Specification m n $ A.Retypes m am s v, VariableName, normalName)
<|> do m <- md
(s, n) <- tryVVX channelSpecifier newChannelName retypesReshapes
c <- directedChannel
sColon
eol
return (A.Specification m n $ A.Retypes m A.Abbrev s c, ChannelName)
return (A.Specification m n $ A.Retypes m A.Abbrev s c, ChannelName, normalName)
<|> do m <- md
(am, s, n) <- tryVVVX valAbbrevMode dataSpecifier newVariableName retypesReshapes
e <- expression
sColon
eol
return (A.Specification m n $ A.RetypesExpr m am s e, VariableName)
return (A.Specification m n $ A.RetypesExpr m am s e, VariableName, normalName)
<?> "RETYPES/RESHAPES abbreviation"
where
retypesReshapes :: OccParser ()
@ -1373,7 +1376,7 @@ structuredTypeField
--}}}
--}}}
--{{{ pragmas
pragma :: OccParser ()
pragma :: OccParser (Maybe NameSpec)
pragma = do m <- getPosition >>* sourcePosToMeta
Pragma rawP <- genToken isPragma
let prag :: Maybe (Int, String)
@ -1397,6 +1400,7 @@ pragma = do m <- getPosition >>* sourcePosToMeta
modify $ \st -> st {csNameAttr = Map.insertWith Set.union
n (Set.singleton NameShared) (csNameAttr st)})
vars
return Nothing
1 -> do
vars <- sepBy1 identifier sComma
mapM_ (\var ->
@ -1407,6 +1411,7 @@ pragma = do m <- getPosition >>* sourcePosToMeta
modify $ \st -> st {csNameAttr = Map.insertWith Set.union
n (Set.singleton NameAliasesPermitted) (csNameAttr st)})
vars
return Nothing
pragmaType | pragmaType == 2 || pragmaType == 3 -> do
m <- md
(n, nt, origN, fs, sp) <-
@ -1430,27 +1435,28 @@ pragma = do m <- getPosition >>* sourcePosToMeta
n <- newFunctionName
return (n, FunctionName, origN, fs, A.Function m (A.PlainSpec, A.PlainRec) ts fs
$ Right (A.Skip m))
let nd = A.NameDef m (A.nameName n) (A.nameName origN)
sp A.Original A.NamePredefined A.Unplaced
ext = if pragmaType == 2 then ExternalOldStyle else ExternalOccam
let ext = if pragmaType == 2 then ExternalOldStyle else ExternalOccam
modify $ \st -> st
{ csNames = Map.insert (A.nameName n) nd (csNames st)
, csLocalNames = (A.nameName origN, (n, nt)) : csLocalNames st
, csExternals = (A.nameName n, (ext, fs)) : csExternals st
{ csExternals = (A.nameName n, (ext, fs)) : csExternals st
}
case (prag, mprod) of
return $ Just (A.Specification m origN sp, nt, (Just n, A.NamePredefined))
ns <- case (prag, mprod) of
(Just (_, pragStr), Just prod) -> do
let column = metaColumn m + fromMaybe 0 (findIndex (=='\"') rawP)
toks <- runLexer' (fromMaybe "<unknown(pragma)>" $ metaFile m
, metaLine m, column) pragStr
cs <- getCompState
case runParser (prod >> getState) cs "" toks of
Left err -> warnP m WarnUnknownPreprocessorDirective $
"Unknown PRAGMA (parse failed): " ++ show err
Right st -> setState st
_ -> warnP m WarnUnknownPreprocessorDirective $
"Unknown PRAGMA type: " ++ show rawP
case runParser (do {n <- prod; s <- getState; return (n, s)}) cs "" toks of
Left err -> do warnP m WarnUnknownPreprocessorDirective $
"Unknown PRAGMA (parse failed): " ++ show err
return Nothing
Right (n, st) -> do setState st
return n
_ -> do warnP m WarnUnknownPreprocessorDirective $
"Unknown PRAGMA type: " ++ show rawP
return Nothing
eol
return ns
where
isPragma (Token _ p@(Pragma {})) = Just p
isPragma _ = Nothing
@ -1479,7 +1485,6 @@ process
<|> intrinsicProc
<|> handleSpecs (allocation <|> specification <|> claimSpec) process
(\m s p -> A.Seq m (A.Spec m s (A.Only m p)))
<|> (tryXV pragma process)
<?> "process"
claimSpec :: OccParser ([NameSpec], OccParser ())
@ -1489,7 +1494,7 @@ claimSpec
n <- getName v >>= getOrigName
eol
indent
return ([(A.Specification m (A.Name m n) $ A.Is m A.Abbrev A.Infer $ A.ActualClaim v, ChannelName)], outdent)
return ([(A.Specification m (A.Name m n) $ A.Is m A.Abbrev A.Infer $ A.ActualClaim v, ChannelName, normalName)], outdent)
where
getName :: A.Variable -> OccParser A.Name
getName (A.Variable _ n) = return n
@ -1887,7 +1892,6 @@ topLevelItem :: OccParser A.AST
topLevelItem
= handleSpecs (allocation <|> specification) topLevelItem
(\m s inner -> A.Spec m s inner)
<|> (pragma >> topLevelItem)
<|> do m <- md
eof
-- Stash the current locals so that we can either restore them