note
	description: "A sequence of actions to be performed on call."
	legal: "See notice at end of class."
	instructions: "[
		Use features inherited from LIST to add/remove actions.
		An action is a procedure of ANY class that takes EVENT_DATA.
		When call is called the actions in the list will be executed
		in order stating at first.
		An action may call abort which will cause call to stop executing
		actions in the sequence. (Until the next call to call).
		Descendants may redefine initialize to arrange for call to
		be called by an event source.
		Use block, pause, flush and resume to change the behavior
		of call.
		eg.
		 birthday_data: TUPLE [INTEGER, STRING] -- (age, name)
		 birthday_actions: ACTION_SEQUENCE [like birthday_data]
		 create birthday_actions.make ("birthday", <<"age","name">>)
		 send_card (age: INTEGER, name, from: STRING) is ...
		 buy_gift (age: INTEGER, name, gift, from: STRING) is ...
		 birthday_actions.extend (agent send_card (?, ?, "Sam")
		 birthday_actions.extend (agent buy_gift (?, ?, "Wine", "Sam")
		 birthday_actions.call ([35, "Julia"])
		 causes call to: send_card (35, "Julia", "Sam")
		                 buy_gift (35, "Julia", "Wine", "Sam")
	]"
	status: "See notice at end of class."
	keywords: event, action
	date: "$Date: 2018-11-14 15:15:17 +0000 (Wed, 14 Nov 2018) $"
	revision: "$Revision: 102463 $"

class 
	ACTION_SEQUENCE [EVENT_DATA -> detachable TUPLE create default_create end]

create 
	default_create,
	make


create {ACTION_SEQUENCE}
	arrayed_list_make,
	make_filled

feature {NONE} -- Initialization

	default_create
			-- Begin in Normal_state.
		require -- from  ANY
			True
		do
			arrayed_list_make (0)
			state := Normal_state
		end

	make_empty_area (n: INTEGER_32)
			-- Creates a special object for n entries.
			-- (from TO_SPECIAL)
		require -- from TO_SPECIAL
			non_negative_argument: n >= 0
		do
			create area_v2.make_empty (n)
		ensure -- from TO_SPECIAL
			area_allocated: area_v2 /= Void
			capacity_set: area_v2.capacity = n
			count_set: area_v2.count = 0
		end

	make_filled_area (a_default_value: PROCEDURE [EVENT_DATA]; n: INTEGER_32)
			-- Creates a special object for n entries.
			-- (from TO_SPECIAL)
		require -- from TO_SPECIAL
			non_negative_argument: n >= 0
		do
			create area_v2.make_filled (a_default_value, n)
		ensure -- from TO_SPECIAL
			area_allocated: area_v2 /= Void
			capacity_set: area_v2.capacity = n
			count_set: area_v2.count = n
			area_filled: area_v2.filled_with (a_default_value, 0, n - 1)
		end

	make_from_array (a: ARRAY [like item])
			-- Create list from array a.
			-- (from INTERACTIVE_LIST)
		require -- from ARRAYED_LIST
			array_exists: a /= Void
		local
			l_index: INTEGER_32
		do
			arrayed_list_make (a.count)
			from
				l_index := a.lower
			until
				l_index > a.upper
			loop
				extend (a.item (l_index))
				l_index := l_index + 1
			end
		ensure -- from ARRAYED_LIST
			shared: area = a.area
			correct_position: before
			filled: count = a.count
		end

	make_from_iterable (other: ITERABLE [PROCEDURE [EVENT_DATA]])
			-- Create a circular chain with all items obtained from other.
			-- (from ARRAYED_LIST)
		local
			a: like area_v2
			i, n: like area_v2.count
		do
			n := estimated_count_of (other)
			arrayed_list_make (n)
			a := area_v2
			across
				other as o
			loop
				i := i + 1
				if i > n then
					n := i
					a := a.aliased_resized_area (n)
					area_v2 := a
				end;
				a.extend (o.item)
			end
		end
	
feature -- Initialization

	arrayed_list_make (n: INTEGER_32)
			-- Allocate list with n items.
			-- (n may be zero for empty list.)
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			valid_number_of_items: n >= 0
		do
			index := 0
			create area_v2.make_empty (n)
		ensure -- from ARRAYED_LIST
			correct_position: before
			is_empty: is_empty
		end

	make_filled (n: INTEGER_32)
			-- Allocate list with n items.
			-- (n may be zero for empty list.)
			-- This list will be full.
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			valid_number_of_items: n >= 0
			has_default: ({PROCEDURE [EVENT_DATA]}).has_default
		do
			index := 0
			make_filled_area (({PROCEDURE [EVENT_DATA]}).default, n)
		ensure -- from ARRAYED_LIST
			correct_position: before
			filled: full
		end
	
feature -- Access

	area: SPECIAL [PROCEDURE [EVENT_DATA]]
			-- Access to internal storage of ARRAYED_LIST
			-- (from ARRAYED_LIST)
		do
			Result := area_v2
		end

	area_v2: SPECIAL [PROCEDURE [EVENT_DATA]]
			-- Special data zone.
			-- (from TO_SPECIAL)

	at alias "@" (i: INTEGER_32): like item assign put_i_th
			-- Item at i-th position
			-- Was declared in ARRAYED_LIST as synonym of i_th.
			-- (from ARRAYED_LIST)
		require -- from TABLE
			valid_key: valid_index (i)
		do
			Result := area_v2.item (i - 1)
		end

	array_at (i: INTEGER_32): PROCEDURE [EVENT_DATA] assign array_put
			-- Entry at index i, if in index interval.
			-- Was declared in TO_SPECIAL as synonym of item.
			-- (from TO_SPECIAL)
		require -- from TO_SPECIAL
			valid_index: array_valid_index (i)
		do
			Result := area_v2.item (i)
		end

	cursor: ARRAYED_LIST_CURSOR
			-- Current cursor position
			-- (from ARRAYED_LIST)
		do
			create Result.make (index)
		ensure -- from CURSOR_STRUCTURE
			cursor_not_void: Result /= Void
		end

	event_data_names: detachable ARRAY [STRING_8]
		obsolete "Not implemented. To be removed. [2017-05-31]"
			-- Textual description of each event datum.
		local
			i: like event_data_names_internal
		do
			i := event_data_names_internal
			if i /= Void then
				Result := i.deep_twin
			end
		ensure
			equal_to_event_data_names_internal: deep_equal (Result, event_data_names_internal)
		end

	first: like item
			-- Item at first position
			-- (from ARRAYED_LIST)
		require -- from CHAIN
			not_empty: not is_empty
		do
			Result := area_v2.item (0)
		end

	generating_type: TYPE [detachable ACTION_SEQUENCE [EVENT_DATA]]
			-- Type of current object
			-- (type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generating_type_not_void: Result /= Void
		end

	generator: STRING_8
			-- Name of current object's generating class
			-- (base class of the type of which it is a direct instance)
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			generator_not_void: Result /= Void
			generator_not_empty: not Result.is_empty
		end

	has (v: like item): BOOLEAN
			-- Does current include v?
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from ARRAYED_LIST)
		require -- from  CONTAINER
			True
		local
			l_area: like area_v2
			i, nb: INTEGER_32
		do
			l_area := area_v2
			nb := count
			if object_comparison and v /= Void then
				from
				until
					i >= nb or Result
				loop
					Result := v ~ l_area.item (i)
					i := i + 1
				end
			else
				from
				until
					i >= nb or Result
				loop
					Result := v = l_area.item (i)
					i := i + 1
				end
			end
		ensure -- from CONTAINER
			not_found_in_empty: Result implies not is_empty
		end

	sequential_has (v: like item): BOOLEAN
			-- Does structure include an occurrence of v?
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from LINEAR)
		require -- from  CONTAINER
			True
		do
			start
			if not off then
				search (v)
			end
			Result := not exhausted
		ensure -- from CONTAINER
			not_found_in_empty: Result implies not is_empty
		end

	i_th alias "[]" (i: INTEGER_32): like item assign put_i_th
			-- Item at i-th position
			-- Was declared in ARRAYED_LIST as synonym of at.
			-- (from ARRAYED_LIST)
		require -- from TABLE
			valid_key: valid_index (i)
		require -- from READABLE_INDEXABLE
			valid_index: valid_index (i)
		do
			Result := area_v2.item (i - 1)
		end

	index: INTEGER_32
			-- Index of item, if valid.
			-- (from ARRAYED_LIST)

	sequential_index_of (v: like item; i: INTEGER_32): INTEGER_32
			-- Index of i-th occurrence of v.
			-- 0 if none.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from LINEAR)
		require -- from LINEAR
			positive_occurrences: i > 0
		local
			occur, pos: INTEGER_32
		do
			if object_comparison and v /= Void then
				from
					start
					pos := 1
				until
					exhausted or (occur = i)
				loop
					if item ~ v then
						occur := occur + 1
					end
					forth
					pos := pos + 1
				end
			else
				from
					start
					pos := 1
				until
					exhausted or (occur = i)
				loop
					if item = v then
						occur := occur + 1
					end
					forth
					pos := pos + 1
				end
			end
			if occur = i then
				Result := pos - 1
			end
		ensure -- from LINEAR
			non_negative_result: Result >= 0
		end

	index_of (v: like item; i: INTEGER_32): INTEGER_32
			-- Index of i-th occurrence of item identical to v.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- 0 if none.
			-- (from CHAIN)
		local
			pos: CURSOR
		do
			pos := cursor
			Result := sequential_index_of (v, i)
			go_to (pos)
		end

	array_item (i: INTEGER_32): PROCEDURE [EVENT_DATA] assign array_put
			-- Entry at index i, if in index interval.
			-- Was declared in TO_SPECIAL as synonym of at.
			-- (from TO_SPECIAL)
		require -- from TO_SPECIAL
			valid_index: array_valid_index (i)
		do
			Result := area_v2.item (i)
		end

	item: PROCEDURE [EVENT_DATA]
			-- Current item
			-- (from ARRAYED_LIST)
		require -- from ACTIVE
			readable: readable
		require -- from TRAVERSABLE
			not_off: not off
		require else -- from ARRAYED_LIST
			index_is_valid: valid_index (index)
		do
			Result := area_v2.item (index - 1)
		end

	item_for_iteration: PROCEDURE [EVENT_DATA]
			-- Item at current position
			-- (from LINEAR)
		require -- from LINEAR
			not_off: not off
		do
			Result := item
		end

	last: like first
			-- Item at last position
			-- (from ARRAYED_LIST)
		require -- from CHAIN
			not_empty: not is_empty
		do
			Result := area_v2.item (count - 1)
		end

	name: detachable STRING_8
			-- Textual description.
		local
			i: like name_internal
		do
			i := name_internal
			if i /= Void then
				Result := i.twin
			end
		ensure
			equal_to_name_internal: Result ~ name_internal
		end

	new_cursor: ARRAYED_LIST_ITERATION_CURSOR [PROCEDURE [EVENT_DATA]]
			-- Fresh cursor associated with current structure
			-- (from ARRAYED_LIST)
		require -- from  ITERABLE
			True
		do
			create Result.make (Current)
		ensure -- from ITERABLE
			result_attached: Result /= Void
		end

	sequential_occurrences (v: like item): INTEGER_32
			-- Number of times v appears.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from LINEAR)
		require -- from  BAG
			True
		do
			from
				start
				search (v)
			until
				exhausted
			loop
				Result := Result + 1
				forth
				search (v)
			end
		ensure -- from BAG
			non_negative_occurrences: Result >= 0
		end

	to_array: ARRAY [PROCEDURE [EVENT_DATA]]
			-- Share content to be used as an ARRAY.
			-- Note that although the content is shared, it might
			-- not be shared when a resizing occur in either ARRAY or Current.
			-- (from ARRAYED_LIST)
		do
			create Result.make_from_special (area_v2)
		ensure -- from ARRAYED_LIST
			to_array_attached: Result /= Void
			array_lower_set: Result.lower = 1
			array_upper_set: Result.upper = count
			shared_area: Result.area = area
		end
	
