forked from GitHub/gf-core
Nonlinear patterns in concrete syntax are now detected and reported as errors
Before, they were silently converted to linear patterns. Nonlinear patterns in MorphoCat.gf, ParadigmsGre.gf and ParadigmsFin.gf have been make linear by renaming pattern variables.
This commit is contained in:
@@ -39,7 +39,7 @@ import GF.Grammar.Printer
|
|||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.List (nub)
|
import Data.List (nub,(\\))
|
||||||
import Text.PrettyPrint
|
import Text.PrettyPrint
|
||||||
|
|
||||||
-- | this gives top-level access to renaming term input in the cc command
|
-- | this gives top-level access to renaming term input in the cc command
|
||||||
@@ -235,76 +235,80 @@ renameTerm env vars = ren vars where
|
|||||||
|
|
||||||
-- | vars not needed in env, since patterns always overshadow old vars
|
-- | vars not needed in env, since patterns always overshadow old vars
|
||||||
renamePattern :: Status -> Patt -> Check (Patt,[Ident])
|
renamePattern :: Status -> Patt -> Check (Patt,[Ident])
|
||||||
renamePattern env patt = case patt of
|
renamePattern env patt =
|
||||||
|
do r@(p',vs) <- renp patt
|
||||||
|
let dupl = vs \\ nub vs
|
||||||
|
unless (null dupl) $ checkError (hang (text "[C.4.13] Pattern is not linear:") 4
|
||||||
|
(ppPatt Unqualified 0 patt))
|
||||||
|
return r
|
||||||
|
where
|
||||||
|
renp patt = case patt of
|
||||||
|
PMacro c -> do
|
||||||
|
c' <- renid $ Vr c
|
||||||
|
case c' of
|
||||||
|
Q d -> renp $ PM d
|
||||||
|
_ -> checkError (text "unresolved pattern" <+> ppPatt Unqualified 0 patt)
|
||||||
|
|
||||||
PMacro c -> do
|
PC c ps -> do
|
||||||
c' <- renid $ Vr c
|
c' <- renid $ Cn c
|
||||||
case c' of
|
case c' of
|
||||||
Q d -> renp $ PM d
|
QC c -> do psvss <- mapM renp ps
|
||||||
_ -> checkError (text "unresolved pattern" <+> ppPatt Unqualified 0 patt)
|
let (ps,vs) = unzip psvss
|
||||||
|
return (PP c ps, concat vs)
|
||||||
|
Q _ -> checkError (text "data constructor expected but" <+> ppTerm Qualified 0 c' <+> text "is found instead")
|
||||||
|
_ -> checkError (text "unresolved data constructor" <+> ppTerm Qualified 0 c')
|
||||||
|
|
||||||
PC c ps -> do
|
PP c ps -> do
|
||||||
c' <- renid $ Cn c
|
(QC c') <- renid (QC c)
|
||||||
case c' of
|
psvss <- mapM renp ps
|
||||||
QC c -> do psvss <- mapM renp ps
|
let (ps',vs) = unzip psvss
|
||||||
let (ps,vs) = unzip psvss
|
return (PP c' ps', concat vs)
|
||||||
return (PP c ps, concat vs)
|
|
||||||
Q _ -> checkError (text "data constructor expected but" <+> ppTerm Qualified 0 c' <+> text "is found instead")
|
|
||||||
_ -> checkError (text "unresolved data constructor" <+> ppTerm Qualified 0 c')
|
|
||||||
|
|
||||||
PP c ps -> do
|
PM c -> do
|
||||||
(QC c') <- renid (QC c)
|
x <- renid (Q c)
|
||||||
psvss <- mapM renp ps
|
c' <- case x of
|
||||||
let (ps',vs) = unzip psvss
|
(Q c') -> return c'
|
||||||
return (PP c' ps', concat vs)
|
_ -> checkError (text "not a pattern macro" <+> ppPatt Qualified 0 patt)
|
||||||
|
return (PM c', [])
|
||||||
|
|
||||||
PM c -> do
|
PV x -> checks [ renid' (Vr x) >>= \t' -> case t' of
|
||||||
x <- renid (Q c)
|
QC c -> return (PP c [],[])
|
||||||
c' <- case x of
|
_ -> checkError (text "not a constructor")
|
||||||
(Q c') -> return c'
|
, return (patt, [x])
|
||||||
_ -> checkError (text "not a pattern macro" <+> ppPatt Qualified 0 patt)
|
]
|
||||||
return (PM c', [])
|
|
||||||
|
|
||||||
PV x -> checks [ renid' (Vr x) >>= \t' -> case t' of
|
PR r -> do
|
||||||
QC c -> return (PP c [],[])
|
let (ls,ps) = unzip r
|
||||||
_ -> checkError (text "not a constructor")
|
psvss <- mapM renp ps
|
||||||
, return (patt, [x])
|
let (ps',vs') = unzip psvss
|
||||||
]
|
return (PR (zip ls ps'), concat vs')
|
||||||
|
|
||||||
PR r -> do
|
PAlt p q -> do
|
||||||
let (ls,ps) = unzip r
|
(p',vs) <- renp p
|
||||||
psvss <- mapM renp ps
|
(q',ws) <- renp q
|
||||||
let (ps',vs') = unzip psvss
|
return (PAlt p' q', vs ++ ws)
|
||||||
return (PR (zip ls ps'), concat vs')
|
|
||||||
|
|
||||||
PAlt p q -> do
|
PSeq p q -> do
|
||||||
(p',vs) <- renp p
|
(p',vs) <- renp p
|
||||||
(q',ws) <- renp q
|
(q',ws) <- renp q
|
||||||
return (PAlt p' q', vs ++ ws)
|
return (PSeq p' q', vs ++ ws)
|
||||||
|
|
||||||
PSeq p q -> do
|
PRep p -> do
|
||||||
(p',vs) <- renp p
|
(p',vs) <- renp p
|
||||||
(q',ws) <- renp q
|
return (PRep p', vs)
|
||||||
return (PSeq p' q', vs ++ ws)
|
|
||||||
|
|
||||||
PRep p -> do
|
PNeg p -> do
|
||||||
(p',vs) <- renp p
|
(p',vs) <- renp p
|
||||||
return (PRep p', vs)
|
return (PNeg p', vs)
|
||||||
|
|
||||||
PNeg p -> do
|
PAs x p -> do
|
||||||
(p',vs) <- renp p
|
(p',vs) <- renp p
|
||||||
return (PNeg p', vs)
|
return (PAs x p', x:vs)
|
||||||
|
|
||||||
PAs x p -> do
|
_ -> return (patt,[])
|
||||||
(p',vs) <- renp p
|
|
||||||
return (PAs x p', x:vs)
|
|
||||||
|
|
||||||
_ -> return (patt,[])
|
renid = renameIdentTerm env
|
||||||
|
renid' = renameIdentTerm' env
|
||||||
where
|
|
||||||
renp = renamePattern env
|
|
||||||
renid = renameIdentTerm env
|
|
||||||
renid' = renameIdentTerm' env
|
|
||||||
|
|
||||||
renameContext :: Status -> Context -> Check Context
|
renameContext :: Status -> Context -> Check Context
|
||||||
renameContext b = renc [] where
|
renameContext b = renc [] where
|
||||||
|
|||||||
Reference in New Issue
Block a user