See https://guitarvydas.github.io/2021/05/03/Software-Components-101.html for an introduction to the examples shown below.
https://github.com/guitarvydas/basicdasl
conn(Component,[Sender|SendingPort],[ReceivingComponent|ReceivingPort]) :-
connection(Component,ConnectionID),
sender(ConnectionID,SenderPairID),
pp(SenderPairID,SendingPort),
pc(SenderPairID,Sender),
receiver(ConnectionID,ReceiverPairID),
pc(ReceiverPairID,ReceivingComponent),
pp(ReceiverPairID,ReceivingPort).
allReceivers(Component,S,R) :-
setof(Receivers,conn(Component,S,Receivers),R).
conn(Component,'-->'(S,RBag)):-
allReceivers(Component, S, RBag).
conn(':'(C,W)) :-
conn(C,W).
The conn/1 query results in one connection (W) for a given component (C).
We repeat the query at the REPL (using semi-colon) to get all connections on a diagram.
[It is possible to write a query that returns all connections for all components, but the REPL version is sufficient for this essay.]
Each sender and each receiver is represented by a pair. Each pair is given a unique ID and each pair consists of two parts pc and pp, pair-component and pair-port, resp.
Fig. 1 Basic Component
=== signatures
[main] < (in) > (out)
=== components
[main]
[]
=== connections
[main]
[
[.].(in) -> [.].(out)
]
component("main",nil).
connection("main",n0).
inputPort("main","in").
outputPort("main","out").
pc(pair1,".").
pc(pair2,".").
pp(pair1,"in").
pp(pair2,"out").
receiver(n0,pair2).
sender(n0,pair1).
?- consult(fb).
true.
?- consult(q).
true.
?- conn(X).
X = "main":(["."|"in"]-->[["."|"out"]]).
?-
Fig. 2 Nested Component
=== signatures
[main] < (in) > (out)
=== components
[main]
[ [subcomponent] ]
=== connections
[main]
[
[.].(in) -> [subcomponent].(A)
[subcomponent].(B) -> [.].(out)
]
=== signatures
[subcomponent] < (A) > (B)
=== components
[subcomponent]
[]
=== connections
[subcomponent]
[]
component("main",nil).
component("subcomponent",nil).
connection("main",n0).
connection("main",n3).
contains("main","subcomponent").
inputPort("main","in").
inputPort("subcomponent","A").
outputPort("main","out").
outputPort("subcomponent","B").
pc(pair1,".").
pc(pair2,"subcomponent").
pc(pair4,"subcomponent").
pc(pair5,".").
pp(pair1,"in").
pp(pair2,"A").
pp(pair4,"B").
pp(pair5,"out").
receiver(n0,pair2).
receiver(n3,pair5).
sender(n0,pair1).
sender(n3,pair4).
?- consult(fb).
true.
?- consult(q).
true.
?- conn(X).
X = "main":(["."|"in"]-->[["subcomponent"|"A"]]) ;
X = "main":(["subcomponent"|"B"]-->[["."|"out"]]).
?-
Fig. 3 Component Nested in a Nested Component
=== signatures
[main] < (in) > (out)
=== components
[main]
[ [subcomponent] ]
=== connections
[main]
[
[.].(in) -> [subcomponent].(A)
[subcomponent].(B) -> [.].(out)
]
=== signatures
[subcomponent] < (A) > (*#)
=== components
[subcomponent]
[ [component X] ]
=== connections
[subcomponent]
[
[.].(A) -> [component X].(c)
[component X].(#) -> [.].(*#)
]
=== signatures
[component X] < (c) > (#)
=== components
[component X]
[]
=== connections
[component X]
[]
component("component_X",nil).
component("main",nil).
component("subcomponent",nil).
connection("main",n0).
connection("main",n3).
connection("subcomponent",n6).
connection("subcomponent",n9).
contains("main","subcomponent").
contains("subcomponent","component_X").
inputPort("component_X","c").
inputPort("main","in").
inputPort("subcomponent","A").
outputPort("component_X","o_").
outputPort("main","out").
outputPort("subcomponent","so_").
pc(pair1,".").
pc(pair10,"component_X").
pc(pair11,".").
pc(pair2,"subcomponent").
pc(pair4,"subcomponent").
pc(pair5,".").
pc(pair7,".").
pc(pair8,"component_X").
pp(pair1,"in").
pp(pair10,"o_").
pp(pair11,"so_").
pp(pair2,"A").
pp(pair4,"B").
pp(pair5,"out").
pp(pair7,"A").
pp(pair8,"c").
receiver(n0,pair2).
receiver(n3,pair5).
receiver(n6,pair8).
receiver(n9,pair11).
sender(n0,pair1).
sender(n3,pair4).
sender(n6,pair7).
sender(n9,pair10).
?- consult(fb).
true.
?- consult(q).
true.
?- conn(X).
X = "main":(["."|"in"]-->[["subcomponent"|"A"]]) ;
X = "main":(["subcomponent"|"so_"]-->[["."|"out"]]) ;
X = "subcomponent":(["."|"A"]-->[["component_X"|"c"]]) ;
X = "subcomponent":(["component_X"|"o_"]-->[["."|"so_"]]).
?-
Fig. 4 Copied Component
=== signatures
[main] < (in) > (out)
=== components
[main]
[ [subcomponent] ]
=== connections
[main]
[
[.].(in) -> [1].(A),[2].(A)
[1].(*#) -> [.].(out)
[2].(*#) -> [.].(out)
]
=== signatures
[subcomponent] < (A) > (*#)
=== components
[subcomponent]
[ [component X] ]
=== connections
[subcomponent]
[
[.].(A) -> [component X].(c)
[component X].(#) -> [.].(*#)
]
=== signatures
[component X] < (c) > (#)
=== components
[component X]
[]
=== connections
[component X]
[]
component("component_X",nil).
component("main",nil).
component("subcomponent",nil).
connection("main",n0).
connection("main",n4).
connection("main",n7).
connection("subcomponent",n10).
connection("subcomponent",n13).
contains("main","subcomponent").
contains("subcomponent","component_X").
inputPort("component_X","c").
inputPort("main","in").
inputPort("subcomponent","A").
outputPort("component_X","o_").
outputPort("main","out").
outputPort("subcomponent","so_").
pc(pair1,".").
pc(pair11,".").
pc(pair12,"component_X").
pc(pair14,"component_X").
pc(pair15,".").
pc(pair2,"1").
pc(pair3,"2").
pc(pair5,"1").
pc(pair6,".").
pc(pair8,"2").
pc(pair9,".").
pp(pair1,"in").
pp(pair11,"A").
pp(pair12,"c").
pp(pair14,"o_").
pp(pair15,"so_").
pp(pair2,"A").
pp(pair3,"A").
pp(pair5,"so_").
pp(pair6,"out").
pp(pair8,"so_").
pp(pair9,"out").
receiver(n0,pair2).
receiver(n0,pair3).
receiver(n10,pair12).
receiver(n13,pair15).
receiver(n4,pair6).
receiver(n7,pair9).
sender(n0,pair1).
sender(n10,pair11).
sender(n13,pair14).
sender(n4,pair5).
sender(n7,pair8).
?- consult(fb).
true.
?- consult(q).
true.
?- conn(X).
X = "main":(["."|"in"]-->[["1"|"A"], ["2"|"A"]]) ;
X = "main":(["1"|"so_"]-->[["."|"out"]]) ;
X = "main":(["2"|"so_"]-->[["."|"out"]]) ;
X = "subcomponent":(["."|"A"]-->[["component_X"|"c"]]) ;
X = "subcomponent":(["component_X"|"o_"]-->[["."|"so_"]]).
?-
Fig. 5 Copied Component
Diagram Fig. 5 is the same as Fig. 4.
At this point, we are not changing the diagram, we will only be changing the .dasl file…
=== signatures
[main] < (in) > (out)
[subcomponent] < (A) > (*#)
[component X] < (c) > (#)
=== components
[main]
[ [subcomponent] ]
[subcomponent]
[ [component X] ]
[component X]
[]
=== connections
[main]
[
[.].(in) -> [1].(A),[2].(A)
[1].(*#) -> [.].(out)
[2].(*#) -> [.].(out)
]
[subcomponent]
[
[.].(A) -> [component X].(c)
[component X].(#) -> [.].(*#)
]
[component X]
[]
In this .dasl file, we squash all of the signatures / components / connections together, but, otherwise this .dasl file represents the same constructs as in Copied Component.
component("component_X",nil).
component("main",nil).
component("subcomponent",nil).
connection("main",n0).
connection("main",n4).
connection("main",n7).
connection("subcomponent",n10).
connection("subcomponent",n13).
contains("main","subcomponent").
contains("subcomponent","component_X").
inputPort("component_X","c").
inputPort("main","in").
inputPort("subcomponent","A").
outputPort("component_X","o_").
outputPort("main","out").
outputPort("subcomponent","so_").
pc(pair1,".").
pc(pair11,".").
pc(pair12,"component_X").
pc(pair14,"component_X").
pc(pair15,".").
pc(pair2,"1").
pc(pair3,"2").
pc(pair5,"1").
pc(pair6,".").
pc(pair8,"2").
pc(pair9,".").
pp(pair1,"in").
pp(pair11,"A").
pp(pair12,"c").
pp(pair14,"o_").
pp(pair15,"so_").
pp(pair2,"A").
pp(pair3,"A").
pp(pair5,"so_").
pp(pair6,"out").
pp(pair8,"so_").
pp(pair9,"out").
receiver(n0,pair2).
receiver(n0,pair3).
receiver(n10,pair12).
receiver(n13,pair15).
receiver(n4,pair6).
receiver(n7,pair9).
sender(n0,pair1).
sender(n10,pair11).
sender(n13,pair14).
sender(n4,pair5).
sender(n7,pair8).
?- consult(fb).
true.
?- consult(q).
true.
?- conn(X).
X = "main":(["."|"in"]-->[["1"|"A"], ["2"|"A"]]) ;
X = "main":(["1"|"so_"]-->[["."|"out"]]) ;
X = "main":(["2"|"so_"]-->[["."|"out"]]) ;
X = "subcomponent":(["."|"A"]-->[["component_X"|"c"]]) ;
X = "subcomponent":(["component_X"|"o_"]-->[["."|"so_"]]).
?-
The queries return the same results as in Copied Component. We have changed nothing, except for the formatting (squashing) of the .dasl file.