feature -- Measurement

	additional_space: INTEGER_32
			-- Proposed number of additional items
			-- (from RESIZABLE)
		do
			Result := (capacity // 2).max (Minimal_increase)
		ensure -- from RESIZABLE
			at_least_one: Result >= 1
		end

	capacity: INTEGER_32
			-- Number of items that may be stored
			-- (from ARRAYED_LIST)
		do
			Result := area_v2.capacity
		ensure -- from BOUNDED
			capacity_non_negative: Result >= 0
		end

	count: INTEGER_32
			-- Number of items.
			-- (from ARRAYED_LIST)
		require -- from  FINITE
			True
		require -- from  READABLE_INDEXABLE
			True
		do
			Result := area_v2.count
		ensure -- from FINITE
			count_non_negative: Result >= 0
		end

	Growth_percentage: INTEGER_32 = 50
			-- Percentage by which structure will grow automatically
			-- (from RESIZABLE)

	index_set: INTEGER_INTERVAL
		obsolete "Use `lower' and `upper' instead. [2017-05-31]"
			-- Range of acceptable indexes.
			-- (from READABLE_INDEXABLE)
		do
			create Result.make (Lower, count)
		ensure -- from READABLE_INDEXABLE
			not_void: Result /= Void
			empty_if_not_in_order: (Lower > count) implies Result.is_empty
			same_lower_if_not_empty: (Lower <= count) implies Result.lower = Lower
			same_upper_if_not_empty: (Lower <= count) implies Result.upper = count
		end

	Lower: INTEGER_32 = 1
			-- Minimum index.
			-- (from CHAIN)

	Minimal_increase: INTEGER_32 = 5
			-- Minimal number of additional items
			-- (from RESIZABLE)

	occurrences (v: like item): INTEGER_32
			-- Number of times v appears.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from CHAIN)
		local
			pos: CURSOR
		do
			pos := cursor
			Result := sequential_occurrences (v)
			go_to (pos)
		end

	upper: INTEGER_32
			-- Maximum index.
			-- Use count instead.
			-- (from ARRAYED_LIST)
		do
			Result := area_v2.count
		ensure -- from ARRAYED_LIST
			definition: Result = count
		end
	
feature {NONE} -- Measurement

	estimated_count_of (other: ITERABLE [PROCEDURE [EVENT_DATA]]): INTEGER_32
			-- Estimated number of elements in other.
			-- (from CONTAINER)
		do
			if attached {FINITE [PROCEDURE [EVENT_DATA]]} other as f then
				Result := f.count
			elseif attached {READABLE_INDEXABLE [PROCEDURE [EVENT_DATA]]} other as r then
				Result := r.upper - r.lower + 1
			end
		ensure -- from CONTAINER
			instance_free: class
			non_negative_result: Result >= 0
		end
	
feature -- Comparison

	frozen deep_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void
			-- or attached to isomorphic object structures?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_deep_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			shallow_implies_deep: standard_equal (a, b) implies Result
			both_or_none_void: (a = Void) implies (Result = (b = Void))
			same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b))
			symmetric: Result implies deep_equal (b, a)
		end

	frozen equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached
			-- to objects considered equal?
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.is_equal (b))
		end

	frozen is_deep_equal alias "≡≡≡" (other: ACTION_SEQUENCE [EVENT_DATA]): BOOLEAN
			-- Are Current and other attached to isomorphic object structures?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			shallow_implies_deep: standard_is_equal (other) implies Result
			same_type: Result implies same_type (other)
			symmetric: Result implies other.is_deep_equal (Current)
		end

	is_equal (other: ACTION_SEQUENCE [EVENT_DATA]): BOOLEAN
			-- Is array made of the same items as other?
			-- (from ARRAYED_LIST)
		require -- from ANY
			other_not_void: other /= Void
		local
			i: INTEGER_32
		do
			if other = Current then
				Result := True
			elseif count = other.count and then object_comparison = other.object_comparison then
				if object_comparison then
					from
						Result := True
						i := Lower
					until
						not Result or i > upper
					loop
						Result := i_th (i) ~ other.i_th (i)
						i := i + 1
					end
				else
					Result := area_v2.same_items (other.area_v2, 0, 0, count)
				end
			end
		ensure -- from ANY
			symmetric: Result implies other ~ Current
			consistent: standard_is_equal (other) implies Result
		ensure then -- from LIST
			indices_unchanged: index = old index and other.index = old other.index
			true_implies_same_size: Result implies count = other.count
		end

	frozen standard_equal (a: detachable ANY; b: like arg #1): BOOLEAN
			-- Are a and b either both void or attached to
			-- field-by-field identical objects of the same type?
			-- Always uses default object comparison criterion.
			-- (from ANY)
		do
			if a = Void then
				Result := b = Void
			else
				Result := b /= Void and then a.standard_is_equal (b)
			end
		ensure -- from ANY
			instance_free: class
			definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.standard_is_equal (b))
		end

	frozen standard_is_equal alias "≜" (other: ACTION_SEQUENCE [EVENT_DATA]): BOOLEAN
			-- Is other attached to an object of the same type
			-- as current object, and field-by-field identical to it?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			same_type: Result implies same_type (other)
			symmetric: Result implies other.standard_is_equal (Current)
		end
	
