-- This file is part of SmartEiffel The GNU Eiffel Compiler. -- Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE -- Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr -- http://SmartEiffel.loria.fr -- 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. -- class PARENT_LIST -- -- To store the parent list of a class. -- inherit GLOBALS creation make feature base_class: BASE_CLASS -- Where the parent list is written. start_position: POSITION -- Of the keyword "inherit". heading_comment: COMMENT -- Global comment of the inherit clause. count: INTEGER is do Result := list.count end up_to_any_in(pl: FIXED_ARRAY[BASE_CLASS]) is local i: INTEGER p: PARENT bc: BASE_CLASS do from i := list.upper until i < list.lower loop p := list.item(i) bc := p.base_class if not pl.fast_has(bc) then pl.add_last(bc) end i := i - 1 end from i := list.upper until i < list.lower loop p := list.item(i) bc := p.base_class if bc /= class_any then bc.up_to_any_in(pl) end i := i - 1 end end base_class_name: CLASS_NAME is do Result := base_class.name end has_redefine(fn: FEATURE_NAME): BOOLEAN is require fn /= Void local i: INTEGER do from i := list.upper until Result or else i < list.lower loop Result := list.item(i).has_redefine(fn) i := i - 1 end end feature {BASE_CLASS} id_extra_information(tfw: TEXT_FILE_WRITE) is local i: INTEGER do tfw.put_integer(count) tfw.put_string(once " parents: ") from i := list.lower until i > list.upper loop list.item(i).id_extra_information(tfw) tfw.put_character(' ') i := i + 1 end end up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is local p1, p2: PARENT; fn1, fn2, new_fn: FEATURE_NAME; i: INTEGER do from i := list.upper until i < list.lower or else fn1 /= Void loop p1 := list.item(i) fn1 := p1.up_to_original(bottom,top_fn) i := i - 1 end from until i < list.lower loop p2 := list.item(i) fn2 := p2.up_to_original(bottom,top_fn) if fn2 /= Void then new_fn := p2.do_rename(top_fn) if p2.has_select_for(new_fn) then p1 := p2 fn1 := fn2 end end i := i - 1 end if fn1 /= Void then if fn1.to_string /= top_fn.to_string then Result := repeated_inheritance(p1,fn1,top_fn) else Result := fn1 end end end original_name(top: BASE_CLASS; bottom_fn: FEATURE_NAME): FEATURE_NAME is require top /= Void bottom_fn /= Void local p1: PARENT; fn1: FEATURE_NAME; i: INTEGER do from i := list.upper until i < list.lower or else fn1 /= Void loop p1 := list.item(i) fn1 := p1.original_name(top,bottom_fn) i := i - 1 end Result := fn1 if Result = Void then Result := bottom_fn error_handler.add_position(bottom_fn.start_position) error_handler.append(top.name.to_string) error_handler.append(". PARENT_LIST.original_name, Not Yet Implemented.") error_handler.print_as_warning end end clients_for(fn: FEATURE_NAME): CLIENT_LIST is require fn /= Void local i: INTEGER; cl: CLIENT_LIST do from i := list.upper until i < list.lower loop cl := list.item(i).clients_for(fn) if Result = Void then Result := cl elseif cl /= Void then Result := Result.append(cl) end if Result = Void then i := i - 1 elseif Result.gives_permission_to_any then i := list.lower - 1 else i := i - 1 end end end going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS top_fn: FEATURE_NAME;): FEATURE_NAME is require top /= Void top_fn /= Void local i: INTEGER p1, p2: PARENT fn1, fn2: FEATURE_NAME do from i := list.upper until fn1 /= Void or else i < list.lower loop p1 := list.item(i) fn1 := p1.going_up(trace,top,top_fn) i := i - 1 end from until i < list.lower loop p2 := list.item(i) fn2 := p2.going_up(trace,top,top_fn) if fn2 /= Void then if p2.has_select_for(fn2) then p1 := p2 fn1 := fn2 end end i := i - 1 end Result := fn1 end is_a_vncg(t1, t2: E_TYPE): BOOLEAN is require t1.run_type = t1 t2.run_type = t2 t2.generic_list /= Void error_handler.is_empty local i: INTEGER do from i := list.upper until Result or else i < list.lower loop Result := list.item(i).is_a_vncg(t1,t2) i := i - 1 end ensure error_handler.is_empty end graph_node_vncg_update(site: POSITION; t1, t2: E_TYPE): BOOLEAN is require t1.is_a(t2) t1.run_type = t1 t2.run_type = t2 t2.generic_list /= Void local i: INTEGER do from i := list.upper until Result or else i < list.lower loop Result := list.item(i).graph_node_vncg_update(site,t1,t2) i := i - 1 end end e_feature(fn: FEATURE_NAME): E_FEATURE is local i: INTEGER do from i := list.upper until Result /= Void or else i < list.lower loop Result := list.item(i).e_feature(fn) i := i - 1 end end collect_invariant(rc: RUN_CLASS) is require rc /= Void local i: INTEGER do from i := list.upper until i < list.lower loop list.item(i).base_class.collect_invariant(rc) i := i - 1 end end inherit_cycle_check is local i: INTEGER p: PARENT bc: BASE_CLASS do from i := list.upper until i < list.lower loop p := list.item(i) bc := p.type.base_class if bc = Void then error_handler.add_position(p.start_position) error_handler.append(fz_cnf) error_handler.print_as_fatal_error else bc.inherit_cycle_check end i := i - 1 end end has_parent(c: BASE_CLASS): BOOLEAN is require not c.is_any local i: INTEGER bc: BASE_CLASS do from i := list.upper until Result or else i < list.lower loop bc := list.item(i).base_class if c = bc then Result := true elseif bc.is_subclass_of(c) then Result := true else i := i - 1 end end end first_parent_for(c: BASE_CLASS): PARENT is -- Gives the first parent going to `c'. local i: INTEGER pbc: BASE_CLASS do from i := list.lower until Result /= Void loop Result := list.item(i) pbc := Result.base_class if pbc = c then elseif pbc.is_subclass_of(c) then else Result := Void end i := i + 1 end ensure Result /= Void end next_parent_for(c: BASE_CLASS; previous: PARENT): like previous is -- Gives the next one or Void. local i: INTEGER pbc: BASE_CLASS do from from i := list.lower until Result = previous loop Result := list.item(i) i := i + 1 end Result := Void until Result /= Void or else i > list.upper loop Result := list.item(i) pbc := Result.base_class if pbc = c then elseif pbc.is_subclass_of(c) then else Result := Void end i := i + 1 end end header_comment_for(ci: CLASS_INVARIANT) is local i: INTEGER do from i := list.upper until i < list.lower or else ci.header_comment /= Void loop list.item(i).base_class.header_comment_for(ci) i := i - 1 end end get_started is local i1, i2: INTEGER; p1, p2: PARENT do from i1 := list.upper until i1 < list.lower loop list.item(i1).get_started(Current) i1 := i1 - 1 end if list.count > 1 then -- Checking select : from i2 := list.upper until i2 = list.lower loop from i1 := list.lower invariant i1 < i2 + 1 variant i2 - i1 until i1 = i2 loop p1 := list.item(i1) p2 := list.item(i2) p1.multiple_check(p2) p2.multiple_check(p1) i1 := i1 + 1 end i2 := i2 - 1 end end end look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is local i: INTEGER p1, p2: PARENT f1, f2: E_FEATURE do from i := list.upper until f1 /= Void or else i < list.lower loop p1 := list.item(i) f1 := p1.look_up_for(rc,fn) i := i - 1 end from until i < list.lower loop p2 := list.item(i) f2 := p2.look_up_for(rc,fn) if f2 = Void then elseif f1 = f2 then elseif f2.is_not_mergeable_with(f1) then error_handler.add_position(start_position) error_handler.add_position(f1.start_position) error_handler.add_position(f2.start_position) error_handler.append(fz_ich) error_handler.print_as_fatal_error elseif f2.is_deferred then elseif f1.is_deferred then f1 := f2 p1 := p2 elseif p1.has_redefine(fn) then if p2.has_redefine(fn) then else error_handler.add_position(fn.start_position) error_handler.add_position(p2.start_position) error_handler.add_position(f2.start_position) error_handler.append(em1) error_handler.print_as_fatal_error end elseif p2.has_redefine(fn) then error_handler.add_position(fn.start_position) error_handler.add_position(p1.start_position) error_handler.add_position(f1.start_position) error_handler.append(em1) error_handler.print_as_fatal_error else error_handler.add_position(p2.start_position) error_handler.add_position(p1.start_position) error_handler.add_position(f1.start_position) error_handler.add_position(f2.start_position) error_handler.append(em1) error_handler.print_as_fatal_error end i := i - 1 end Result := f1 end collect_assertion(fn: FEATURE_NAME) is require fn /= Void local i: INTEGER; p1, p2: PARENT; fn1, fn2: FEATURE_NAME do from i := list.upper until i < list.lower loop p2 := list.item(i) fn2 := p2.name_in_parent(fn) if fn2 /= Void and then p2.has_select_for(fn) then p1 := p2 fn1 := fn2 end i := i - 1 end if fn1 /= Void then p1.base_class.collect_assertion(fn1) else from i := list.upper until i < list.lower loop p1 := list.item(i) fn1 := p1.name_in_parent(fn) if fn1 /= Void then p1.base_class.collect_assertion(fn1) end i := i - 1 end end end pretty_print is local i: INTEGER do pretty_printer.set_indent_level(0) if pretty_printer.zen_mode then pretty_printer.indent else pretty_printer.skip(1) end pretty_printer.keyword(once "inherit") pretty_printer.set_indent_level(1) pretty_printer.indent if heading_comment /= Void then heading_comment.pretty_print end from i := list.lower until i > list.upper loop list.item(i).pretty_print i := i + 1 end end smallest_ancestor(type, other: E_TYPE): E_TYPE is require type.base_class.parent_list = Current other.base_class.parent_list /= Void type.is_run_type other.is_run_type local i: INTEGER; p: PARENT; sa: E_TYPE do from i := list.upper until i < list.lower loop p := list.item(i) sa := p.runnable_type(other) if sa.run_time_mark = other.run_time_mark then Result := sa i := list.lower - 1 elseif Result = Void then Result := sa.smallest_ancestor(other) elseif sa.is_a(other) then if Result.is_a(other) then Result := sa.smallest_ancestor(Result) else error_handler.cancel Result := sa end else error_handler.cancel end i := i - 1 end ensure Result.is_run_type end feature {PRECURSOR_CALL} precursor_for(pc: PRECURSOR_CALL; wrf: RUN_FEATURE): EFFECTIVE_ROUTINE is -- Look for the feature for `pc' which is written inside `wrf'. require pc /= Void wrf /= Void local i: INTEGER parent: PARENT f2: like precursor_for do from i := list.upper until Result /= Void or else i < list.lower loop parent := list.item(i) Result := parent.precursor_for(pc,wrf) i := i - 1 end if Result = Void then error_handler.add_position(pc.start_position) error_handler.append("Precursor routine not found.") error_handler.print_as_fatal_error end if base_class.all_check then from until i < list.lower loop parent := list.item(i) f2 := parent.precursor_for(pc,wrf) if f2 /= Void and then f2 /= Result then error_handler.add_position(pc.start_position) error_handler.add_position(Result.start_position) error_handler.add_position(f2.start_position) error_handler.append("Multiple Precursor found (% %must use { ... } ancestor selection).") error_handler.print_as_fatal_error end i := i - 1 end end end feature {NONE} list: FIXED_ARRAY[PARENT] make(bc: like base_class; sp: like start_position hc: like heading_comment; l: like list) is require bc /= Void not sp.is_unknown not l.is_empty do base_class := bc heading_comment := hc start_position := sp list := l ensure base_class = bc start_position = sp heading_comment = hc list = l end repeated_inheritance(p1: PARENT; fn1, top_fn: FEATURE_NAME): FEATURE_NAME is require p1 /= void fn1 /= Void top_fn /= Void local i: INTEGER p2: PARENT bc1: BASE_CLASS do from bc1 := p1.base_class i := list.upper until i < list.lower loop p2 := list.item(i) if p1 /= p2 then if bc1 = p2.base_class then if p2.do_rename(fn1).to_string = top_fn.to_string then Result := top_fn elseif p1.do_rename(fn1).to_string = top_fn.to_string then Result := top_fn end end end i := i - 1 end if Result = Void then Result := fn1 end ensure top_fn /= Void end em1: STRING is "Inheritance clash." invariant base_class /= Void not list.is_empty end -- PARENT_LIST