-
Notifications
You must be signed in to change notification settings - Fork 2
/
v_container.e
160 lines (142 loc) · 3.11 KB
/
v_container.e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
note
description: "[
Containers for a finite number of values.
Immutable interface.
]"
author: "Nadia Polikarpova"
model: bag
manual_inv: true
false_guards: true
deferred class
V_CONTAINER [G]
inherit
ITERABLE [G]
feature -- Measurement
count: INTEGER
-- Number of elements.
deferred
ensure
definition: Result = bag.count
end
feature -- Status report
is_empty: BOOLEAN
-- Is container empty?
note
status: nonvariant
do
Result := count = 0
ensure
definition: Result = bag.is_empty
end
feature -- Search
has (v: G): BOOLEAN
-- Is value `v' contained?
-- (Uses reference equality.)
note
status: impure, nonvariant
require
modify_model ("observers", Current)
local
it: V_ITERATOR [G]
do
it := new_cursor
it.search_forth (v)
Result := not it.after
forget_iterator (it)
ensure
definition: Result = bag.domain [v]
observers_restored: observers = old observers
end
occurrences (v: G): INTEGER
-- How many times is value `v' contained?
-- (Uses reference equality.)
note
status: impure, nonvariant
require
modify_model ("observers", Current)
local
it: V_ITERATOR [G]
s: MML_SEQUENCE [G]
do
from
it := new_cursor
invariant
1 <= it.index_ and it.index_ <= it.sequence.count + 1
s = it.sequence.front (it.index_ - 1)
Result = s.occurrences (v)
it.is_wrapped
modify_model ("index_", it)
until
it.off
loop
if it.item = v then
Result := Result + 1
end
s := s & it.item
it.forth
variant
it.sequence.count - it.index_
end
forget_iterator (it)
ensure
definition: Result = bag [v]
observers_restored: observers ~ old observers
end
feature -- Iteration
new_cursor: V_ITERATOR [G]
-- New iterator pointing to a position in the container, from which it can traverse all elements by going `forth'.
note
status: impure
deferred
ensure then
target_definition: Result.target = Current
index_definition: Result.index_ = 1
end
feature -- Specification
bag: MML_BAG [G]
-- Bag of elements.
note
status: ghost
attribute
end
forget_iterator (it: V_ITERATOR [G])
-- Remove `it' from `observers'.
note
status: ghost
explicit: contracts
require
wrapped: is_wrapped
it_wrapped: it.is_wrapped
valid_target: it.target = Current
modify_field (["observers", "closed"], Current)
modify (it) -- not using modify_field here because of the typing bug
do
it.unwrap
set_observers (observers / it)
ensure
wrapped: is_wrapped
it_open: it.is_open
observer_removed: observers = old observers / it
it.owns ~ old it.owns
it.observers ~ old it.observers
end
feature {V_CONTAINER, V_ITERATOR} -- Specification
add_iterator (it: V_ITERATOR [G])
-- Add `it' to `observers'.
note
status: ghost
require
wrapped: is_wrapped
valid_type: attached {like new_cursor} it
modify_field (["observers", "closed"], Current)
do
unwrap
set_observers (observers & it)
wrap
ensure
wrapped: is_wrapped
observer_added: observers = old observers & it
end
invariant
not_observer: not observers [Current]
end