feature -- Status report

	after: BOOLEAN
			-- Is there no valid cursor position to the right of cursor?
			-- (from LIST)
		require -- from  LINEAR
			True
		do
			Result := index = count + 1
		end

	all_default: BOOLEAN
			-- Are all items set to default values?
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			has_default: ({PROCEDURE [EVENT_DATA]}).has_default
		do
			Result := area_v2.filled_with (({PROCEDURE [EVENT_DATA]}).default, 0, area_v2.upper)
		end

	before: BOOLEAN
			-- Is there no valid cursor position to the left of cursor?
			-- (from LIST)
		require -- from  BILINEAR
			True
		do
			Result := index = 0
		end

	Blocked_state: INTEGER_32 = 3

	call_is_underway: BOOLEAN
			-- Is call currently being executed?
		do
			Result := not is_aborted_stack.is_empty
		ensure
				Result = not is_aborted_stack.is_empty
		end

	changeable_comparison_criterion: BOOLEAN
			-- May object_comparison be changed?
			-- (Answer: yes by default.)
			-- (from CONTAINER)
		do
			Result := True
		end

	conforms_to (other: ANY): BOOLEAN
			-- Does type of current object conform to type
			-- of other (as per Eiffel: The Language, chapter 13)?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		end

	empty: BOOLEAN
		obsolete "ELKS 2000: Use `is_empty' instead. [2017-05-31]"
			-- Is there no element?
			-- (from CONTAINER)
		do
			Result := is_empty
		end

	exhausted: BOOLEAN
			-- Has structure been completely explored?
			-- (from LINEAR)
		do
			Result := off
		ensure -- from LINEAR
			exhausted_when_off: off implies Result
		end

	extendible: BOOLEAN
			-- May new items be added? (Answer: yes.)
			-- (from DYNAMIC_CHAIN)
		require -- from  COLLECTION
			True
		do
			Result := True
		end

	full: BOOLEAN
			-- Is structure full?
			-- (from BOUNDED)
		require -- from  BOX
			True
		do
			Result := count = capacity
		end

	is_empty: BOOLEAN
			-- Is structure empty?
			-- (from FINITE)
		do
			Result := count = 0
		end

	is_inserted (v: PROCEDURE [EVENT_DATA]): BOOLEAN
			-- Has v been inserted at the end by the most recent put or
			-- extend?
			-- (from ARRAYED_LIST)
		do
			if not is_empty then
				Result := (v = last) or else (not off and then (v = item))
			end
		end

	isfirst: BOOLEAN
			-- Is cursor at first position?
			-- (from CHAIN)
		do
			Result := not is_empty and (index = 1)
		ensure -- from CHAIN
			valid_position: Result implies not is_empty
		end

	islast: BOOLEAN
			-- Is cursor at last position?
			-- (from CHAIN)
		do
			Result := not is_empty and (index = count)
		ensure -- from CHAIN
			valid_position: Result implies not is_empty
		end

	Normal_state: INTEGER_32 = 1

	object_comparison: BOOLEAN
			-- Must search operations use equal rather than =
			-- for comparing references? (Default: no, use =.)
			-- (from CONTAINER)

	off: BOOLEAN
			-- Is there no current item?
			-- (from CHAIN)
		require -- from  TRAVERSABLE
			True
		do
			Result := (index = 0) or (index = count + 1)
		end

	Paused_state: INTEGER_32 = 2

	prunable: BOOLEAN
			-- May items be removed? (Answer: yes.)
			-- (from ARRAYED_LIST)
		require -- from  COLLECTION
			True
		do
			Result := True
		end

	readable: BOOLEAN
			-- Is there a current item that may be read?
			-- (from SEQUENCE)
		require -- from  ACTIVE
			True
		do
			Result := not off
		end

	replaceable: BOOLEAN
			-- Can current item be replaced?
			-- (from ACTIVE)
		do
			Result := True
		end

	resizable: BOOLEAN
			-- May capacity be changed? (Answer: yes.)
			-- (from RESIZABLE)
		do
			Result := True
		end

	same_type (other: ANY): BOOLEAN
			-- Is type of current object identical to type of other?
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		external
			"built_in"
		ensure -- from ANY
			definition: Result = (conforms_to (other) and other.conforms_to (Current))
		end

	state: INTEGER_32
			-- One of Normal_state Paused_state or Blocked_state

	valid_cursor (p: CURSOR): BOOLEAN
			-- Can the cursor be moved to position p?
			-- (from ARRAYED_LIST)
		do
			if attached {ARRAYED_LIST_CURSOR} p as al_c then
				Result := valid_cursor_index (al_c.index)
			end
		end

	valid_cursor_index (i: INTEGER_32): BOOLEAN
			-- Is i correctly bounded for cursor movement?
			-- (from CHAIN)
		do
			Result := (i >= 0) and (i <= count + 1)
		ensure -- from CHAIN
			valid_cursor_index_definition: Result = ((i >= 0) and (i <= count + 1))
		end

	valid_index (i: INTEGER_32): BOOLEAN
			-- Is i a valid index?
			-- (from ARRAYED_LIST)
		require -- from  READABLE_INDEXABLE
			True
		require -- from  TABLE
			True
		do
			Result := (1 <= i) and (i <= count)
		ensure -- from READABLE_INDEXABLE
			only_if_in_index_set: Result implies (Lower <= i and i <= count)
		ensure then -- from CHAIN
			valid_index_definition: Result = ((i >= 1) and (i <= count))
		end

	array_valid_index (i: INTEGER_32): BOOLEAN
			-- Is i within the bounds of Current?
			-- (from TO_SPECIAL)
		do
			Result := area_v2.valid_index (i)
		end

	writable: BOOLEAN
			-- Is there a current item that may be modified?
			-- (from SEQUENCE)
		require -- from  ACTIVE
			True
		do
			Result := not off
		end
	
feature -- Status setting

	abort
			-- Abort the current call.
			-- (The current item.call will be completed.)
		require
			call_is_underway: call_is_underway
		do
			is_aborted_stack.replace (True)
		ensure
			is_aborted_set: is_aborted_stack.item
		end

	block
			-- Ignore subsequent calls.
		do
			state := Blocked_state
		ensure
			blocked_state: state = Blocked_state
		end

	compare_objects
			-- Ensure that future search operations will use equal
			-- rather than = for comparing references.
			-- (from CONTAINER)
		require -- from CONTAINER
			changeable_comparison_criterion: changeable_comparison_criterion
		do
			object_comparison := True
		ensure -- from CONTAINER
				object_comparison
		end

	compare_references
			-- Ensure that future search operations will use =
			-- rather than equal for comparing references.
			-- (from CONTAINER)
		require -- from CONTAINER
			changeable_comparison_criterion: changeable_comparison_criterion
		do
			object_comparison := False
		ensure -- from CONTAINER
			reference_comparison: not object_comparison
		end

	flush
			-- Discard any buffered calls.
		do
			call_buffer.wipe_out
		ensure
			call_buffer_empty: call_buffer.is_empty
		end

	pause
			-- Buffer subsequent calls for later execution.
			-- If is_blocked calls will simply be ignored.
		do
			state := Paused_state
		ensure
			paused_state: state = Paused_state
		end

	resume
			-- Used after block or pause to resume normal call
			-- execution.  Executes any buffered calls.
		local
			l_call_buffer: like call_buffer
		do
			state := Normal_state
			from
				l_call_buffer := call_buffer
			until
				l_call_buffer.is_empty
			loop
				call (l_call_buffer.item);
				l_call_buffer.remove
			end
		ensure
			normal_state: state = Normal_state
		end
	
