data module Products
begin
    exports
    begin
	sorts
	    PRODUCT
	functions
	    A : -> PRODUCT
	    B : -> PRODUCT
    end
end Products

data module Stations
begin
    exports
    begin
	sorts
	    STATION
	functions
	    1 : -> STATION
	    2 : -> STATION
	    3 : -> STATION
	    4 : -> STATION
	    5 : -> STATION
	    6 : -> STATION
	    eq-stat : STATION # STATION -> BOOLEAN
	    next : STATION # PRODUCT -> STATION
    end
    imports
	Booleans, Products
    variables
	x : -> STATION
	y : -> STATION
	p : -> PRODUCT
    equations
    [1] eq-stat(x, x) = true
    [2] not(eq-stat(x, y)) = true
    [3] next(1, p) = 2
    [4] next(2, p) = 3
    [5] next(3, A) = 4
    [6] next(3, B) = 5
    [7] next(4, p) = 5
    [8] next(5, p) = 6
end Stations

process module Factoryx
begin
    imports
	Stations
    atoms
	input : PRODUCT
	output : PRODUCT
	read-input : PRODUCT
	send-input : PRODUCT
	comm-input : PRODUCT
	read-output : PRODUCT
	send-output : PRODUCT
	comm-output : PRODUCT
	to-belt : STATION # STATION # PRODUCT
	from-belt : STATION # PRODUCT
	comm-belt : STATION # STATION # PRODUCT
    processes
	Start
	Input
	Stations
	Station : STATION
	Output
    sets
	of PRODUCT
	    PRODUCT-set = { A, B }
	of STATION
	    STATION-set = { 1, 2, 3, 4, 5, 6 }
	of atoms
	    H = { send-input(p), read-input(p), send-output(p), read-output(p),
		    to-belt(x, y, p), from-belt(y, p)  | p in PRODUCT,
		    x in STATION, y in STATION }
    communications
	send-input(p) | read-input(p) = comm-input(p)
	    for p in PRODUCT
	send-output(p) | read-output(p) = comm-output(p)
	    for p in PRODUCT
	to-belt(s1, s2, p) | from-belt(s2, p) = comm-belt(s1, s2, p)
	    for s1 in STATION, s2 in STATION, p in PRODUCT
    variables
	s : -> STATION
    definitions
	Start = encaps(H, Input || Stations || Output)
	Input = sum(p in PRODUCT-set, input(p) . send-input(p)) . Input
	Stations = merge(s in STATION-set, Station(s))
	Station(s) =
		[eq-stat(s, 1) = true] -> (
		    sum(p in PRODUCT,
			read-input(p) . to-belt(s, next(s, p), p)
		    ) . Station(s)
		)
	    +   [eq-stat(s, 6) = true] -> (
		    sum(p in PRODUCT,
			from-belt(s, p) . send-output(p)
		    ) . Station(s)
		)
	    +   [and(not(eq-stat(s, 1)), not(eq-stat(s, 6))) = true] -> (
		    sum(p in PRODUCT,
			from-belt(s, p) . (
			    [p = A] ->
				to-belt(s, next(s, A), p)
			+   [p = B] ->
				to-belt(s, next(s, B), p)
			)
		    ) . Station(s)
		)
	Output = sum(p in PRODUCT, read-output(p) . output(p)) . Output
end Factoryx
