0N/ADescription : static analysis of heterogeneous structured specifications
0N/ACopyright : (c) Till Mossakowski and Uni Bremen 2003-2006
0N/AMaintainer : till@informatik.uni-bremen.de
0N/AStability : provisional
0N/AStatic analysis of CASL (heterogeneous) structured specifications
0N/A Follows the verfication semantic rules in Chap. IV:4.7
0N/A of the CASL Reference Manual.
793N/AcoerceMaybeNode :: LogicGraph -> DGraph -> MaybeNode -> NodeName -> AnyLogic
0N/A -> Result (MaybeNode, DGraph)
0N/AcoerceMaybeNode lg dg mn nn l2 = case mn of
0N/A EmptyNode _ -> return (EmptyNode l2, dg)
0N/A (ms, dg2) <- coerceNode lg dg ns nn l2
0N/A return (JustNode ms, dg2)
0N/AcoerceNode :: LogicGraph -> DGraph -> NodeSig -> NodeName -> AnyLogic
0N/A -> Result (NodeSig, DGraph)
0N/AcoerceNode lg dg ns@(NodeSig n s@(G_sign lid1 _ _)) nn l2@(Logic lid2) =
0N/A if language_name lid1 == language_name lid2 then return (ns, dg)
0N/A c <- logicInclusion lg (Logic lid1) l2
0N/A gmor <- gEmbedComorphism c s
0N/A case find (\ (_, _, l) -> dgl_origin l == SeeTarget
0N/A && dgl_type l == globalDef
0N/A && dgl_morphism l == gmor) $ outDG dg n of
0N/A let (ms@(NodeSig m _), dg2) =
3087N/A insGSig dg (extName "XCoerced" nn) DGLogicCoercion $ cod gmor
3087N/A dg3 = insLink dg2 gmor globalDef SeeTarget n m
0N/A return (NodeSig t $ signOf $ dgn_theory $ labDG dg t, dg)
0N/AinsGTheory :: DGraph -> NodeName -> DGOrigin -> G_theory -> (NodeSig, DGraph)
0N/AinsGTheory dg name orig (G_theory lid sig ind sens tind) =
0N/A let (sgMap, s) = sigMapI dg
0N/A (tMap, t) = thMapI dg
0N/A nind = if ind == startSigId then succ s else ind
0N/A ntind = if tb then succ t else tind
0N/A nsig = G_sign lid sig nind
0N/A nth = G_theory lid sig nind sens ntind
0N/A node_contents = newNodeLab name orig nth
0N/A node = getNewNodeDG dg
0N/A in (NodeSig node nsig,
0N/A (if ind == startSigId
0N/A $ insNodeDG (node, node_contents) dg)
0N/AinsGSig :: DGraph -> NodeName -> DGOrigin -> G_sign -> (NodeSig, DGraph)
0N/AinsGSig dg name orig (G_sign lid sig ind) =
0N/A insGTheory dg name orig $ noSensGTheory lid sig ind
0N/AinsLink :: DGraph -> GMorphism -> DGLinkType -> DGLinkOrigin -> Node -> Node
0N/AinsLink dg (GMorphism cid sign si mor mi) ty orig n t =
0N/A let (sgMap, s) = sigMapI dg
0N/A (mrMap, m) = morMapI dg
0N/A nsi = if si == startSigId then succ s else si
0N/A nmi = if mi == startMorId then succ m else mi
0N/A nmor = GMorphism cid sign nsi mor nmi
0N/A link = defDGLink nmor ty orig
0N/A (toG_morphism nmor) mrMap else id) $
0N/A (G_sign (sourceLogic cid) sign nsi) sgMap else id)
0N/A $ insLEdgeNubDG (n, t, link) dg
0N/AcreateConsLink :: LinkKind -> Conservativity -> LogicGraph -> DGraph
0N/A -> MaybeNode -> NodeSig -> DGLinkOrigin -> Result DGraph
0N/AcreateConsLink lk conser lg dg nsig (NodeSig node gsig) orig = case nsig of
0N/A EmptyNode _ | conser == None -> return dg
0N/A JustNode (NodeSig n sig) -> do
0N/A let Result _ mIncl = ginclusion lg sig gsig
0N/A return $ insLink dg incl
0N/A (ScopedLink Global lk $ mkConsStatus conser) orig n node
0N/A unless (conser == None) $ warning ()
0N/A "ingoring conservativity annotation between non-subsignatures"
0N/A EmptyNode _ -> -- add conservativity to the target node
0N/A return $ let lbl = labDG dg node
0N/A in if isDGRef lbl then dg else
0N/A { node_cons_status = case getNodeConsStatus lbl of
0N/A ConsStatus c d th -> ConsStatus (max c conser) d th }}) dg
0N/AanaSpecTop :: Conservativity -> Bool -> LogicGraph -> LibName -> DGraph
0N/A -> MaybeNode -> NodeName -> HetcatsOpts -> SPEC
0N/A -> Result (SPEC, NodeSig, DGraph)
0N/AanaSpecTop conser addSyms lg ln dg nsig name opts sp =
0N/A if conser == None || case sp of
0N/A -- for these cases def-links are re-used
0N/A Basic_spec _ _ -> True
0N/A Closed_spec _ _ -> True
0N/A Spec_inst _ _ _ -> True
0N/A Group _ _ -> True -- in this case we recurse
0N/A then anaSpecAux conser addSyms lg ln dg nsig name opts sp else do
0N/A ThmLink $ Proven (DGRule "static analysis") emptyProofBasis
0N/A (rsp, ns, rdg) <- anaSpec addSyms lg ln dg nsig name opts sp
0N/A ndg <- createConsLink provenThmLink conser lg rdg nsig ns SeeTarget
0N/A return (rsp, ns, ndg)
0N/AanaQualSpec :: Bool -> LogicGraph -> HetcatsOpts -> LibName -> DGraph
0N/A -> MaybeNode -> NodeName -> Annoted SPEC -> Range
0N/A -> Result (Annoted SPEC, NodeSig, DGraph)
0N/AanaQualSpec addSyms lg opts ln dg nsig name asp pos = adjustPos pos $ do
0N/A (sp', NodeSig n' gsigma, dg') <- anaSpec addSyms lg ln dg nsig
0N/A (extName "Qualified" name) opts $ item asp
0N/A let (ns@(NodeSig node _), dg2) = insGSig dg' name DGLogicQual gsigma
0N/A return (replaceAnnoted sp' asp, ns,
0N/A insLink dg2 (ide gsigma) globalDef SeeTarget n' node)
0N/AanaFreeOrCofreeSpec :: Bool -> LogicGraph -> HetcatsOpts -> LibName -> DGraph
0N/A -> MaybeNode -> NodeName -> FreeOrCofree -> Annoted SPEC -> Range
0N/A -> Result (Annoted SPEC, NodeSig, DGraph)
0N/AanaFreeOrCofreeSpec addSyms lg opts ln dg nsig name dglType asp pos =
0N/A (sp', NodeSig n' gsigma, dg') <-
0N/A anaSpec addSyms lg ln dg nsig (extName (show dglType) name) opts
0N/A let (ns@(NodeSig node _), dg2) =
0N/A insGSig dg' name (DGFreeOrCofree dglType) gsigma
0N/A nsigma = case nsig of
0N/A EmptyNode cl -> emptyG_sign cl
0N/A JustNode nds -> getSig nds
0N/A incl <- ginclusion lg nsigma gsigma
0N/A return (replaceAnnoted sp' asp, ns,
0N/A insLink dg2 incl (FreeOrCofreeDefLink dglType nsig)
0N/A{- | analyze a SPEC. The Bool Parameter determines if incoming symbols shall
0N/Abe ignored. The options are needed to check: shall only the structure be
0N/AanaSpec :: Bool -> LogicGraph -> LibName -> DGraph -> MaybeNode -> NodeName
0N/A -> HetcatsOpts -> SPEC -> Result (SPEC, NodeSig, DGraph)
0N/AanaSpec = anaSpecAux None
0N/AanaSpecAux :: Conservativity -> Bool -> LogicGraph -> LibName -> DGraph
0N/A -> MaybeNode -> NodeName -> HetcatsOpts -> SPEC
0N/A -> Result (SPEC, NodeSig, DGraph)
0N/AanaSpecAux conser addSyms lg ln dg nsig name opts sp = case sp of
0N/A Basic_spec (G_basic_spec lid bspec) pos -> adjustPos pos $ do
0N/A let curLogic = Logic lid
0N/A (nsig', dg0) <- coerceMaybeNode lg dg nsig name curLogic
0N/A G_sign lid' sigma' _ <- return $ case nsig' of
0N/A EmptyNode cl -> emptyG_sign cl
0N/A JustNode ns -> getSig ns
0N/A coerceSign lid' lid "Analysis of basic spec" sigma'
0N/A (bspec', ExtSign sigma_complete sysd, ax) <-
0N/A if isStructured opts
0N/A then return (bspec, mkExtSign $ empty_signature lid, [])
0N/A let res@(Result ds mb) = extBasicAnalysis lid (getName name)
0N/A (getLibId ln) bspec sig $ globalAnnos dg0
0N/A Nothing | null ds ->
0N/A fail "basic analysis failed without giving a reason"
0N/A (ns, dg') = insGTheory dg0 name
0N/A (DGBasicSpec (Just $ G_basic_spec lid bspec') gsysd)
0N/A $ G_theory lid (ExtSign sigma_complete
0N/A $ symset_of lid sigma_complete)
0N/A startSigId (toThSens ax) startThId
0N/A dg'' <- createConsLink DefLink conser lg dg' nsig' ns DGLinkExtension
0N/A return (Basic_spec (G_basic_spec lid bspec') pos, ns, dg'')
0N/A EmptySpec pos -> case nsig of
0N/A warning () "empty spec" pos
0N/A let (ns, dg') = insGSig dg name DGEmpty (getMaybeSig nsig)
0N/A return (sp, ns, dg')
0N/A {- anaSpec should be changed to return a MaybeNode!
0N/A Then this duplicate dummy node could be avoided.
0N/A Also empty unions could be treated then -}
0N/A JustNode ns -> return (sp, ns , dg)
0N/A Translation asp ren ->
0N/A do let sp1 = item asp
0N/A (sp1', NodeSig n' gsigma, dg') <-
0N/A anaSpec addSyms lg ln dg nsig (extName "Translation" name) opts sp1
0N/A mor <- anaRenaming lg nsig gsigma opts ren
0N/A -- ??? check that mor is identity on local env
0N/A let (ns@(NodeSig node _), dg'') =
0N/A insGSig dg' name (DGTranslation $ Renamed ren) $ cod mor
0N/A -- ??? too simplistic for non-comorphism inter-logic translations
0N/A let dg3 = insLink dg'' mor globalDef SeeTarget n' node
0N/A return (Translation (replaceAnnoted sp1' asp) ren, ns, dg3)
0N/A Reduction asp restr ->
0N/A do let sp1 = item asp
0N/A orig = DGRestriction $ Restricted restr
0N/A (sp1', NodeSig n' gsigma', dg') <-
0N/A anaSpec addSyms lg ln dg nsig (extName "Restriction" name) opts sp1
0N/A let gsigma = getMaybeSig nsig
0N/A (hmor, tmor) <- anaRestriction lg gsigma gsigma' opts restr
0N/A {- we treat hiding and revealing differently
0N/A in order to keep the dg as simple as possible -}
0N/A do let (ns@(NodeSig node _), dg'') =
0N/A insGSig dg' name orig $ dom hmor
0N/A -- ??? too simplistic for non-comorphism inter-logic reductions
0N/A return (Reduction (replaceAnnoted sp1' asp) restr, ns,
0N/A insLink dg'' hmor HidingDefLink SeeTarget n' node)
0N/A let gsigma1 = dom tmor'
0N/A gsigma'' = cod tmor'
0N/A {- ??? too simplistic for non-comorphism inter-logic reductions
0N/A the case with identity translation leads to a simpler dg -}
0N/A if tmor' == ide (dom tmor')
0N/A let (ns@(NodeSig node1 _), dg'') =
0N/A insGSig dg' name orig gsigma1
0N/A return (Reduction (replaceAnnoted sp1' asp) restr, ns,
0N/A insLink dg'' hmor HidingDefLink SeeTarget n' node1)
0N/A let (NodeSig node1 _, dg'') =
0N/A insGSig dg' (extName "Revealing" name) orig gsigma1
0N/A (ns@(NodeSig node2 _), dg3) =
0N/A insGSig dg'' name DGRevealTranslation gsigma''
0N/A dg4 = insLink dg3 hmor HidingDefLink SeeTarget n' node1
0N/A return (Reduction (replaceAnnoted sp1' asp) restr, ns,
0N/A insLink dg4 tmor' globalDef SeeTarget node1 node2)
0N/A Union asps pos -> do
0N/A (newAsps, _, ns, dg') <- adjustPos pos $ anaUnion addSyms lg ln dg nsig
0N/A return (Union newAsps pos, ns, dg')
0N/A Extension asps pos -> do
0N/A let namedSps = map (\ (asp, n) ->
0N/A let nn = incBy n (extName "Extension" name) in
0N/A if n < length asps then (nn, asp)
0N/A else (name { xpath = xpath nn }, asp)) $ number asps
0N/A (sps', nsig1', dg1, _, _) <- foldM (anaExtension lg opts ln pos)
1879N/A ([], nsig, dg, conser, addSyms) namedSps
EmptyNode _ -> fail "empty extension"
JustNode nsig1 -> return (Extension (zipWith replaceAnnoted
(nasp, nsig', dg') <- anaFreeOrCofreeSpec addSyms lg opts ln dg nsig
return (Free_spec nasp poss, nsig', dg')
Cofree_spec asp poss -> do
(nasp, nsig', dg') <- anaFreeOrCofreeSpec addSyms lg opts ln dg nsig
return (Cofree_spec nasp poss, nsig', dg')
Local_spec asp asp' poss -> adjustPos poss $ do
lname = extName "Local" name
(sp2, nsig'@(NodeSig _ gsig1), dg') <-
anaSpec False lg ln dg nsig (extName "Spec" lname) opts sp1
(sp2', NodeSig n'' (G_sign lid2 sigma2 _), dg'') <- anaSpec False lg
ln dg' (JustNode nsig') (extName "Within" lname) opts sp1'
let gSigN = getMaybeSig nsig
(G_sign lid sigmaN _, _) <- gSigCoerce lg gSigN (Logic lid2)
sigma <- coerceSign lid lid2 "Analysis of local spec1" sigmaN
(G_sign lid' sigma' _, _) <- gSigCoerce lg gsig1 (Logic lid2)
sigma1 <- coerceSign lid' lid2 "Analysis of local spec2" sigma'
let sys = ext_sym_of lid2 sigma
sys1 = ext_sym_of lid2 sigma1
sys2 = ext_sym_of lid2 sigma2
mor3 <- if isStructured opts then return (ext_ide sigma2)
else ext_cogenerated_sign lid2
-- gsigma2 = G_sign lid sigma2
gsigma3 = G_sign lid2 (makeExtSign lid2 sigma3) startSigId
sys3 = symset_of lid2 sigma3
unless (isStructured opts
"illegal use of locally declared symbols: "
let (ns@(NodeSig node _), dg2) = insGSig dg'' name DGLocal gsigma3
return (Local_spec (replaceAnnoted sp2 asp)
(replaceAnnoted sp2' asp')
insLink dg2 (gEmbed2 gsigma3 $ mkG_morphism lid2 mor3)
HidingDefLink SeeTarget n'' node)
Closed_spec asp pos -> adjustPos pos $ do
-- analyse spec with empty local env
(sp', NodeSig n' gsigma', dg') <- anaSpec False lg ln dg
(EmptyNode l) (extName "Closed" name) opts sp1
let gsigma = getMaybeSig nsig
gsigma2 <- gsigUnion lg gsigma gsigma'
let (ns@(NodeSig node _), dg2) = insGSig dg' name DGClosed gsigma2
incl2 <- ginclusion lg gsigma' gsigma2
let dg3 = insLink dg2 incl2 globalDef SeeTarget n' node
dg4 <- createConsLink DefLink conser lg dg3 nsig ns DGLinkClosedLenv
return (Closed_spec (replaceAnnoted sp' asp) pos, ns, dg4)
Qualified_spec lognm@(Logic_name nln _) asp pos -> do
let newLG = lg { currentLogic = tokStr nln }
l <- lookupCurrentLogic "Qualified_spec" newLG
let newNSig = case nsig of
EmptyNode _ -> EmptyNode l
anaQualSpec addSyms lg opts ln dg newNSig name asp pos
return (Qualified_spec lognm nasp pos, nsig', dg')
anaSpecTop conser addSyms lg ln dg nsig name opts (item asp)
return (Group (replaceAnnoted sp' asp) pos, nsig', dg')
Spec_inst spname afitargs pos0 -> let
pos = if null afitargs then tokPos spname else pos0
in adjustPos pos $ case lookupGlobalEnvDG spname dg of
Just (SpecEntry gs@(ExtGenSig (GenSig _ params _)
body@(NodeSig nB gsigmaB))) ->
case (\ x y -> (x , x - y)) (length afitargs) (length params) of
-- the case without parameters leads to a simpler dg
-- if the node shall not be named and the logic does not change,
EmptyNode _ | isInternal name -> do
dg2 <- createConsLink DefLink conser lg dg nsig body SeeTarget
-- then just return the body
-- otherwise, we need to create a new one
EmptyNode _ -> return gsigmaB
JustNode (NodeSig _ sigI) -> gsigUnion lg sigI gsigmaB
let (fsig@(NodeSig node _), dg2) =
insGSig dg name (DGInst spname) gsigma
incl <- ginclusion lg gsigmaB gsigma
JustNode (NodeSig nI _) | nI == nB -> dg2
_ -> insLink dg2 incl globalDef (DGLinkMorph spname) nB node
dg4 <- createConsLink DefLink conser lg dg3 nsig fsig SeeTarget
-- now the case with parameters
(ffitargs, dg', (morDelta, gsigmaA, ns@(NodeSig nA gsigmaRes))) <-
anaAllFitArgs lg opts ln dg nsig name spname gs afitargs
GMorphism cid _ _ _ _ <- return morDelta
morDelta' <- case nsig of
EmptyNode _ -> return morDelta
_ -> ginclusion lg gsigmaA gsigmaRes >>= comp morDelta
(_, imor) <- gSigCoerce lg gsigmaB $ Logic $ sourceLogic cid
tmor <- gEmbedComorphism imor gsigmaB
morDelta'' <- comp tmor morDelta'
JustNode (NodeSig nI _) | nI == nB -> dg'
_ -> insLink dg' morDelta'' globalDef (DGLinkMorph spname) nB nA
dg5 <- createConsLink DefLink conser lg dg4 nsig ns SeeTarget
return (Spec_inst spname ffitargs pos, ns, dg5)
-- finally the case with conflicting numbers of formal and actual parameters
(spstr ++ " expects " ++ show (length params) ++ " arguments"
++ " but was given " ++ show (length afitargs)) pos
("Structured specification " ++ spstr ++ " not found") pos
-- analyse "data SPEC1 SPEC2"
Data (Logic lidD) (Logic lidP) asp1 asp2 pos -> adjustPos pos $ do
{- look for the inclusion comorphism from the current logic's data logic
into the current logic itself -}
Comorphism cid <- logicInclusion lg (Logic lidD) (Logic lidP)
let lidD' = sourceLogic cid
dname = extName "Data" name
(sp1', NodeSig n' (G_sign lid' sigma' _), dg') <-
anaSpec False lg ln dg (EmptyNode (Logic lidD)) dname opts sp1
-- force the result to be in the data logic
sigmaD <- coerceSign lid' lidD' "Analysis of data spec" sigma'
-- translate SPEC1's signature along the comorphism
(sigmaD', sensD') <- ext_map_sign cid sigmaD
-- create a development graph link for this translation
let (nsig2@(NodeSig node _), dg1) = insGTheory dg' dname DGData
$ G_theory lidP' sigmaD' startSigId (toThSens sensD') startThId
dg2 = insLink dg1 (GMorphism cid sigmaD startSigId
(ext_ide sigmaD') startMorId)
globalDef SeeTarget n' node
gsigmaD = G_sign lidP' sigmaD' startSigId
(usig, udg) <- case nsig of
EmptyNode _ -> return (nsig2, dg2)
let gsigma = getMaybeSig nsig
gsigma2 <- gsigUnion lg gsigma gsigmaD
let (ns@(NodeSig node2a _), dg2a) =
insGSig dg2 (extName "Union" name) DGUnion gsigma2
incl2 <- ginclusion lg gsigmaD gsigma2
let dg3 = insLink dg2a incl2 globalDef SeeTarget node node2a
dg4 <- createConsLink DefLink conser lg dg3 nsig ns SeeTarget
anaSpec addSyms lg ln udg (JustNode usig) name opts sp2
return (Data (Logic lidD) (Logic lidP)
(replaceAnnoted sp1' asp1)
(replaceAnnoted sp2' asp2)
anaUnion :: Bool -> LogicGraph -> LibName -> DGraph -> MaybeNode -> NodeName
-> HetcatsOpts -> [Annoted SPEC]
-> Result ([Annoted SPEC], [NodeSig], NodeSig, DGraph)
anaUnion addSyms lg ln dg nsig name opts asps = case asps of
let ana (sps1, nsigs, dg', n) sp' = do
(sp1, nsig', dg1) <- anaSpec addSyms lg ln dg' nsig n1 opts sp'
return (sp1 : sps1, nsig' : nsigs, dg1, n1)
in foldM ana ([], [], dg, extName "Union" name) sps
let newAsps = zipWith replaceAnnoted (reverse sps') asps
[ns] -> return (newAsps, nsigs, ns, dg')
let nsigs' = reverse nsigs
gbigSigma <- gsigManyUnion lg (map getSig nsigs')
let (ns@(NodeSig node _), dg2) = insGSig dg' name DGUnion gbigSigma
insE dgl (NodeSig n gsigma) = do
incl <- ginclusion lg gsigma gbigSigma
return $ insLink dgl incl globalDef SeeTarget n node
dg3 <- foldM insE dg2 nsigs'
return (newAsps, nsigs', ns, dg3)
anaRen :: LogicGraph -> HetcatsOpts -> MaybeNode -> Range -> GMorphism
-> G_mapping -> Result GMorphism
anaRen lg opts lenv pos gmor@(GMorphism r sigma ind1 mor _) gmap =
adjustPos pos $ case gmap of
G_symb_map (G_symb_map_items_list lid sis) ->
let lid2 = targetLogic r in
if language_name lid2 == language_name lid then
if isStructured opts then return gmor else do
sis1 <- coerceSymbMapItemsList lid lid2 "Analysis of renaming" sis
rmap <- stat_symb_map_items lid2 sis1
mor1 <- ext_induced_from_morphism lid2 rmap $ makeExtSign lid2 $ cod mor
JustNode (NodeSig _ sigLenv) -> do
-- needs to be changed for logic translations
(G_sign lid1 sigmaLenv1 _, _) <-
gSigCoerce lg sigLenv (Logic lid2)
sigmaLenv' <- coerceSign lid1 lid2 "" sigmaLenv1
let sysLenv = ext_sym_of lid2 sigmaLenv'
unless (
Set.null forbiddenSys) $ plain_error () (
"attempt to rename the following symbols from " ++
"the local environment:\n" ++ showDoc forbiddenSys "") pos
return $ GMorphism r sigma ind1 mor2 startMorId
comor <- logicInclusion lg (Logic lid2) (Logic lid)
gmorTrans <- gEmbedComorphism comor $ cod gmor
newMor <- comp gmor gmorTrans
anaRen lg opts lenv pos newMor gmap
G_logic_translation (Logic_code tok src tar pos1) ->
let adj1 = adjustPos $ if pos1 == nullRange then pos else pos1
G_sign srcLid srcSig ind <- return (cod gmor)
let getLogicStr (Logic_name l _) = tokStr l
Comorphism cid <- lookupComorphism (tokStr ctok) lg
when (isJust src && getLogicStr (fromJust src) /=
language_name (sourceLogic cid))
(fail (getLogicStr (fromJust src) ++
"is not the source logic of "
when (isJust tar && getLogicStr (fromJust tar) /=
language_name (targetLogic cid))
(fail (getLogicStr (fromJust tar) ++
"is not the target logic of "
lookupLogic "with logic: " (tokStr l) lg
>>= logicInclusion lg (Logic srcLid)
Nothing -> fail "with logic: cannot determine comorphism"
mor1 <- gEmbedComorphism c (G_sign srcLid srcSig ind)
anaRenaming :: LogicGraph -> MaybeNode -> G_sign -> HetcatsOpts -> RENAMING
anaRenaming lg lenv gSigma opts (Renaming ren pos) =
foldM (anaRen lg opts lenv pos) (ide gSigma) ren
-- analysis of restrictions
anaRestr :: LogicGraph -> G_sign -> Range -> GMorphism -> G_hiding
anaRestr lg sigEnv pos (GMorphism cid (ExtSign sigma1 sys1) _ mor _) gh =
G_symb_list (G_symb_items_list lid' sis') -> do
let lid1 = sourceLogic cid
sis1 <- coerceSymbItemsList lid' lid1 "Analysis of restriction1" sis'
rsys <- stat_symb_items lid1 sis1
let sys = symset_of lid1 sigma1
sys' =
Set.filter (\ sy -> any (matches lid1 sy) rsys) sys
( \ sy -> matches lid1 sy rsy) sys') rsys
$ plain_error () ("attempt to hide unknown symbols:\n"
++ showDoc unmatched "") pos
-- needs to be changed when logic projections are implemented
(G_sign lidE sigmaLenv0 _, _) <- gSigCoerce lg sigEnv (Logic lid1)
sigmaLenv' <- coerceSign lidE lid1 "" sigmaLenv0
let sysLenv = ext_sym_of lid1 sigmaLenv'
"attempt to hide the following symbols from the local environment:\n"
++ showDoc forbiddenSys "") pos
mor1 <- cogenerated_sign lid1 sys' sigma1
mor1' <- map_morphism cid mor1
return $ GMorphism cid (ExtSign (dom mor1) $
Set.fold (\ sy ->
startSigId mor2 startMorId
G_logic_projection (Logic_code _tok _src _tar pos1) ->
fatal_error "no analysis of logic projections yet" pos1
anaRestriction :: LogicGraph -> G_sign -> G_sign -> HetcatsOpts -> RESTRICTION
-> Result (GMorphism, Maybe GMorphism)
anaRestriction lg gSigma gSigma'@(G_sign _lid0 _sig0 ind0) opts restr =
if isStructured opts then return (ide gSigma, Nothing) else
mor <- foldM (anaRestr lg gSigma pos) (ide gSigma') rstr
Revealed (G_symb_map_items_list lid1 sis) pos -> adjustPos pos $ do
(G_sign lid sigma _, _) <- gSigCoerce lg gSigma (Logic lid1)
sigma0 <- coerceSign lid lid1 "" sigma
(G_sign lid' sigma' _, Comorphism cid) <-
gSigCoerce lg gSigma' (Logic lid1)
sigma1 <- coerceSign lid' lid1 "" sigma'
let sys = ext_sym_of lid1 sigma0 -- local env
sys' = ext_sym_of lid1 sigma1 -- "big" signature
rmap <- stat_symb_map_items lid1 sis
{- domain of rmap intersected with sys'
domain of rmap should be checked to match symbols from sys' ??? -}
mor1 <- ext_generated_sign lid1 (sys `
Set.union` sys'') sigma1
let extsig1 = makeExtSign lid1 $ dom mor1
mor2 <- ext_induced_from_morphism lid1 rmap extsig1
mor1' <- coerceMorphism lid1 (targetLogic cid) "" mor1
extsig1' <- coerceSign lid1 (sourceLogic cid) "" extsig1
return (GMorphism cid extsig1' ind0 mor1' startMorId
, Just $ gEmbed $ mkG_morphism lid1 mor2)
partitionGmaps :: [G_mapping] -> ([G_mapping], [G_mapping])
(hs, rs) = span (\ sm -> case sm of
G_logic_translation _ -> False) $ reverse l
in (reverse rs, reverse hs)
anaGmaps :: LogicGraph -> HetcatsOpts -> Range -> G_sign -> G_sign
-> [G_mapping] -> Result G_morphism
anaGmaps lg opts pos psig@(G_sign lidP sigmaP _) asig@(G_sign lidA sigmaA _)
gsis = adjustPos pos $ if isStructured opts
then return $ mkG_morphism lidP $ ext_ide sigmaP
else if null gsis then do
(G_sign lidP' sigmaP' _, _) <- gSigCoerce lg psig (Logic lidA)
sigmaA' <- coerceSign lidA lidP' "anaGmaps" sigmaA
fmap (mkG_morphism lidP') $
ext_induced_from_to_morphism lidP'
Map.empty sigmaP' sigmaA'
cl <- lookupCurrentLogic "anaGmaps" lg
G_symb_map_items_list lid sis <- homogenizeGM cl gsis
rmap <- stat_symb_map_items lid sis
(G_sign lidP' sigmaP'' _, _) <- gSigCoerce lg psig (Logic lid)
sigmaP' <- coerceSign lidP' lid "anaGmaps1" sigmaP''
(G_sign lidA' sigmaA'' _, _) <- gSigCoerce lg asig (Logic lid)
sigmaA' <- coerceSign lidA' lid "anaGmaps2" sigmaA''
$ ext_induced_from_to_morphism lid rmap sigmaP' sigmaA'
let symI = sym_of lidP sigmaI'
symmap_mor = symmap_of lidP mor
-- are symbols of the imports left untouched?
if
Set.all (\sy -> lookupFM symmap_mor sy == Just sy) symI
else plain_error () "Fitting morphism must not affect import" pos
-- also output symbols that are affected
anaFitArg :: LogicGraph -> LibName -> DGraph -> SIMPLE_ID -> MaybeNode
-> NodeSig -> HetcatsOpts -> NodeName -> FIT_ARG
-> Result (FIT_ARG, DGraph, (G_morphism, NodeSig))
anaFitArg lg ln dg spname nsigI nsigP@(NodeSig nP gsigmaP) opts name fv =
Fit_spec asp gsis pos -> do
(sp', nsigA, dg') <- anaSpec False lg ln dg nsigI name opts (item asp)
logicUnion lg (getNodeLogic nsigP) (getNodeLogic nsigA)
let tl = Logic $ targetLogic aid
(nsigA'@(NodeSig nA' gsigA'), dg'') <- coerceNode lg dg' nsigA name tl
(gsigmaP', pmor) <- gSigCoerce lg gsigmaP tl
tmor <- gEmbedComorphism pmor gsigmaP
gmor <- anaGmaps lg opts pos gsigmaP' gsigA' gsis
eGmor <- comp tmor $ gEmbed gmor
return ( Fit_spec (replaceAnnoted sp' asp) gsis pos
, if nP == nA' && isHomInclusion eGmor then dg'' else
insLink dg'' eGmor globalThm
(DGLinkInst spname $ Fitted gsis) nP nA'
Fit_view vn afitargs pos -> case lookupGlobalEnvDG vn dg of
Just (ViewEntry (ExtViewSig (NodeSig nSrc gsigmaS) mor
gs@(ExtGenSig (GenSig _ params _) target@(NodeSig nTar _))))
GMorphism cid _ _ morHom ind <- return mor
let lid = targetLogic cid
pname = dgn_name $ labDG dg nP
gsigmaI = getMaybeSig nsigI
gsigmaIS <- gsigUnion lg gsigmaI gsigmaS
unless (isSubGsign lg gsigmaP gsigmaIS
&& isSubGsign lg gsigmaIS gsigmaP)
("Parameter does not match source of fittig view. "
++ "Parameter signature:\n"
"\nSource signature of fitting view (united with import):\n"
++ showDoc gsigmaIS "") pos)
(dg4, iSrc) <- case nsigI of
EmptyNode _ -> return (dg, nSrc)
JustNode (NodeSig nI _) -> do
inclI <- ginclusion lg gsigmaI gsigmaIS
inclS <- ginclusion lg gsigmaS gsigmaIS
let (NodeSig n' _, dg1) = insGSig dg (extName "View" name)
{xpath = xpath pname} (DGFitView vn) gsigmaIS
dg2 = insLink dg1 inclI globalDef
(DGLinkFitViewImp vn) nI n'
return (insLink dg2 inclS globalDef
(DGLinkFitViewImp vn) nSrc n', n')
gmor <- ginclusion lg gsigmaP gsigmaIS
return $ insLink dg4 gmor globalThm (DGLinkFitView vn) nP iSrc
case (\ x y -> (x, x - y)) (length afitargs) (length params) of
-- the case without parameters leads to a simpler dg
(0, 0) -> return (fv, dg5, (G_morphism lid morHom ind, target))
-- now the case with parameters
(ffitargs, dg', (gmor_f, _, ns@(NodeSig nA _))) <-
anaAllFitArgs lg opts ln dg5 (EmptyNode $ Logic lid)
GMorphism cid1 _ _ theta _ <- return mor1
let lid1 = targetLogic cid1
when (language_name (sourceLogic cid1) /= language_name lid1)
$ fatal_error "heterogeneous fitting views not yet implemented"
let dg9 = insLink dg' gmor_f globalDef (DGLinkMorph vn) nTar nA
return (Fit_view vn ffitargs pos, dg9, (mkG_morphism lid1 theta, ns))
-- finally the case with conflicting numbers of formal and actual parameters
(tokStr spname ++ " expects " ++ show (length params) ++ " arguments"
++ " but was given " ++ show (length afitargs)) pos
_ -> fatal_error ("View " ++ tokStr vn ++ " not found") pos
anaFitArgs :: LogicGraph -> HetcatsOpts -> LibName -> SIMPLE_ID -> MaybeNode
-> ([FIT_ARG], DGraph, [(G_morphism, NodeSig)], NodeName)
-> Result ([FIT_ARG], DGraph, [(G_morphism, NodeSig)], NodeName)
anaFitArgs lg opts ln spname imps (fas', dg1, args, name') (nsig', fa) = do
(fa', dg', arg) <- anaFitArg lg ln dg1 spname imps nsig' opts n1 fa
return (fa' : fas', dg', arg : args, n1)
anaAllFitArgs :: LogicGraph -> HetcatsOpts -> LibName -> DGraph -> MaybeNode
-> NodeName -> SIMPLE_ID -> ExtGenSig -> [Annoted FIT_ARG]
-> Result ([Annoted FIT_ARG], DGraph, (GMorphism, G_sign, NodeSig))
anaAllFitArgs lg opts ln dg nsig name spname
gs@(ExtGenSig (GenSig imps params _) _)
let fitargs = map item afitargs
(fitargs', dg', args, _) <- foldM (anaFitArgs lg opts ln spname imps)
([], dg, [], extName "Actuals" name) (zip params fitargs)
let actualargs = reverse args
(gsigma', morDelta) <- applyGS lg gs actualargs
gsigmaRes <- gsigUnion lg (getMaybeSig nsig) gsigma'
let (ns, dg2) = insGSig dg' name (DGInst spname) gsigmaRes
dg3 <- foldM (parLink lg nsig (DGLinkInstArg spname) ns) dg2
return ( zipWith replaceAnnoted (reverse fitargs') afitargs, dg3
, (morDelta, gsigma', ns))
parLink :: LogicGraph -> MaybeNode -> DGLinkOrigin -> NodeSig -> DGraph
-> NodeSig -> Result DGraph
parLink lg nsig orig (NodeSig node gsigma') dg (NodeSig nA_i sigA_i) =
JustNode (NodeSig nI _) | nI == nA_i -> return dg
-- actual parameter will be included via import
incl <- ginclusion lg sigA_i gsigma'
return $ insLink dg incl globalDef orig nA_i node
{- Extension of signature morphisms (for instantitations)
first some auxiliary functions -}
mapID idmap i@(Id toks comps pos1) =
compsnew <- mapM (mapID idmap) comps
return (Id toks compsnew pos1)
("Identifier component " ++ showId i
" can be mapped in various ways:\n"
++ showDoc ids "") $ getRange i
-> Result (EndoMap Id) -> Result (EndoMap Id)
extID1 idmap i@(Id toks comps pos1) m = do
compsnew <- mapM (mapID idmap) comps
return $ if comps == compsnew then m1 else
extendMorphism :: G_sign -- ^ formal parameter
-> G_sign -- ^ actual parameter
-> G_morphism -- ^ fitting morphism
-> Result (G_sign, G_morphism)
extendMorphism (G_sign lid sigmaP _) (G_sign lidB sigmaB1 _)
(G_sign lidA sigmaA1 _) (G_morphism lidM fittingMor1 _) = do
-- for now, only homogeneous instantiations....
sigmaB@(ExtSign _ sysB) <-
coerceSign lidB lid "Extension of symbol map1" sigmaB1
sigmaA <- coerceSign lidA lid "Extension of symbol map2" sigmaA1
fittingMor <- coerceMorphism lidM lid "Extension of symbol map3" fittingMor1
let symsP = ext_sym_of lid sigmaP
symsB = ext_sym_of lid sigmaB
idsB =
Set.map (sym_name lid) symsB
h = symmap_of lid fittingMor
rh = symbMapToRawSymbMap h
(\ sy1 sy2 ->
Rel.setInsert (sym_name lid sy1) (sym_name lid sy2))
(id_to_raw lid id1) (id_to_raw lid id2))
-- do we need combining function catching the clashes???
mor <- ext_induced_from_morphism lid r sigmaB
let hmor = symmap_of lid mor
sigmaAD = ExtSign (cod mor) $
Set.map (\ sy ->
sigma <- ext_signature_union lid sigmaA sigmaAD
$ plain_error () ("Symbols shared between actual parameter and body"
++ "\nmust be in formal parameter:\n"
++ showDoc illShared "") nullRange
comb2 p qs [] ++ comb1 qs
comb2 p@(a, b) ((c, d) : qs) rs =
comb2 p qs $ if b == d then (a, c) : rs else rs
newIdentifications = myKernel hmor Set.\\ myKernel h
"Fitting morphism may lead to forbidden identifications:\n"
++ showDoc newIdentifications "") nullRange
incl <- ext_inclusion lid sigmaAD sigma
return (G_sign lid sigma startSigId, mkG_morphism lid mor1)
applyGS :: LogicGraph -> ExtGenSig -> [(G_morphism, NodeSig)]
-> Result (G_sign, GMorphism)
applyGS lg (ExtGenSig (GenSig nsigI _ gsigmaP) nsigB) args = do
gsigmaA_i = map (getSig . snd) args
gsigmaA@(G_sign lidA _ _) <- gsigManyUnion lg gsigmaA_i
(Comorphism bid, Comorphism uid) <-
logicUnion lg (getNodeLogic nsigB) (Logic lidA)
let cl = Logic $ targetLogic uid
G_morphism lidG mor0 _ <- case nsigI of
EmptyNode _ -> homogeneousMorManyUnion mor_i
JustNode (NodeSig _ gsigmaI) -> do
(G_sign lidI sigmaI _, _) <- gSigCoerce lg gsigmaI (Logic lidA)
homogeneousMorManyUnion $ mkG_morphism lidI idI : mor_i
(gsigmaP', _) <- gSigCoerce lg (getMaybeSig gsigmaP) cl
(gsigmaB', _) <- gSigCoerce lg gsigmaB cl
(gsigmaA', Comorphism aid) <- gSigCoerce lg gsigmaA cl
mor1 <- coerceMorphism lidG (sourceLogic aid) "applyGS" mor0
mor2 <- map_morphism aid mor1
(gsig, G_morphism gid mor3 mId) <- extendMorphism gsigmaP' gsigmaB' gsigmaA' $
G_morphism (targetLogic aid) mor2 startMorId
G_sign lidB sigB indB -> do
sigB' <- coerceSign lidB (sourceLogic bid) "applyGS2" sigB
mor4 <- coerceMorphism gid (targetLogic bid) "applyGS3" mor3
return (gsig, GMorphism bid sigB' indB mor4 mId)
homogenizeGM :: AnyLogic -> [G_mapping] -> Result G_symb_map_items_list
homogenizeGM (Logic lid) gsis =
foldM homogenize1 (G_symb_map_items_list lid []) gsis
homogenize1 (G_symb_map_items_list lid2 sis) sm = case sm of
G_symb_map (G_symb_map_items_list lid1 sis1) -> do
sis1' <- coerceSymbMapItemsList lid1 lid2 "" sis1
return $ G_symb_map_items_list lid2 $ sis ++ sis1'
G_logic_translation lc ->
fail $ "translation not supported by " ++ showDoc lc ""
-- | check if structured analysis should be performed
isStructured :: HetcatsOpts -> Bool
isStructured a = case analysis a of
getSpecAnnos :: Range -> Annoted a -> Result (Conservativity, Bool)
let sannos = filter isSemanticAnno $ l_annos a
(sanno1, conflict, impliedA, impliesA) = case sannos of
f@(Semantic_anno anno1 _) : r -> (case anno1 of
anno1 == SA_implied, anno1 == SA_implies)
_ -> (None, False, False, False)
when conflict $ plain_error () "Conflicting semantic annotations" pos
when impliedA $ plain_error ()
"Annotation %implied should come after a BASIC-ITEM" pos
return (sanno1, impliesA)
-- only consider addSyms for the first spec
:: LogicGraph -> HetcatsOpts -> LibName -> Range
-> ([SPEC], MaybeNode, DGraph, Conservativity, Bool)
-> (NodeName, Annoted SPEC)
-> Result ([SPEC], MaybeNode, DGraph, Conservativity, Bool)
anaExtension lg opts ln pos (sps', nsig', dg', conser, addSyms) (name', asp')
(sanno1, impliesA) <- getSpecAnnos pos asp'
-- attach conservativity to definition link
(sp1', nsig1@(NodeSig n1 sig1), dg1) <- anaSpecTop (max conser sanno1)
addSyms lg ln dg' nsig' name' opts (item asp')
dg2 <- if impliesA then case nsig' of
JustNode (NodeSig n' sig') -> do
-- is the extension going between real nodes?
unless (isHomSubGsign sig1 sig') $ plain_error ()
"Signature must not be extended in presence of %implies" pos
-- insert a theorem link according to p. 319 of the CASL Reference Manual
return $ insLink dg1 (ide sig1) globalThm DGImpliesLink n1 n'
return (sp1' : sps', JustNode nsig1, dg2, None, True)