feature -- Cursor movement

	back
			-- Move cursor one position backward.
			-- (from ARRAYED_LIST)
		require -- from BILINEAR
			not_before: not before
		do
			index := index - 1
		end

	finish
			-- Move cursor to last position if any.
			-- (from ARRAYED_LIST)
		require -- from  LINEAR
			True
		do
			index := count
		ensure then -- from CHAIN
			at_last: not is_empty implies islast
		ensure then -- from ARRAYED_LIST
			before_when_empty: is_empty implies before
		end

	forth
			-- Move cursor one position forward.
			-- (from ARRAYED_LIST)
		require -- from LINEAR
			not_after: not after
		do
			index := index + 1
		ensure then -- from LIST
			moved_forth: index = old index + 1
		end

	go_i_th (i: INTEGER_32)
			-- Move cursor to i-th position.
			-- (from ARRAYED_LIST)
		require -- from CHAIN
			valid_cursor_index: valid_cursor_index (i)
		do
			index := i
		ensure -- from CHAIN
			position_expected: index = i
		end

	go_to (p: CURSOR)
			-- Move cursor to position p.
			-- (from ARRAYED_LIST)
		require -- from CURSOR_STRUCTURE
			cursor_position_valid: valid_cursor (p)
		do
			if attached {ARRAYED_LIST_CURSOR} p as al_c then
				index := al_c.index
			else
				check
					correct_cursor_type: False
				end
			end
		end

	move (i: INTEGER_32)
			-- Move cursor i positions.
			-- (from ARRAYED_LIST)
		do
			index := index + i
			if index > count + 1 then
				index := count + 1
			elseif index < 0 then
				index := 0
			end
		ensure -- from CHAIN
			too_far_right: (old index + i > count) implies exhausted
			too_far_left: (old index + i < 1) implies exhausted
			expected_index: (not exhausted) implies (index = old index + i)
		end

	search (v: like item)
			-- Move to first position (at or after current
			-- position) where item and v are equal.
			-- If structure does not include v ensure that
			-- exhausted will be true.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from ARRAYED_LIST)
		require -- from  LINEAR
			True
		local
			l_area: like area_v2
			i, nb: INTEGER_32
			l_found: BOOLEAN
		do
			l_area := area_v2
			nb := count - 1
			i := (index - 1).max (0)
			if object_comparison and v /= Void then
				from
				until
					i > nb or l_found
				loop
					l_found := v ~ l_area.item (i)
					i := i + 1
				end
			else
				from
				until
					i > nb or l_found
				loop
					l_found := v = l_area.item (i)
					i := i + 1
				end
			end
			if l_found then
				index := i
			else
				index := i + 1
			end
		ensure -- from LINEAR
			object_found: (not exhausted and object_comparison) implies v ~ item
			item_found: (not exhausted and not object_comparison) implies v = item
		end

	start
			-- Move cursor to first position if any.
			-- (from ARRAYED_LIST)
		require -- from  TRAVERSABLE
			True
		do
			index := 1
		ensure then -- from CHAIN
			at_first: not is_empty implies isfirst
		ensure then -- from ARRAYED_LIST
			after_when_empty: is_empty implies after
		end
	
feature -- Element change

	fill (other: CONTAINER [PROCEDURE [EVENT_DATA]])
			-- Fill with as many items of other as possible.
			-- The representations of other and current structure
			-- need not be the same.
			-- (from CHAIN)
		require -- from COLLECTION
			other_not_void: other /= Void
			extendible: extendible
		local
			lin_rep: LINEAR [PROCEDURE [EVENT_DATA]]
			l_cursor: CURSOR
		do
			lin_rep := other.linear_representation
			from
				l_cursor := cursor;
				lin_rep.start
			until
				not extendible or else lin_rep.off
			loop
				extend (lin_rep.item)
				finish;
				lin_rep.forth
			end
			go_to (l_cursor)
		end

	force (v: like item)
			-- Add v to end.
			-- Do not move cursor.
			-- Was declared in ARRAYED_LIST as synonym of extend.
			-- (from ARRAYED_LIST)
		require -- from SEQUENCE
			extendible: extendible
		local
			i: INTEGER_32
			l_area: like area_v2
		do
			i := count + 1
			l_area := area_v2
			if i > l_area.capacity then
				l_area := l_area.aliased_resized_area (i + additional_space)
				area_v2 := l_area
			end;
			l_area.extend (v)
		ensure then -- from SEQUENCE
			new_count: count = old count + 1
			item_inserted: has (v)
		end

	array_put (v: PROCEDURE [EVENT_DATA]; i: INTEGER_32)
			-- Replace i-th entry, if in index interval, by v.
			-- (from TO_SPECIAL)
		require -- from TO_SPECIAL
			valid_index: array_valid_index (i)
		do
			area_v2.put (v, i)
		ensure -- from TO_SPECIAL
			inserted: array_item (i) = v
		end

	put (v: like item)
			-- Replace current item by v.
			-- (Synonym for replace)
			-- (from CHAIN)
		require -- from CHAIN
			writeable: writable
			replaceable: replaceable
		do
			replace (v)
		ensure -- from CHAIN
			same_count: count = old count
			is_inserted: is_inserted (v)
		end

	sequence_put (v: like item)
			-- Add v to end.
			-- (from SEQUENCE)
		require -- from COLLECTION
			extendible: extendible
		do
			extend (v)
		ensure -- from COLLECTION
			item_inserted: is_inserted (v)
		ensure then -- from SEQUENCE
			new_count: count = old count + 1
		end
	
feature {NONE} -- Element change

	set_area (other: like area_v2)
			-- Make other the new area.
			-- (from TO_SPECIAL)
		do
			area_v2 := other
		ensure -- from TO_SPECIAL
			area_set: area_v2 = other
		end
	
feature -- Removal

	prune (v: like item)
			-- Remove first occurrence of v, if any,
			-- after cursor position.
			-- Move cursor to right neighbor.
			-- (or after if no right neighbor or v does not occur)
		require -- from COLLECTION
			prunable: prunable
		local
			l_compare_objects: BOOLEAN
			l_kamikazes: like kamikazes_internal
		do
			Precursor (v)
			l_kamikazes := kamikazes_internal
			if l_kamikazes /= Void then
				if object_comparison then
					l_compare_objects := l_kamikazes.object_comparison;
					l_kamikazes.compare_objects;
					l_kamikazes.start;
					l_kamikazes.prune (v)
					if not l_compare_objects then
						l_kamikazes.compare_references
					end
				else
					l_kamikazes.prune (v)
				end
			end
		end

	prune_when_called (an_action: like item)
			-- Remove an_action after the next time it is called.
		require
				has (an_action)
		do
			kamikazes.extend (an_action)
		end

	remove_i_th (i: INTEGER_32)
			-- Remove item at index i.
			-- Move cursor to next neighbor (or after if no next neighbor) if it is at i-th position.
			-- Do not change cursor otherwise.
			-- (from ARRAYED_LIST)
		require -- from DYNAMIC_TABLE
			prunable: prunable
			valid_key: valid_index (i)
		do
			if i < count then
				area_v2.move_data (i, i - 1, count - i)
			end;
			area_v2.remove_tail (1)
			if index > i then
				index := index - 1
			end
		ensure then -- from DYNAMIC_CHAIN
			new_count: count = old count - 1
			same_index_if_below: index <= i implies index = old index
			new_index_if_above: index > i implies index = old index - 1
			same_leading_items: across
					old twin as c
				all
					c.target_index < i implies c.item = i_th (c.target_index)
				end
			same_trailing_items: across
					old twin as c
				all
					c.target_index > i implies c.item = i_th (c.target_index - 1)
				end
		end

	remove_left
			-- Remove item to the left of cursor position.
			-- Do not move cursor.
			-- (from ARRAYED_LIST)
		require -- from DYNAMIC_CHAIN
			left_exists: index > 1
		do
			index := index - 1
			remove
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count - 1
			new_index: index = old index - 1
		end

	wipe_out
			-- Remove all items.
			-- (from INTERACTIVE_LIST)
		local
			l: like area
			i, l_count: INTEGER_32
		do
			l := area.twin
			l_count := count
			Precursor {ARRAYED_LIST}
			from
				i := 0
			until
				i = l_count
			loop
				on_item_removed_at (l @ i, 1)
				i := i + 1
			end
		ensure then -- from DYNAMIC_LIST
			is_before: before
		end

	chain_wipe_out
			-- Remove all items.
			-- (from DYNAMIC_CHAIN)
		require -- from COLLECTION
			prunable: prunable
		do
			from
				start
			until
				is_empty
			loop
				remove
			end
		ensure -- from COLLECTION
			wiped_out: is_empty
		end
	
