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
|