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 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
|
-- 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
--
deferred class CLASS_CHECKER
--
-- Common parent of SHORT and CLASS_CHECK
--
inherit
COMMAND_LINE_TOOLS
feature {CLASS_CHECKER_VISITOR}
make_for_visitor is
-- An empty creator used by `CLASS_CHECKER_VISITOR'
do
end
parents: FIXED_ARRAY[BASE_CLASS] is
-- From `ace..root_class' up to ANY included.
once
create Result.with_capacity(4)
end
run_class: RUN_CLASS
-- The corresponding one of the class to class_check.
short_list: SHORT_LIST is
-- To be printed by the short command.
once
create Result.make
end
client: CLASS_NAME
-- The client for whom the class is class_check'ed (-client flag).
-- If no client is provided on the command line, the default is ANY.
format: STRING
-- The selected format directory to find hooks files.
sort: BOOLEAN
-- True if the -sort flag is used.
obsolete_type_string: MANIFEST_STRING
-- Non Void when the class to short is itself obsolete.
output: OUTPUT_STREAM
root_class_names: FIXED_ARRAY[STRING] is
once
create Result.with_capacity(1)
end
short: BOOLEAN
start is
-- Should be called by the make procedure of short or class_check
require
output /= Void
local
bc: BASE_CLASS; cn: CLASS_NAME; i: INTEGER
do
smart_eiffel.set_short_flag
parse_arguments
-- Force client class lookup:
bc := smart_eiffel.base_class(client)
-- Set the output stream:
short_print.set_out_stream(output)
from
i := root_class_names.lower
until
i > root_class_names.upper
loop
create cn.unknown_position(root_class_names.item(i))
bc := smart_eiffel.base_class(cn)
obsolete_type_string := bc.obsolete_type_string
if not smart_eiffel.no_file_for(bc.name.to_string) then
class_check(bc)
end
i := i + 1
end
end
parse_arguments is
deferred
ensure
client /= Void
format /= Void
not root_class_names.is_empty
end
class_check(bc: BASE_CLASS) is
-- Actually check the class `bc'
local
ccl: CREATION_CLAUSE_LIST; name: STRING
obsolete_flag, file_exist_flag: BOOLEAN
do
file_exist_flag := not smart_eiffel.no_file_for(bc.name.to_string)
if file_exist_flag then
parents.clear
parents.add_last(bc)
if not short then
bc.up_to_any_in(parents)
end
else
name := bc.name.to_string
if as_none = name then
none_documentation(bc)
elseif as_tuple = name then
tuple_documentation(bc)
elseif as_routine = name then
routine_documentation(bc)
elseif as_procedure = name then
procedure_documentation(bc)
elseif as_function = name then
function_documentation(bc)
elseif as_predicate = name then
predicate_documentation(bc)
else
check -- Forgot this one ?
False
end
end
end
-- Prepare data:
compute_run_class(bc)
run_class.runnable_class_invariant
-- Print the class interface:
short_print.start(format, bc, run_class)
if obsolete_type_string /= Void then
obsolete_flag := True
obsolete_type_string.set_once_flag(False)
obsolete_type_string.short
short_print.a_character('%N')
else
ccl := bc.creation_clause_list
if ccl = Void or else not ccl.short(client) then
short_print.hook(once "hook102")
end
compute_short_list_for(client)
if sort then
if not short_list.is_empty then
short_print.hook_or(once "hook200",once "feature(s)%N")
end
short_list.do_sorted_print
else
-- Nothing to do because features are actually already printed
-- using the order of feature clauses in various source files.
end
short_print.hook(once "hook201")
end
short_print.finish(obsolete_flag)
end
set_format(a_format: like format) is
do
format := a_format
end
set_client(a_client: STRING) is
require
string_aliaser.item(a_client) = a_client
do
create client.unknown_position(a_client)
end
compute_run_class(bc: BASE_CLASS) is
local
ct, t: E_TYPE; constraints: DICTIONARY[E_TYPE, STRING]
i: INTEGER; fgl: FORMAL_GENERIC_LIST; sp: POSITION
fga: FORMAL_GENERIC_ARG
do
-- Creates the `constraints' substitution dictionary first:
fgl := bc.formal_generic_list
if fgl /= Void then
from
sp := bc.name.start_position
i := 1
create constraints.make
until
i > fgl.count
loop
fga := fgl.item(i)
t := fga.constraint
if t = Void then
constraints.put(create {TYPE_ANY}.make(sp),
fga.name.to_string)
elseif t.base_class.formal_generic_list = Void then
constraints.put(t, fga.name.to_string)
end
i := i + 1
end
end
ct := run_type_for(bc, sp, constraints)
run_class := ct.run_class
end
compute_short_list_for(cn: CLASS_NAME) is
local
i: INTEGER; bc: BASE_CLASS; rc: RUN_CLASS; fcl: FEATURE_CLAUSE_LIST
do
from
i := parents.upper
rc := run_class
until
i < 0
loop
bc := parents.item(i)
fcl := bc.feature_clause_list
if fcl /= Void then
fcl.for_short(bc.name, False, short_list, rc, cn)
end
i := i - 1
end
end
fatal_bad_usage is
do
system_tools.bad_use_exit(Current)
end
feature {NONE}
run_type_for(bc: BASE_CLASS; sp: POSITION
constraints: DICTIONARY[E_TYPE, STRING]): E_TYPE is
-- Create a valid runnable one. The `constraints' dictionary
-- is used to substitute nested generic formal arguments.
local
bcn: STRING; fgl: FORMAL_GENERIC_LIST
t: E_TYPE; gl: ARRAY[E_TYPE]; i: INTEGER; fga: FORMAL_GENERIC_ARG
do
bcn := bc.name.to_string
fgl := bc.formal_generic_list
if as_any = bcn then
create {TYPE_ANY} Result.make(sp)
elseif as_native_array = bcn then
create {TYPE_CHARACTER} t.make(sp)
create {TYPE_NATIVE_ARRAY} Result.make(sp, t)
elseif as_array = bcn then
create {TYPE_ANY} t.make(sp)
create {TYPE_ARRAY} Result.make(sp, t)
elseif as_integer_8 = bcn then
create {TYPE_INTEGER} Result.integer_8(sp)
elseif as_integer_16 = bcn then
create {TYPE_INTEGER} Result.integer_16(sp)
elseif as_integer_32 = bcn then
create {TYPE_INTEGER} Result.integer_32(sp)
elseif as_integer = bcn then
create {TYPE_INTEGER} Result.integer(sp)
elseif as_integer_64 = bcn then
create {TYPE_INTEGER} Result.integer_64(sp)
elseif as_integer_general = bcn then
create {TYPE_INTEGER} Result.integer_general(sp)
elseif as_real = bcn then
create {TYPE_REAL} Result.make(sp)
elseif as_double = bcn then
create {TYPE_DOUBLE} Result.make(sp)
elseif as_character = bcn then
create {TYPE_CHARACTER} Result.make(sp)
elseif as_boolean = bcn then
create {TYPE_BOOLEAN} Result.make(sp)
elseif as_pointer = bcn then
create {TYPE_POINTER} Result.make(sp)
elseif as_string = bcn then
create {TYPE_STRING} Result.make(sp)
elseif as_none = bcn then
create {TYPE_NONE} Result.make(sp)
elseif fgl /= Void then
from
i := 1
create gl.with_capacity(fgl.count, 1)
until
i > fgl.count
loop
fga := fgl.item(i)
t := constraints.reference_at(fga.name.to_string)
if t = Void then
t := fga.constraint
t := run_type_for(t.base_class, sp, constraints)
end
gl.add_last(t)
i := i + 1
end
create {TYPE_GENERIC} Result.make(bc.name, gl)
else
create {TYPE_CLASS} Result.make(bc.name)
end
Result := Result.to_runnable(create {TYPE_ANY}.make(sp))
ensure
Result.is_run_type
end
none_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_none
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
Note: actually, the NONE class is an artefact of the Eiffel language
definition. The NONE class is supposed to inherit of all existing
classes of the entire system.
Actually, the NONE class cannot be written (i.e. there is no file for
this class and this class is magically written by the compiler).
]")
bc.set_heading_comment2(comment)
end
tuple_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_tuple
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
The main purpose of the TUPLE class is allow you to manipulate Eiffel
agents and to avoid in some cases to write simple record-like classes.
For a good start with TUPLE class, you might consider to have a look
in directory SmartEiffel/tutorial/tuple.
For more details about agents, see also ROUTINE, PROCEDURE, FUNCTION
and PREDICATE as well as examples from SmartEiffel/tutorial/agent.
]")
bc.set_heading_comment2(comment)
end
routine_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_routine
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
The main purpose of the ROUTINE class is allow you to manipulate Eiffel
code parts, also known as agents using the Eiffel terminology.
The only thing you can do on a ROUTINE object is to run the corresponding
Eiffel code by using the `call' procedure.
For more details about agents, you might consider first to have a look
at examples from SmartEiffel/tutorial/agent directory.
Note: there is no file for this class (this class is magically provided
by the compiler).
]")
bc.set_heading_comment2(comment)
end
procedure_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_procedure
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
The main purpose of the PROCEDURE class is allow you to manipulate Eiffel
code parts, also known as agents using the Eiffel terminology.
The only thing you can do on a PROCEDURE object is to run the corresponding
Eiffel code by using the `call' procedure.
For more details about agents, you might consider first to have a look
at examples from SmartEiffel/tutorial/agent directory.
Note: there is no file for this class (this class is magically provided
by the compiler).
]")
bc.set_heading_comment2(comment)
end
function_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_function
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
The main purpose of the FUCNTION class is allow you to manipulate Eiffel
code parts, also known as agents using the Eiffel terminology.
The only thing you can do on a FUCNTION object is to run the corresponding
Eiffel code by using the `item' procedure.
For more details about agents, you might consider first to have a look
at examples from SmartEiffel/tutorial/agent directory.
Note: there is no file for this class (this class is magically provided
by the compiler).
]")
bc.set_heading_comment2(comment)
end
predicate_documentation(bc: BASE_CLASS) is
require
bc.name.to_string = as_predicate
local
comment: COMMENT
do
create comment.fake_comment(bc,
"[
The main purpose of the PREDICATE class is allow you to manipulate Eiffel
code parts, also known as agents using the Eiffel terminology.
The only thing you can do on a PREDICATE object is to run the corresponding
Eiffel code by using the `call' procedure.
For more details about agents, you might consider first to have a look
at examples from SmartEiffel/tutorial/agent directory.
Note: there is no file for this class (this class is magically provided
by the compiler).
]")
bc.set_heading_comment2(comment)
end
invariant
out /= Void
end
|