feature -- Resizing

	automatic_grow
			-- Change the capacity to accommodate at least
			-- Growth_percentage more items.
			-- (from RESIZABLE)
		require -- from RESIZABLE
			resizable: resizable
		do
			grow (capacity + additional_space)
		ensure -- from RESIZABLE
			increased_capacity: capacity >= old capacity + old additional_space
		end

	grow (i: INTEGER_32)
			-- Change the capacity to at least i.
			-- (from ARRAYED_LIST)
		require -- from RESIZABLE
			resizable: resizable
		do
			if i > area_v2.capacity then
				area_v2 := area_v2.aliased_resized_area (i)
			end
		ensure -- from RESIZABLE
			new_capacity: capacity >= i
		end

	resize (new_capacity: INTEGER_32)
			-- Resize list so that it can contain
			-- at least n items. Do not lose any item.
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			resizable: resizable
			new_capacity_large_enough: new_capacity >= capacity
		do
			grow (new_capacity)
		ensure -- from ARRAYED_LIST
			capacity_set: capacity >= new_capacity
		end

	trim
			-- Decrease capacity to the minimum value.
			-- Apply to reduce allocated storage.
			-- (from ARRAYED_LIST)
		require -- from  RESIZABLE
			True
		local
			n: like count
		do
			n := count
			if n < area_v2.capacity then
				area_v2 := area_v2.aliased_resized_area (n)
			end
		ensure -- from RESIZABLE
			same_count: count = old count
			minimal_capacity: capacity = count
		ensure then -- from ARRAYED_LIST
			same_items: to_array.same_items (old to_array)
		end
	
feature -- Transformation

	swap (i: INTEGER_32)
			-- Exchange item at i-th position with item
			-- at cursor position.
			-- (from ARRAYED_LIST)
		require -- from CHAIN
			not_off: not off
			valid_index: valid_index (i)
		local
			old_item: like item
		do
			old_item := item
			replace (area_v2.item (i - 1));
			area_v2.put (old_item, i - 1)
		ensure -- from CHAIN
			swapped_to_item: item = old i_th (i)
			swapped_from_item: i_th (i) = old item
		end
	
feature -- Conversion

	linear_representation: LINEAR [PROCEDURE [EVENT_DATA]]
			-- Representation as a linear structure
			-- (from LINEAR)
		require -- from  CONTAINER
			True
		do
			Result := Current
		end
	
feature -- Duplication

	frozen clone (other: detachable ANY): like other
		obsolete "Use `twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- equal to other
			--
			-- For non-void other, clone calls copy;
			-- to change copying/cloning semantics, redefine copy.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.twin
			end
		ensure -- from ANY
			instance_free: class
			equal: Result ~ other
		end

	copy (other: ACTION_SEQUENCE [EVENT_DATA])
			-- Reinitialize by copying all the items of other.
			-- (This is also used by clone.)
			-- (from ARRAYED_LIST)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		do
			if other /= Current then
				standard_copy (other)
				set_area (other.area_v2.twin)
			end
		ensure -- from ANY
			is_equal: Current ~ other
		ensure then -- from ARRAYED_LIST
			equal_areas: area_v2 ~ other.area_v2
		end

	frozen deep_clone (other: detachable ANY): like other
		obsolete "Use `deep_twin' instead. [2017-05-31]"
			-- Void if other is void: otherwise, new object structure
			-- recursively duplicated from the one attached to other
			-- (from ANY)
		do
			if other /= Void then
				Result := other.deep_twin
			end
		ensure -- from ANY
			instance_free: class
			deep_equal: deep_equal (other, Result)
		end

	frozen deep_copy (other: ACTION_SEQUENCE [EVENT_DATA])
			-- Effect equivalent to that of:
			--		copy (other . deep_twin)
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
		do
			copy (other.deep_twin)
		ensure -- from ANY
			deep_equal: deep_equal (Current, other)
		end

	frozen deep_twin: ACTION_SEQUENCE [EVENT_DATA]
			-- New object structure recursively duplicated from Current.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			deep_twin_not_void: Result /= Void
			deep_equal: deep_equal (Current, Result)
		end

	duplicate (n: INTEGER_32): ACTION_SEQUENCE [EVENT_DATA]
		obsolete "[
			Create a new container explicitly using `make_from_iterable` if available.
			Otherwise, replace a call to the feature with code that creates and initializes container.
			[2018-11-30]
		]"
			-- Copy of sub-list beginning at current position
			-- and having min (n, count - index + 1) items.
			-- (from ARRAYED_LIST)
		require -- from CHAIN
			not_off_unless_after: off implies after
			valid_subchain: n >= 0
		local
			m: INTEGER_32
		do
			if after then
				Result := new_filled_list (0)
			else
				m := (count - index + 1).min (n)
				Result := new_filled_list (m);
				Result.area_v2.copy_data (area_v2, index - 1, 0, m)
			end
		end

	frozen standard_clone (other: detachable ANY): like other
		obsolete "Use `standard_twin' instead. [2017-05-31]"
			-- Void if other is void; otherwise new object
			-- field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		do
			if other /= Void then
				Result := other.standard_twin
			end
		ensure -- from ANY
			instance_free: class
			equal: standard_equal (Result, other)
		end

	frozen standard_copy (other: ACTION_SEQUENCE [EVENT_DATA])
			-- Copy every field of other onto corresponding field
			-- of current object.
			-- (from ANY)
		require -- from ANY
			other_not_void: other /= Void
			type_identity: same_type (other)
		external
			"built_in"
		ensure -- from ANY
			is_standard_equal: standard_is_equal (other)
		end

	frozen standard_twin: ACTION_SEQUENCE [EVENT_DATA]
			-- New object field-by-field identical to other.
			-- Always uses default copying semantics.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			standard_twin_not_void: Result /= Void
			equal: standard_equal (Result, Current)
		end

	frozen twin: ACTION_SEQUENCE [EVENT_DATA]
			-- New object equal to Current
			-- twin calls copy; to change copying/twinning semantics, redefine copy.
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			twin_not_void: Result /= Void
			is_equal: Result ~ Current
		end
	
feature -- Miscellaneous

	on_item_added_at (an_item: like item; item_index: INTEGER_32)
			-- an_item has just been added at index item_index.
		require -- from INTERACTIVE_LIST
			item_index_valid: (1 <= item_index) and (item_index <= count)
		do
			if count = 1 and not_empty_actions_internal /= Void then
				call_action_list (not_empty_actions)
			end
		end

	on_item_removed_at (an_item: like item; item_index: INTEGER_32)
			-- an_item has just been removed from index item_index.
		require -- from INTERACTIVE_LIST
			item_index_valid: (1 <= item_index) and (item_index <= count + 1)
		do
			if count = 0 and empty_actions_internal /= Void then
				call_action_list (empty_actions)
			end
		end
	
