Reputation:
I recently started learning Ada. I want to see if there's a possibility in creating a Boost::Statechart
-like framework in Ada. To do this I need a record structure with a constant access-to-object-of-parent-type component, like a tree node that statically points to another tree node, and the parent pointer must not be changed at all times. Something like this:
-- Not working sample
type Node_T is record
Parent : constant access Node_T;
-- error: constant components are not permitted
end record;
-- I wish to create objects of this type like this
Top_Node : Node_T (null);
Child1_Node : Node_T (Top_Node'Access);
Child2_Node : Node_T (Top_Node'Access);
It seems that constant member fields are not supported in Ada. So I resorted to using access discriminants:
-- Not working sample
type Node_T (Parent : access Node_T) is null record;
-- error: type declaration cannot refer to itself
However, using named-access-type as discriminant works
type Node_T;
type Ref_Node_T is access all Node_T;
type Node_T (Parent : Ref_Node_T) is null record;
However, from what I learned this causes the life-time of Node_T
objects to be bound to that of a Ref_Node_T
object, rather than another parent Node_T
object. Is this true?
Are there any better ways of implementing what I need?
Upvotes: 1
Views: 288
Reputation: 4198
An alternate alternate solution for FSM is to use enumerations and arrays, and if you're going to need more than one, generic
.
Generic
Type State is (<>); -- Any discrete type.
Type Event is (<>);
Package Finite_State_Machine_Domain is
Type Domain is Array(State, Event) of State;
Generic
Start,
Error : State;
Package Finite_State_Machine is
Type State_Machine is private;
Function Create (State_Map : Domain) return State_Machine;
Function Get_State (Object : in State_Machine) return State;
Procedure Send_Event(Object : in out State_Machine; Transition : in Event);
Private
Type State_Machine is record
Current : State := Start;
State_Map : Domain := (Others => Error);
End record;
End Finite_State_Machine;
End Finite_State_Machine_Domain;
Package Body Finite_State_Machine_Domain is
Package Body Finite_State_Machine is
Function Create (State_Map : Domain) return State_Machine is
( State_Machine'(State_Map => State_Map, Others => <>) );
Function Get_State (Object : in State_Machine) return State is
( Object.Current );
Procedure Send_Event(Object : in out State_Machine; Transition : in Event) is
Begin
if Object.Current /= Error then
Object.Current:= Object.State_Map(Object.Current, Transition);
end if;
End Send_Event;
End Finite_State_Machine;
End Finite_State_Machine_Domain;
Upvotes: 0
Reputation: 5021
An alternate approach to creating a finite state machine is described in https://www.sigada.org/ada_letters/june2000/sanden.pdf This solution uses a combination of protected objects and tasks to implement the finite state machine.
Upvotes: 1