File: client_list.e

package info (click to toggle)
smarteiffel 1.1-11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 12,288 kB
  • ctags: 40,785
  • sloc: ansic: 35,791; lisp: 4,036; sh: 1,783; java: 895; ruby: 613; python: 209; makefile: 115; csh: 78; cpp: 50
file content (314 lines) | stat: -rw-r--r-- 9,180 bytes parent folder | download | duplicates (2)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
-- This file is part of SmartEiffel The GNU Eiffel Compiler Tools and Libraries
--
-- SmartEiffel is  free software;  you can redistribute it and/or  modify it
-- under  the terms of the  GNU General Public License, as published by  the
-- Free Software Foundation; either version 2, or (at your option) any later
-- version.
-- SmartEiffel is distributed in the hope that it will be useful but WITHOUT 
-- ANY WARRANTY;  without  even the implied warranty  of MERCHANTABILITY  or
-- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-- more details.  You should have received a copy of  the GNU General Public
-- License along with SmartEiffel;  see the file COPYING.  If not,  write to
-- the Free Software Foundation,  Inc., 59 Temple Place - Suite 330,  Boston, 
-- MA 02111-1307, USA.
--
-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.
--			   - University of Nancy 1 - FRANCE
-- Copyright(C) 2003:      INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne
--			   - University of Nancy 2 - FRANCE
--
--		 Dominique COLNET, Suzanne COLLIN, Olivier ZENDRA,
--			   Philippe RIBET, Cyril ADRIAN
--
-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
--
class CLIENT_LIST
   --
   -- To store a list of clients class like : {FOO,BAR}
   --

inherit
   GLOBALS
   VISITABLE

creation make, omitted, merge