feature -- Basic operations

	frozen as_attached: attached ACTION_SEQUENCE [EVENT_DATA]
		obsolete "Remove calls to this feature. [2017-05-31]"
			-- Attached version of Current.
			-- (Can be used during transitional period to convert
			-- non-void-safe classes to void-safe ones.)
			-- (from ANY)
		do
			Result := Current
		end

	call (event_data: detachable EVENT_DATA)
			-- Call each procedure in order unless is_blocked.
			-- If is_paused delay execution until resume.
			-- Stop at current point in list on abort.
		local
			l_routines_snapshot: SPECIAL [like item]
			l_count: INTEGER_32
			l_action: like item
			l_kamikazes: SPECIAL [like item]
			l_kamikazes_internal: like kamikazes_internal
			l_is_aborted_stack: like is_aborted_stack
			i: INTEGER_32
		do
			if count > 0 then
				create l_routines_snapshot.make_empty (count);
				l_routines_snapshot.copy_data (area, 0, 0, count)
				l_kamikazes_internal := kamikazes_internal
				if l_kamikazes_internal /= Void and then not l_kamikazes_internal.is_empty then
					from
						l_kamikazes := l_kamikazes_internal.area
						l_count := l_kamikazes_internal.count
						i := 0
					until
						i = l_count
					loop
						prune_all (l_kamikazes @ i)
						i := i + 1
					end;
					l_kamikazes_internal.wipe_out
				end
				inspect state
				when Normal_state then
					from
						l_is_aborted_stack := is_aborted_stack;
						l_is_aborted_stack.extend (False)
						l_count := l_routines_snapshot.count
						i := 0
					variant
							l_count - i
					until
						i = l_count or l_is_aborted_stack.item
					loop
						l_action := l_routines_snapshot @ i
						if l_action /= Void then
							l_action.call (event_data)
						end
						i := i + 1
					end;
					l_is_aborted_stack.remove
				when Paused_state then
					call_buffer.extend (event_data)
				when Blocked_state then
				end
			end
		ensure
			is_aborted_stack_unchanged: (old is_aborted_stack) ~ is_aborted_stack
		end

	frozen default: detachable ACTION_SEQUENCE [EVENT_DATA]
			-- Default value of object's type
			-- (from ANY)
		do
		end

	frozen default_pointer: POINTER
			-- Default value of type POINTER
			-- (Avoid the need to write p.default for
			-- some p of type POINTER.)
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end

	default_rescue
			-- Process exception for routines with no Rescue clause.
			-- (Default: do nothing.)
			-- (from ANY)
		do
		end

	frozen do_nothing
			-- Execute a null action.
			-- (from ANY)
		do
		ensure -- from ANY
			instance_free: class
		end

	extend_kamikaze (an_item: like item)
			-- Extend an_item and remove it again after it is called.
		do
			extend (an_item)
			prune_when_called (an_item)
		end
	
feature -- Obsolete

	make
		obsolete "Use `default_create`. [2017-05-31]"
		do
			default_create
		end

	set_source_connection_agent (a_source_connection_agent: PROCEDURE)
		obsolete "Use `not_empty_actions`. [2017-05-31]"
			-- Set a_source_connection_agent that will connect sequence to an
			-- actual event source. The agent will be called when the first action is
			-- added to the sequence. If there are already actions in the
			-- sequence the agent is called immediately.
		do
			not_empty_actions.extend (a_source_connection_agent)
			if not is_empty then
				a_source_connection_agent.call (Void)
			end
		end
	
feature {DYNAMIC_CHAIN} -- Inapplicable

	new_chain: ACTION_SEQUENCE [EVENT_DATA]
		obsolete "Use explicit creation instead. See also explanations for `duplicate`. [2018-11-30]"
			-- Unused
			-- (from ARRAYED_LIST)
		do
			Result := Current
		ensure -- from DYNAMIC_CHAIN
			result_exists: Result /= Void
		end
	
feature {NONE} -- Implementation

	add_all (other: ACTION_SEQUENCE [EVENT_DATA]; start_index: INTEGER_32)
			-- Call on_item_added for all elements in other.
			-- (from INTERACTIVE_LIST)
		local
			cur: CURSOR
			current_index: INTEGER_32
		do
			current_index := start_index
			cur := other.cursor
			from
				other.start
			until
				other.after
			loop
				added_item (other.item, current_index);
				other.forth
				current_index := current_index + 1
			end;
			other.go_to (cur)
		end

	added_item (an_item: like item; item_index: INTEGER_32)
			-- an_item is has been added.
			-- (from INTERACTIVE_LIST)
		do
			if not in_operation then
				on_item_added_at (an_item, item_index)
			end
		end

	call_action_list (actions: ARRAYED_LIST [PROCEDURE])
			-- Call each action in actions.
		require
			actions_not_void: actions /= Void
		local
			snapshot: like actions
			i: INTEGER_32
		do
			if not actions.is_empty then
				snapshot := actions.twin
				from
					i := 1
				until
					i > snapshot.count
				loop
					if snapshot @ i /= Void then
						snapshot.i_th (i).call (Void)
					end
					i := i + 1
				end
			end
		end

	call_buffer: LINKED_QUEUE [detachable EVENT_DATA]
			-- Holds calls made while is_paused
			-- to be executed on resume.
		do
			Result := call_buffer_internal
			if Result = Void then
				create Result.make
				call_buffer_internal := Result
			end
		end

	call_buffer_internal: detachable like call_buffer
			-- Internal storage for call_buffer.

	dummy_event_data_internal: detachable EVENT_DATA
			-- See dummy_event_data.

	empty_actions_internal: detachable like empty_actions
			-- Internal storage for empty_actions.

	event_data_names_internal: detachable ARRAY [STRING_8]
			-- See event_data_names.

	force_i_th (v: like i_th; pos: INTEGER_32)
			-- (from ARRAYED_LIST)
		do
			if count + 1 > capacity then
				grow (count + additional_space)
			end;
			area_v2.force (v, pos)
		end

	in_operation: BOOLEAN
			-- Are we executing an operation from ARRAYED_LIST?
			-- (from INTERACTIVE_LIST)

	insert (v: like item; pos: INTEGER_32)
			-- Add v at pos, moving subsequent items
			-- to the right.
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			index_small_enough: pos <= count
			index_large_enough: pos >= 1
		do
			if count + 1 > capacity then
				grow (count + additional_space)
			end;
			area_v2.move_data (pos - 1, pos, count - pos + 1)
			put_i_th (v, pos)
		ensure -- from ARRAYED_LIST
			new_count: count = old count + 1
			index_unchanged: index = old index
			insertion_done: i_th (pos) = v
		end

	is_aborted_stack: LINKED_STACK [BOOLEAN]
			-- item holds abort status of
			-- innermost of possibly recursive calls.
		do
			Result := is_aborted_stack_internal
			if Result = Void then
				create Result.make
				is_aborted_stack_internal := Result
			end
		end

	is_aborted_stack_internal: detachable like is_aborted_stack
			-- Internal storage for is_aborted_stack.

	kamikazes: ARRAYED_LIST [like item]
			-- Used by prune_when_called.
		do
			Result := kamikazes_internal
			if Result = Void then
				create Result.make (0)
				kamikazes_internal := Result
			end
		end

	kamikazes_internal: detachable like kamikazes
			-- Internal storage for kamikazes.

	name_internal: detachable STRING_8
			-- See name.

	new_filled_list (n: INTEGER_32): like Current
		obsolete "Use explicit creation instead. See also explanations for `duplicate`. [2018-11-30]"
			-- New list with n elements.
		require -- from ARRAYED_LIST
			n_non_negative: n >= 0
		do
			create Result.make_filled (n)
		ensure -- from ARRAYED_LIST
			new_filled_list_not_void: Result /= Void
			new_filled_list_count_set: Result.is_empty
			new_filled_list_before: Result.before
		end

	not_empty_actions_internal: detachable like not_empty_actions
			-- Internal storage for not_empty_actions.

	removed_item (an_item: like item; item_index: INTEGER_32)
			-- an_item has been removed.
			-- (from INTERACTIVE_LIST)
		do
			if not in_operation then
				on_item_removed_at (an_item, item_index)
			end
		end
	
feature -- Correction

	Mismatch_information: MISMATCH_INFORMATION
			-- Original attribute values of mismatched object
			-- (from MISMATCH_CORRECTOR)
		once
			create Result
		end
	
