/ src /
src/INTextual.hs
1 module INTextual
2 (
3 Net (..)
4 , doc2net
5 , network2net
6 , textualRule
7 , toRuleNet -- tricky function with unsafe operations inside
8 , simplify
9 , filterRules
10 , filterNet
11
12 , Representation (..)
13 , showRepresentation
14 )where
15
16 import Document hiding (ActiveCanvas(..))
17 import Network
18 import qualified Palette as Pal
19 import Constants
20 import qualified Data.IntMap as IM
21 import Data.Maybe
22 import Data.Char
23 import Data.List
24 import Common
25 import INRules
26 import INRule
27 import InfoKind
28 import SpecialSymbols
29
30
31 type Edge' = EdgeNr
32 type AgentName = String
33 type Agent = (AgentName -- agent name
34 , Int -- the agent arity, this is, the number of ports
35 -- excludind the principal one
36 )
37 type Interface = [Term]
38
39 -- | (rules, <interface | equations>) is a configuration
40 data Net = Net { agents :: [Agent] -- ^ the list of agents and its arities
41 , equations :: [Equation] -- ^ the equations
42 , interface :: Interface -- ^ the interface of the net
43 --
44 , rules :: [Rule] -- ^ rules
45 } deriving (Eq)
46
47 type NodeApl = (AgentName, [Term])
48 data Term = Simple Edge' | Compound NodeApl deriving (Eq, Ord, Show)
49 type Equation = (Term, Term)
50
51 type Rule = (Maybe String, NodeApl, NodeApl)
52
53
54 instance Show Net where
55 show = showRepresentation PIN
56
57 {-
58 generalRepresentation :: Net -> String
59 generalRepresentation = unlines . map showEquation . equations
60 where showEquation (edge, info) = (showEdge edge) ++ " = " ++ showNodeApl info ++ " ;"
61 showNodeApl (node, edges) =
62 showNode node ++ if null edges
63 then ""
64 else "(" ++ showTerm (head edges)
65 ++ showTail (tail edges)
66 ++ ")"
67 showEdge = int2name
68 showNode node = filter (not . isSpace) node
69 showTail = concatMap (\a -> ", " ++ showTerm a)
70 -}
71
72 data Representation = AMIN | PIN deriving Show
73
74 repFold amin pin rep = case rep of
75 AMIN -> amin
76 PIN -> pin
77
78 -- | Creates the string with the representation of a 'Net'
79 -- in the format of IN transformation tools:
80 -- * AMIN
81 -- * PIN
82 showRepresentation :: Representation -> Net -> String
83 showRepresentation rep net =
84 unlines (
85 [ "/* Automatically generated by " ++ toolName ++ " for " ++ show rep ++ " */"
86 , ""
87 , repFold "agents" "" rep
88 , ""
89 ] ++ map showAgent (agents net) ++
90 [ ""
91 , repFold "rules" "" rep
92 , ""
93 ] ++ map showRule (rules net) ++
94 [ ""
95 , repFold "net" "//test net\nstart :" rep
96 , ""
97 ] ++ map showEquation (equations net) ++
98 case rep of
99 AMIN -> [ ""
100 , "interface"
101 , ""
102 ] ++ map showEdge2 (interface net) ++
103 [ ""
104 , ""
105 , "end"
106 ]
107 PIN -> []
108 )
109 where showAgent :: Agent -> String
110 showAgent (name, arity) = sl (spaces2underscores name) (repFold "\t" ":" rep) $ show arity
111
112 showEquation :: Equation -> String
113 showEquation (lhs, rhs) = sl (showTerm lhs) (repFold " = " " - " rep) $ showTerm rhs
114
115 showTerm (Simple e) = showEdge e
116 showTerm (Compound c) = showNodeApl c
117
118 showNodeApl (node, edges) =
119 showNode node ++ if null edges
120 then ""
121 else "(" ++ showTerm (head edges)
122 ++ showTail (tail edges)
123 ++ ")"
124 showNode node = spaces2underscores node
125 showTail = concatMap (\a -> ", " ++ showTerm a)
126
127 showEdge :: Edge' -> String
128 showEdge = int2name
129
130 showEdge2 term = showTerm term ++ ";"
131
132 sl arg1 sep arg2 = '\t' : arg1 ++ sep ++ arg2 ++ repFold ";" [] rep
133
134 showRule (mStr, lhs, rhs) = repFold [] (maybe [] ((++ ":\n") . spaces2underscores) mStr) rep
135 ++ sl (showNodeApl lhs) " >< " (showNodeApl rhs) ++ "\n"
136
137
138 doc2net :: (InfoKind n g, InfoKind e g) => Document g n e -> Net
139 doc2net doc = nubAgents $ (network2net palette $ getNetwork doc)
140 `join`
141 (foldr1 join . mapRules (textualRule palette) $ getRules doc)
142 where palette = getPalette doc
143
144 nubAgents :: Net -> Net
145 nubAgents net = net { agents = nub $ agents net}
146
147 join :: Net -> Net -> Net
148 join net1 net2 =
149 Net { agents = agents net1 ++ agents net2
150 , equations = equations net1 ++ equations net2
151 , interface = interface net1 ++ interface net2
152 , rules = rules net1 ++ rules net2
153 }
154
155 network2net :: Pal.Palette n -> Network g n e -> Net
156 network2net palette network =
157 Net { agents = delete (fst interfaceSymbol, 0) . nub
158 . map getAgent . IM.assocs $ nodeMap
159 , equations = sort eqs'
160 , interface = map fst inter
161 , rules = []
162 }
163 where nodeMap = networkNodes network
164
165 eqs = catMaybes $ IM.foldWithKey f [] nodeMap
166 (eqs', inter) = partition test eqs
167 f nodeNr node r = (node2net nodeNr node) : r
168 node2net :: NodeNr -> Node n -> Maybe Equation
169 node2net nr node =
170 do (pPort:otherPorts) <- getPorts palette network nr
171 pEdge <- edgeConnectedOnPort network nr (fst pPort)
172 let otherEdges = catMaybes $ map (edgeConnectedOnPort network nr . fst) otherPorts
173 return (Simple pEdge, Compound (getShape node, map Simple otherEdges))
174 test :: Equation -> Bool
175 test (Simple _, Compound (str, [])) = str /= fst interfaceSymbol
176 test _ = True
177 getAgent :: (NodeNr, Node n) -> (AgentName, Int)
178 getAgent (nr,node) = (getShape node, agentArity nr)
179 agentArity :: NodeNr -> Int
180 agentArity nr = length (maybe [] id $ getPorts palette network nr) - 1
181
182 -- | Generates the textual representation of a rule.
183 textualRule :: (InfoKind n g, InfoKind e g) => Pal.Palette n -> INRule g n e -> Net
184 textualRule palette rule =
185 let lhs = getLHS rule
186 rhs = getRHS rule
187 ruleName = INRule.getName rule
188 (interface, others) = partition isInterfaceNode $ getNodeAssocs lhs
189
190 f :: (NodeNr -> NodeNr) -> Network g n e -> MappingElement -> Network g n e
191 f new oldnet (nil, nir) =
192 let redge = takeJust ("One interface agent in rhs of rule "
193 ++ ruleName ++ " is disconnected.")
194 $ edgeConnectedOnPort oldnet nir "interface"
195 (nl, pl) = takeJust ("One interface agent in lhs of rule "
196 ++ ruleName ++ " is disconnected.")
197 $ otherExtremeOfEdgeConnectedOnPort lhs nil "interface"
198
199 in removeNode nir . updateEdge redge (substBy (nir, "interface") (new nl, pl)) $ oldnet
200 f _ _ _ = error "unknow error"
201
202 substBy (oldNode, oldPort) (newNode, newPort) edge =
203 case getFullPortFrom edge of
204 (node, port) | node == oldNode && port == oldPort
205 -> setPortFrom newNode newPort edge
206 _ -> case getFullPortTo edge of
207 (node, port) | node == oldNode && port == oldPort
208 -> setPortTo newNode newPort edge
209 _ -> error "unexpected"
210
211 in case others of
212 [(n1, a), (n2, b)] | hasActivePair n1 n2 lhs palette ->
213 let aPrincipalPort = head . fromJust $ getPorts palette lhs n1
214 bPrincipalPort = head . fromJust $ getPorts palette lhs n2
215 (na, rhs1) = addExistingNode a rhs
216 (nb, rhs2) = addExistingNode b rhs1
217 rhs3 = addEdge palette na (fst aPrincipalPort) nb (fst bPrincipalPort) rhs2
218
219 new n | n==n1 = na
220 | n==n2 = nb
221 | otherwise = error "unknow error"
222
223 -- connect mapping with wires removing interface agents
224 rhs4 = foldl (f new) rhs3 $ getMapping rule
225
226 in toRuleNet ruleName . simplify . network2net palette $ rhs4
227
228 _ -> if isEmpty lhs
229 then error $ "LHS of rule " ++ ruleName ++ " is empty."
230 else error $ "LHS of rule " ++ ruleName ++ " must have just one active pair and interface and it was found something differente. Maybe it was a "
231
232
233
234 hasActivePair :: NodeNr-> NodeNr -> Network g n e -> Pal.Palette n -> Bool
235 hasActivePair n1 n2 net palette =
236 case (getPorts palette net n1, getPorts palette net n2) of
237 (Just ((ap,_):_), Just ((bp,_):_) ) ->
238 isJust ( findEdge n1 ap n2 bp net ) ||
239 isJust ( findEdge n2 bp n1 ap net )
240 _ -> False
241
242 toRuleNet :: String -> Net -> Net
243 toRuleNet ruleName net =
244 if null $ interface net
245 then case equations net of
246 [(Compound x, Compound y)] -> net {equations = [], rules = [(Just ruleName,x,y)]}
247 x:xs | not $ null xs -> error $ "Rule " ++ ruleName ++ " probably has active pair(s) in its rhs."
248 y -> error $ "Internal error in textual representation generation of rule "
249 ++ ruleName ++ " or unknow error." ++ show y
250
251 else error $ "Rule " ++ ruleName ++ " with interface: internal error in textual representation generation or mismatching interfaces between lhs and rhs."
252
253 simplify :: Net -> Net
254 simplify net = Net { agents = agents net
255 , equations = eqs''
256 , interface = inter'
257 , rules = rules net }
258 where inter = interface net
259 eqs' = simp [] (equations net)
260 (eqs'', inter') = simp2 inter eqs'
261
262 -- | @ simp @ removes equations of form @ a = X @
263 -- for something as @ X @ and for any @ a @
264 -- that don't belong to the interface,
265 -- substituting the unique occurence of @ a @
266 -- in the others equations.
267 simp :: [Equation] -- ^ the equations already folded
268 -> [Equation] -- ^ the equations to fold
269 -> [Equation] -- ^ the result
270 simp eqsB [] = eqsB
271 simp eqsB (eq@(Compound _, _) : eqsA) = simp (eqsB ++ [eq]) eqsA
272 simp eqsB (eq@(Simple x , a) : eqsA)
273 | Simple x `elem` inter = simp (eqsB ++ [eq]) eqsA
274 | otherwise = simp eqsBS eqsAS
275 where (eqsBS, eqsAS) = subst2 (Simple x) a eqsB eqsA
276
277 -- | @ simp2 @ removes the equations of form @ a = X @
278 -- for something as @ X @ and for any @ a @
279 -- that belong to the interface,
280 -- substituting @ a @ by @ X @ in the interface.
281 simp2 :: Interface -> [Equation] -> ([Equation], Interface)
282 simp2 i = foldl f2 ([],i)
283 f2 :: ([Equation], Interface) -> Equation -> ([Equation], Interface)
284 f2 (eqsB, i) (Simple x , a)
285 | Simple x `elem` i = (eqsB, a : delete (Simple x) i)
286 | otherwise = error "unexpected case in the simplification of a net: free edge don't belong to the interface"
287 f2 (eqsB, i) eq = (eqsB ++ [eq], i)
288
289 -- | It's known that exactly one occurency of the edge will be found
290 -- in the equations (eqsB ++ eqsA).
291 -- In the future the function will be optimize for this invariant.
292 -- Now it simply transverse the whole tree and replaces in the correct place.
293 subst2 :: Term -> Term -> [Equation] -> [Equation]
294 -> ([Equation], [Equation])
295 subst2 (Compound _) _ _ _ = error "unexpected case"
296 subst2 (Simple x) rhs eqsB eqsA = (subst eqsB, subst eqsA)
297 where subst :: [Equation] -> [Equation]
298 subst = map (substTerm >< substTerm)
299
300 -- | Substitution in terms; t[rhs\/x]
301 -- with t the first argument of substTerm
302 -- the occurence of variable @ x @ in term @ t @
303 -- is replaced by term @ rhs @.
304 substTerm (Simple a) | a == x = rhs
305 | otherwise = Simple a
306 substTerm (Compound c) = Compound . substNA $ c
307
308 substNA (agent, args) = (agent, map substTerm args)
309
310
311 filterRules :: Net -> Net
312 filterRules net = net { equations = [], interface = [] }
313
314 filterNet :: Net -> Net
315 filterNet net = net { rules = []}