1
1
module Statebox.Core.WiringTree where
2
2
3
3
import Prelude
4
- import Data.Array (head )
4
+ import Control.Apply (lift3 )
5
+ import Data.Array (head , length , partition , range )
6
+ import Data.Either (Either (..), either )
5
7
import Data.Maybe (Maybe )
8
+ import Data.Tuple.Nested ((/\))
6
9
7
- import Statebox.Core.Types (Diagram , Net , Wiring )
10
+ import Data.ArrayMultiset (ArrayMultiset )
11
+ import Data.Petrinet.Representation.NLL (ErrNetEncoding , TransitionF' , fromNLL )
12
+ import Statebox.Core.Execution (Path )
13
+ import Statebox.Core.Types (Diagram , Net , PID , TID , Wiring )
8
14
9
15
data WiringTree
10
16
= Net Net
@@ -14,3 +20,60 @@ data WiringTree
14
20
-- | For the moment, we forget about diagrams and gluings and we consider only simple nets
15
21
wiringToWiringTree :: Wiring -> Maybe WiringTree
16
22
wiringToWiringTree wiring = Net <$> head wiring.nets
23
+
24
+ type Transition =
25
+ { path :: Path
26
+ , transition :: TID
27
+ , name :: String
28
+ }
29
+
30
+ data Glued a
31
+ = Untouched a
32
+ | Initial a
33
+ | Final a
34
+ | Glued a a
35
+
36
+ isInitial :: forall a . Glued a -> Boolean
37
+ isInitial = case _ of
38
+ Initial a -> true
39
+ _ -> false
40
+
41
+ isFinal :: forall a . Glued a -> Boolean
42
+ isFinal = case _ of
43
+ Final a -> true
44
+ _ -> false
45
+
46
+ data LinerisationError
47
+ = DiagramNotYetAllowed
48
+ | NLLDecodingFailed ErrNetEncoding
49
+
50
+ linearise :: WiringTree -> Either LinerisationError (Array (Glued Transition ))
51
+ linearise (Net net) = lineariseNet net
52
+ linearise (Diagram diagram branches) = Left DiagramNotYetAllowed
53
+
54
+ lineariseNet :: Net -> Either LinerisationError (Array (Glued Transition ))
55
+ lineariseNet net = linearisePartitionsAndNames net.partition net.names
56
+
57
+ linearisePartitionsAndNames :: ArrayMultiset PID -> Array String -> Either LinerisationError (Array (Glued Transition ))
58
+ linearisePartitionsAndNames partition names =
59
+ either (NLLDecodingFailed >>> Left ) (Right <<< flip lineriseTransitionsAndNames names) $ fromNLL 0 partition
60
+
61
+ -- the use of `lift3` does not consider the fact that the arrays could in principle have different lenghts
62
+ lineriseTransitionsAndNames :: Array (TransitionF' PID ) -> Array String -> Array (Glued Transition )
63
+ lineriseTransitionsAndNames transitions names =
64
+ sortInitialFinal $ lift3 buildGluedTransition (range 0 (length transitions - 1 )) transitions names
65
+
66
+ buildGluedTransition :: TID -> TransitionF' PID -> String -> Glued Transition
67
+ buildGluedTransition tId (inputs /\ outputs) name =
68
+ case (inputs /\ outputs) of
69
+ ([] /\ _ ) -> Initial { name: name, path: [0 , 0 , 0 ], transition: tId } -- the path is [0, 0, 0] because we consider a trivial diagram to be there
70
+ (_ /\ [] ) -> Final { name: name, path: [0 , 0 , 0 ], transition: tId }
71
+ (inp /\ out) -> Untouched { name: name, path: [0 , 0 , 0 ], transition: tId }
72
+
73
+ -- | we are using this custom function instead of `sortBy` because that does not guarantee
74
+ -- | the order of equal things to be preserved
75
+ sortInitialFinal :: forall a . Array (Glued a ) -> Array (Glued a )
76
+ sortInitialFinal gluedItems =
77
+ let { no: notInitial , yes: initial } = partition isInitial gluedItems
78
+ { no: notInitialAndFinal, yes: final } = partition isFinal notInitial
79
+ in initial <> notInitialAndFinal <> final
0 commit comments