feature -- Element Change

	append (s: SEQUENCE [like item])
			-- Append a copy of s.
			-- (from INTERACTIVE_LIST)
		require -- from SEQUENCE
			argument_not_void: s /= Void
		local
			new_count: INTEGER_32
		do
			new_count := count + s.count
			if new_count > capacity then
				grow (new_count)
			end
			across
				if s = Current then
					s.twin
				else
					s
				end as c
			loop
				extend (c.item)
			end
		ensure -- from SEQUENCE
			new_count: count >= old count
		end

	extend (v: like item)
			-- Add v to end.
			-- Do not move cursor.
			-- (from INTERACTIVE_LIST)
		require -- from COLLECTION
			extendible: extendible
		do
			in_operation := True
			Precursor {ARRAYED_LIST} (v)
			in_operation := False
			added_item (v, count)
		ensure -- from COLLECTION
			item_inserted: is_inserted (v)
		end

	merge_left (other: ACTION_SEQUENCE [EVENT_DATA])
			-- Merge other into current structure after cursor
			-- position. Do not move cursor. Empty other
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			extendible: extendible
			not_before: not before
			other_exists: other /= Void
			not_current: other /= Current
		local
			original_index: INTEGER_32
			original_other_count: INTEGER_32
		do
			original_index := index
			original_other_count := other.count
			index := index - 1
			merge_right (other)
			index := original_index + original_other_count
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count + old other.count
			new_index: index = old index + old other.count
			other_is_empty: other.is_empty
		end

	merge_right (other: ACTION_SEQUENCE [EVENT_DATA])
			-- Merge other into current structure before cursor
			-- position. Do not move cursor. Empty other
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			extendible: extendible
			not_after: not after
			other_exists: other /= Void
			not_current: other /= Current
		local
			original_index: INTEGER_32
		do
			original_index := index
			in_operation := True
			Precursor {ARRAYED_LIST} (other)
			in_operation := False
			update_for_added (original_index + 1)
			go_i_th (original_index)
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count + old other.count
			same_index: index = old index
			other_is_empty: other.is_empty
		end

	prune_all (v: like item)
			-- Remove all occurrences of v.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- (from INTERACTIVE_LIST)
		require -- from COLLECTION
			prunable: prunable
		local
			i, nb: INTEGER_32
			offset: INTEGER_32
			res: BOOLEAN
			obj_cmp: BOOLEAN
			l_item: like item
			l_area: like area
		do
			obj_cmp := object_comparison
			from
				l_area := area
				i := 0
				nb := count
			until
				i = count
			loop
				if i < nb - offset then
					if offset > 0 then
						l_area.put (l_area.item (i + offset), i)
					end
					l_item := l_area.item (i)
					if obj_cmp then
						res := v ~ l_item
					else
						res := v = l_item
					end
					if res then
						removed_item (l_item, i + Lower)
						offset := offset + 1
					else
						i := i + 1
					end
				else
					i := i + 1
				end
			end;
			l_area.remove_tail (offset)
			index := count + 1
		ensure -- from COLLECTION
			no_more_occurrences: not has (v)
		ensure then -- from DYNAMIC_CHAIN
			is_exhausted: exhausted
		ensure then -- from ARRAYED_LIST
			is_after: after
		ensure then -- from INTERACTIVE_LIST
			is_after: after
		end

	put_front (v: like item)
			-- Add v to beginning.
			-- Do not move cursor.
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			extendible: extendible
		do
			in_operation := True
			Precursor {ARRAYED_LIST} (v)
			in_operation := False
			added_item (v, 1)
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count + 1
			item_inserted: first = v
		end

	put_i_th (v: like i_th; i: INTEGER_32)
			-- Replace i-th entry, if in index interval, by v.
			-- (from INTERACTIVE_LIST)
		require -- from TABLE
			valid_key: valid_index (i)
		require -- from TABLE
			valid_key: valid_index (i)
		local
			original_item: like item
		do
			original_item := i_th (i)
			in_operation := True
			Precursor {ARRAYED_LIST} (v, i)
			in_operation := False
			if original_item /= Void then
				removed_item (original_item, i)
			end
			added_item (v, i)
		ensure -- from TABLE
			inserted: i_th (i) = v
		end

	put_left (v: like item)
			-- Add v to the left of cursor position.
			-- Do not move cursor.
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			extendible: extendible
			not_before: not before
		do
			in_operation := True
			Precursor {ARRAYED_LIST} (v)
			in_operation := False
			added_item (v, index - 1)
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count + 1
			new_index: index = old index + 1
		end

	put_right (v: like item)
			-- Add v to the right of cursor position.
			-- Do not move cursor.
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			extendible: extendible
			not_after: not after
		do
			in_operation := True
			Precursor {ARRAYED_LIST} (v)
			in_operation := False
			added_item (v, index + 1)
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count + 1
			same_index: index = old index
		end

	remove
			-- Remove current item.
			-- Move cursor to right neighbor
			-- (or after if no right neighbor).
			-- (from INTERACTIVE_LIST)
		require -- from ACTIVE
			prunable: prunable
			writable: writable
		local
			original_index: INTEGER_32
			original_item: like item
		do
			original_index := index
			original_item := item
			in_operation := True
			Precursor {ARRAYED_LIST}
			in_operation := False
			removed_item (original_item, original_index)
		ensure then -- from DYNAMIC_LIST
			after_when_empty: is_empty implies after
		ensure then -- from ARRAYED_LIST
			index: index = old index
		end

	remove_right
			-- Remove item to the right of cursor position.
			-- Do not move cursor.
			-- (from INTERACTIVE_LIST)
		require -- from DYNAMIC_CHAIN
			right_exists: index < count
		local
			item_removed: like item
		do
			item_removed := i_th (index + 1)
			in_operation := True
			Precursor {ARRAYED_LIST}
			in_operation := False
			removed_item (item_removed, index + 1)
		ensure -- from DYNAMIC_CHAIN
			new_count: count = old count - 1
			same_index: index = old index
		end

	replace (v: like item)
			-- Replace current item by v.
			-- (from INTERACTIVE_LIST)
		require -- from ACTIVE
			writable: writable
			replaceable: replaceable
		local
			original_index: INTEGER_32
			original_item: like item
		do
			original_index := index
			original_item := item
			in_operation := True
			Precursor {ARRAYED_LIST} (v)
			in_operation := False
			removed_item (original_item, original_index)
			added_item (v, original_index)
		ensure -- from ACTIVE
			item_replaced: item = v
		end

	update_for_added (start_index: INTEGER_32)
			-- Call added_item for all items from index start_index to count
			-- (from INTERACTIVE_LIST)
		local
			l_index: INTEGER_32
		do
			l_index := index
			from
				go_i_th (start_index)
			until
				index > count
			loop
				added_item (item, index)
				forth
			end
			go_i_th (l_index)
		end
	
feature -- Element status

	has_kamikaze_action (an_action: like item): BOOLEAN
			-- Return True is an_action is found and will be pruned when called.
		require
				has (an_action)
		do
			Result := has (an_action) and then kamikazes.has (an_action)
		end
	
feature -- Event handling

	empty_actions: ARRAYED_LIST [PROCEDURE]
			-- Actions to be performed on transition from not is_empty to is_empty.
		do
			Result := empty_actions_internal
			if Result = Void then
				create Result.make (0)
				empty_actions_internal := Result
			end
		end

	not_empty_actions: ARRAYED_LIST [PROCEDURE]
			-- Actions to be performed on transition from is_empty to not is_empty.
		do
			Result := not_empty_actions_internal
			if Result = Void then
				create Result.make (0)
				not_empty_actions_internal := Result
			end
		end
	