feature

   start_position: POSITION
         -- Of the the opening bracket when list is really written.

   is_omitted: BOOLEAN is
      do
         Result := start_position.is_unknown
      end

   pretty_print is
      do
         if is_omitted then
            if pretty_printer.parano_mode then
               pretty_printer.put_string(once "{ANY} ")
            end
         else
            if list = Void then
               if pretty_printer.zen_mode then
                  pretty_printer.put_string(once "{} ")
               else
                  pretty_printer.put_string(once "{NONE} ")
               end
            else
               pretty_printer.put_character('{')
               pretty_printer.set_indent_level(2)
               list.pretty_print
               pretty_printer.put_character('}')
               pretty_printer.put_character(' ')
            end
         end
      end

   gives_permission_to(cn: CLASS_NAME): BOOLEAN is
         -- Check whether the `cn' class is a member (or a subclass as
         -- well) of the `Current' client list. (No error report done here
         -- in `error_handler').
      require
         cn /= Void
	 error_handler.is_empty
      do
         if is_omitted then
            -- It is equivalent to {ANY}:
            Result := true
         elseif list = Void then
            -- Because it is equivalent to {NONE}.
         else
            Result := list.gives_permission_to(cn)
         end
      ensure
	 error_handler.is_empty
      end

   gives_permission_to_any: BOOLEAN is
         -- Check whether the `Current' client list gives permission to all
         -- classes. (No error report done here in `error_handler').
      require
	 error_handler.is_empty
      do
         if is_omitted then
            Result := true
            -- Because it is as : {ANY}.
         elseif list = Void then
            -- Because it is as : {NONE}.
         else
            Result := list.gives_permission_to_any
         end
      ensure
	 error_handler.is_empty
      end

feature {BASE_CLASS, CLIENT_LIST}

   eiffel_view: STRING is
	 -- The Eiffel view of the allowed classe(s) list. (Because of
	 -- clients list merging, the `Current' clients list may be located
	 -- on many Eiffel source files. This function is also useful to
	 -- remind default abbreviated notation as omited list or empty
	 -- list.)
      local
	 i: INTEGER
      do
	 if eiffel_view_memory = Void then
	    if is_omitted then
	       eiffel_view_memory := once "{ANY}"
	    elseif list = Void then
	       eiffel_view_memory := once "{NONE}"
	    else
	       create eiffel_view_memory.make(64)
	       eiffel_view_memory.extend('{')
	       from
		  i := 1
	       until
		  i > list.count
	       loop
		  eiffel_view_memory.append(list.item(i).to_string)
		  i := i + 1
		  if i <= list.count then
		     eiffel_view_memory.extend(',')
		     eiffel_view_memory.extend(' ')
		  end
	       end
	       eiffel_view_memory.extend('}')
	    end
	 end
	 Result := eiffel_view_memory
      ensure
	 Result /= Void
      end

   locate_in_error_handler is
	 -- Add one or more related positions in the `error_handler'.
      do
	 if list = Void then
	    error_handler.add_position(start_position)
	 else
	    list.locate_in_error_handler
	 end
      end

feature {EXPORT_LIST}

   merge_with(other: like Current): like current is
      require
         other /= Void
      local
         sp: POSITION
      do
         if gives_permission_to_any then
            Result := Current
         elseif other.gives_permission_to_any then
            Result := other
         else
            sp := start_position
            if sp.is_unknown then
               sp := other.start_position
            end
            create Result.merge(sp,list,other.list)
         end
      end

feature {PARENT_LIST}

   append(other: like Current): like Current is
      require
         other /= Void
      do
         if Current = other or else is_omitted then
            Result := Current
         elseif gives_permission_to_any then
	    Result := Current
	 elseif other.is_omitted then
	    Result := other
	 elseif other.gives_permission_to_any then
	    Result := other
	 else
	    create Result.merge(start_position,list,other.list)
	 end
	 debug
	    eiffel_view_memory := Void
	    if eiffel_view /= Void then end
	 end
      end

feature {RUN_FEATURE}

   vape_check(enclosing: RUN_FEATURE; call_site: POSITION;
	      other: like Current) is
         -- To enforce the VAPE rule. The `Current' client list is the one of
         -- the `enclosing' feature and the `other' is the one of the
	 -- `call_site' which is inside the require assertion.
      require
         other /= Void
      local
         vape: BOOLEAN; i: INTEGER; cn: CLASS_NAME
      do
         if is_omitted then
            -- It is as {ANY}:
            vape := other.gives_permission_to_any
         elseif list = Void then
            -- It is {NONE}:
            vape := true
         else
            from
               vape := true
               i := list.count
            until
               not vape or else i = 0
            loop
               cn := list.item(i)
               vape := other.gives_permission_to(cn)
               i := i - 1
            end
         end
         if not vape then
            error_handler.append("(VAPE): The content of a require assertion must %
		      %also be visible by the caller of the routine (i.e. %
		      %the client must be able to check the require %
		      %assertion before calling the routine). See next %
		      %two following reports for details.")
            error_handler.print_as_error
	    --
            error_handler.add_position(call_site)
            error_handler.append("This call which is inside the require assertion is %
		       %exported to ")
	    error_handler.append(other.eiffel_view)
	    other.locate_in_error_handler
	    error_handler.extend('.')
            error_handler.print_as_error
	    --
            error_handler.add_position(enclosing.start_position)
            error_handler.append("This routine, is exported to ")
	    error_handler.append(Current.eiffel_view)
	    Current.locate_in_error_handler
            error_handler.append(" (when the type of Current is ")
            error_handler.append(enclosing.current_type.run_time_mark)
            error_handler.append(" ).")
            if cn /= Void then
	       error_handler.append(" (Class ")
	       error_handler.append(cn.to_string)
	       error_handler.append(" is not allowed to use the code inside the %
			 %require assertion.)")
            end
            error_handler.print_as_fatal_error
         end
      end

feature {CLIENT_LIST_VISITOR}

   accept(visitor: CLIENT_LIST_VISITOR) is
      do
         visitor.visit_client_list(Current)
      end

feature {CLIENT_LIST, CLIENT_LIST_VISITOR}

   list: CLASS_NAME_LIST

feature {NONE}

   make(sp: like start_position; l: like list) is
         -- When the client list is really written.
         --
         -- Note : {NONE} has the same meaning as {}.
      require
         not sp.is_unknown
      do
         start_position := sp
         list := l
	 debug
	    if eiffel_view /= Void then end
	 end
      ensure
         start_position = sp
         list = l
      end

   omitted is
         -- When the client list is omitted. (Remind that when the
         -- client list is omitted, it is like {ANY}.)
      do
      end

   merge(sp: like start_position; l1, l2: like list) is
      require
         not sp.is_unknown
      do
         start_position := sp
         create list.merge(l1,l2)
	 debug
	    eiffel_view_memory := Void
	    if eiffel_view /= Void then end
	 end
      end

   eiffel_view_memory: STRING
	 -- To cache the Result of `eiffel_view'.

end -- CLIENT_LIST