--      Gas Station is a particular example of a general
--      problem of protecting resources. In this case, the
--      Pump is the resource, and the Operator is the
--      scheduler.

--      types of objects in the problem.

  type Dollars is integer; -- enum '0', 1, 2, 3 end enum;
  type Gallons is integer; -- enum 0, 1, 2, 3 end enum;

  type Pump is interface
  action in  On(), Off(), Activate(Cost : Dollars);
         out     Report(Amount : Gallons;
                          Cost : Dollars);
  behavior
      Free : var Boolean := True;
      Reading, Limit : var Dollars := 0;
      action In_Use(), Done();
  begin
     (?X : Dollars)(On ~ Activate(?X)) where $Free => Free := False;
                                                         Limit := ?X;
                                                         In_Use;;
     In_Use => Reading := $Limit; Done;;
       Off or Done  => Free := True; Report($Reading);;
--  constraint
-- foo
  end Pump;

  type Customer is interface
  action out Pre_Pay(Cost : Dollars),
             Turn_On(), Walk(), Turn_Off();
         in  Okay(), Change(Cost : Dollars);
  behavior
     D : Dollars is 10;
  begin
     start => Pre_Pay(D);;
     Okay  => Walk;;
     Walk  => Turn_On;;
--  constraint

  end Customer;

  type Operator is interface
  action in  Request(Cost : Dollars),
             Result(Cost : Dollars);
         out Schedule(Cost : Dollars),
             Remit(Change : Dollars);
  behavior
     Payment : var Dollars := 0;
  begin
     (?X : Dollars)Request(?X) => Payment := ?X; Schedule(?X);;
     (?X : Dollars)Result(?X) => Remit($Payment - ?X);;
--  constraint

  end;

-- main unit
  architecture gas_station1() return root
  is
     O : Operator;
     P : Pump;
     C1, C2 : Customer;
  connect
     (?C : Customer; ?X : Dollars) ?C.Pre_Pay(?X) => O.Request(?X);
     (?X : Dollars) O.Schedule(?X) => P.Activate(?X);
     (?X : Dollars) O.Schedule(?X) => C1.Okay;  -- change this
     (?C : Customer) ?C.Turn_On => P.On;
     (?C : Customer) ?C.Turn_Off => P.Off;
--     (?C : Customer; ?X : Dollars) O.Remit(?X) => ?C.Change(?X);
     (?X : Gallons; ?Y : Dollars)P.Report(?X, ?Y) => O.Result(?Y);
  end gas_station1;