feature -- Iteration

	do_all (action: PROCEDURE [PROCEDURE [EVENT_DATA]])
			-- Apply action to every item, from first to last.
			-- Semantics not guaranteed if action changes the structure;
			-- in such a case, apply iterator to clone of structure instead.
			-- (from ARRAYED_LIST)
		require -- from TRAVERSABLE
			action_exists: action /= Void
		do
			area_v2.do_all_in_bounds (action, 0, area_v2.count - 1)
		end

	do_all_with_index (action: PROCEDURE [PROCEDURE [EVENT_DATA], INTEGER_32])
			-- Apply action to every item, from first to last.
			-- action receives item and its index.
			-- Semantics not guaranteed if action changes the structure;
			-- in such a case, apply iterator to clone of structure instead.
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			action_not_void: action /= Void
		local
			i, j, nb: INTEGER_32
			l_area: like area_v2
		do
			from
				i := 0
				j := Lower
				nb := count - 1
				l_area := area_v2
			until
				i > nb
			loop
				action.call ([l_area.item (i), j])
				j := j + 1
				i := i + 1
			end
		end

	do_if (action: PROCEDURE [PROCEDURE [EVENT_DATA]]; test: FUNCTION [PROCEDURE [EVENT_DATA], BOOLEAN])
			-- Apply action to every item that satisfies test, from first to last.
			-- Semantics not guaranteed if action or test changes the structure;
			-- in such a case, apply iterator to clone of structure instead.
			-- (from ARRAYED_LIST)
		require -- from TRAVERSABLE
			action_exists: action /= Void
			test_exists: test /= Void
		do
			area_v2.do_if_in_bounds (action, test, 0, area_v2.count - 1)
		end

	do_if_with_index (action: PROCEDURE [PROCEDURE [EVENT_DATA], INTEGER_32]; test: FUNCTION [PROCEDURE [EVENT_DATA], INTEGER_32, BOOLEAN])
			-- Apply action to every item that satisfies test, from first to last.
			-- action and test receive the item and its index.
			-- Semantics not guaranteed if action or test changes the structure;
			-- in such a case, apply iterator to clone of structure instead.
			-- (from ARRAYED_LIST)
		require -- from ARRAYED_LIST
			action_not_void: action /= Void
			test_not_void: test /= Void
		local
			i, j, nb: INTEGER_32
			l_area: like area_v2
		do
			from
				i := 0
				j := Lower
				nb := count - 1
				l_area := area_v2
			until
				i > nb
			loop
				if test.item ([l_area.item (i), j]) then
					action.call ([l_area.item (i), j])
				end
				j := j + 1
				i := i + 1
			end
		end

	for_all (test: FUNCTION [PROCEDURE [EVENT_DATA], BOOLEAN]): BOOLEAN
			-- Is test true for all items?
			-- (from ARRAYED_LIST)
		require -- from TRAVERSABLE
			test_exists: test /= Void
		do
			Result := area_v2.for_all_in_bounds (test, 0, area_v2.count - 1)
		ensure then -- from LINEAR
			empty: is_empty implies Result
		end

	there_exists (test: FUNCTION [PROCEDURE [EVENT_DATA], BOOLEAN]): BOOLEAN
			-- Is test true for at least one item?
			-- (from ARRAYED_LIST)
		require -- from TRAVERSABLE
			test_exists: test /= Void
		do
			Result := area_v2.there_exists_in_bounds (test, 0, area_v2.count - 1)
		end
	
feature -- Output

	Io: STD_FILES
			-- Handle to standard file setup
			-- (from ANY)
		once
			create Result;
			Result.set_output_default
		ensure -- from ANY
			instance_free: class
			io_not_void: Result /= Void
		end

	out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from ANY)
		do
			Result := tagged_out
		ensure -- from ANY
			out_not_void: Result /= Void
		end

	print (o: detachable ANY)
			-- Write terse external representation of o
			-- on standard output.
			-- (from ANY)
		local
			s: READABLE_STRING_8
		do
			if attached o then
				s := o.out
				if attached {READABLE_STRING_32} s as s32 then
					Io.put_string_32 (s32)
				elseif attached {READABLE_STRING_8} s as s8 then
					Io.put_string (s8)
				else
					Io.put_string_32 (s.as_string_32)
				end
			end
		ensure -- from ANY
			instance_free: class
		end

	frozen tagged_out: STRING_8
			-- New string containing terse printable representation
			-- of current object
			-- (from ANY)
		external
			"built_in"
		ensure -- from ANY
			tagged_out_not_void: Result /= Void
		end
	
feature -- Platform

	Operating_environment: OPERATING_ENVIRONMENT
			-- Objects available from the operating system
			-- (from ANY)
		once
			create Result
		ensure -- from ANY
			instance_free: class
			operating_environment_not_void: Result /= Void
		end
	
feature -- Retrieval

	correct_mismatch
			-- Attempt to correct object mismatch using Mismatch_information.
			-- (from ARRAYED_LIST)
		local
			i: INTEGER_32
		do
			if not Mismatch_information.has ("area_v2") and then attached {SPECIAL [PROCEDURE [EVENT_DATA]]} Mismatch_information.item ("area") as l_area and then attached {INTEGER_32} Mismatch_information.item ("count") as l_count and then attached {BOOLEAN} Mismatch_information.item ("object_comparison") as l_comp and then attached {INTEGER_32} Mismatch_information.item ("index") as l_index then
				create area_v2.make_empty (l_count)
				from
					i := 0
				until
					i = l_count
				loop
					area_v2.extend (l_area.item (i))
					i := i + 1
				end
				object_comparison := l_comp
				index := l_index
			else
				Precursor
			end
		end
	
feature {NONE} -- Retrieval

	frozen internal_correct_mismatch
			-- Called from runtime to perform a proper dynamic dispatch on correct_mismatch
			-- from MISMATCH_CORRECTOR.
			-- (from ANY)
		local
			l_msg: STRING_32
			l_exc: EXCEPTIONS
		do
			if attached {MISMATCH_CORRECTOR} Current as l_corrector then
				l_corrector.correct_mismatch
			else
				create l_msg.make_from_string ("Mismatch: ".as_string_32)
				create l_exc;
				l_msg.append (generating_type.name_32);
				l_exc.raise_retrieval_exception (l_msg)
			end
		end
	
invariant
	is_aborted_stack_not_void: is_aborted_stack /= Void
	call_buffer_not_void: call_buffer /= Void
	valid_state: state = Normal_state or state = Paused_state or state = Blocked_state
	call_buffer_consistent: state = Normal_state implies call_buffer.is_empty
	not_empty_actions_not_void: not_empty_actions /= Void
	empty_actions_not_void: empty_actions /= Void

		-- from ARRAYED_LIST
	prunable: prunable
	starts_from_one: Lower = 1

		-- from ANY
	reflexive_equality: standard_is_equal (Current)
	reflexive_conformance: conforms_to (Current)

		-- from RESIZABLE
	increase_by_at_least_one: Minimal_increase >= 1

		-- from BOUNDED
	valid_count: count <= capacity
	full_definition: full = (count = capacity)

		-- from FINITE
	empty_definition: is_empty = (count = 0)

		-- from LIST
	before_definition: before = (index = 0)
	after_definition: after = (index = count + 1)

		-- from CHAIN
	non_negative_index: index >= 0
	index_small_enough: index <= count + 1
	off_definition: off = ((index = 0) or (index = count + 1))
	isfirst_definition: isfirst = ((not is_empty) and (index = 1))
	islast_definition: islast = ((not is_empty) and (index = count))
	item_corresponds_to_index: (not off) implies (item = i_th (index))

		-- from ACTIVE
	writable_constraint: writable implies readable
	empty_constraint: is_empty implies (not readable) and (not writable)

		-- from READABLE_INDEXABLE
	consistent_boundaries: Lower <= count or else Lower = count + 1

		-- from BILINEAR
	not_both: not (after and before)
	before_constraint: before implies off

		-- from LINEAR
	after_constraint: after implies off

		-- from TRAVERSABLE
	empty_constraint: is_empty implies off

note
	library: "EiffelBase: Library of reusable components for Eiffel."
	copyright: "Copyright (c) 1984-2018, Eiffel Software and others"
	license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
	source: "[
		Eiffel Software
		5949 Hollister Ave., Goleta, CA 93117 USA
		Telephone 805-685-1006, Fax 805-685-6869
		Website http://www.eiffel.com
		Customer support http://support.eiffel.com
	]"

end -- class ACTION_SEQUENCE

Generated by ISE EiffelStudio