--          This file is part of SmallEiffel The GNU Eiffel Compiler.
--          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
--            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
--                       http://www.loria.fr/SmallEiffel
-- SmallEiffel 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. SmallEiffel 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  SmallEiffel;  see the file COPYING.  If not,
-- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
expanded class SWITCH_COLLECTION
   -- 
   -- Unique Global Object in charge of the `switch_collection'.
   --

inherit GLOBALS;

feature {NONE}

   dictionary: DICTIONARY[DICTIONARY[RUN_FEATURE,STRING],STRING] is
	 -- First STRING key is the name of a run type corresponding 
	 -- to a RUN_CLASS.
         -- Embedded dictionary gives all switching points.
      once
	 !!Result.make;
      end;

feature {CALL_PROC_CALL}

   update(target: EXPRESSION; run_feature: RUN_FEATURE) is
      -- Update the switch_collection such that `run_feature' can be 
      -- applied with `target'.
      require
	 target /= Void;
	 run_feature /= Void
      local
	 current_type: TYPE;
	 running: ARRAY[RUN_CLASS];
      do
	 if target.is_current then
	 elseif target.is_manifest_string then
	 else
	    current_type := run_feature.current_type;
	    if current_type.is_reference then
	       running := current_type.run_class.running;
	       if running /= Void and then running.count > 1 then
		  update_with(run_feature);
	       end;
	    end;
	 end;
      end;

feature {C_PRETTY_PRINTER}

   c_define is
	 -- Produce C code for switches.
      local
	 dictionary2: DICTIONARY[RUN_FEATURE,STRING];
	 count1, count2, total: INTEGER;
	 switch: SWITCH;
      do
	 if not dictionary.empty then
	    cpp.swap_on_c;
	    cpp.split_c_now;
	    from  
	       count1 := 1;
	    until
	       count1 > dictionary.count
	    loop
	       dictionary2 := dictionary.item(count1);
	       from  
		  count2 := 1;
	       until
		  count2 > dictionary2.count
	       loop
		  switch.c_define(dictionary2.item(count2));
		  total := total + 1;
		  cpp.incr_elt_c_count(20);
		  count2 := count2 + 1;
	       end;
	       count1 := count1 + 1;
	    end;
	    cpp.split_c_now;
	 end;
	 echo.print_count("Defined Switche",total);
      end;

feature {SMALL_EIFFEL}

   falling_down is
      local
	 dictionary2: DICTIONARY[RUN_FEATURE,STRING];
	 count1, count2: INTEGER;
      do
	 if not dictionary.empty then
	    from  
	       count1 := 1;
	    until
	       count1 > dictionary.count
	    loop
	       dictionary2 := dictionary.item(count1);
	       from  
		  count2 := 1;
	       until
		  count2 > dictionary2.count
	       loop
		  dictionary2.item(count2).fall_down;
		  count2 := count2 + 1;
	       end;
	       count1 := count1 + 1;
	    end;
	 end;
      end;

feature {CECIL_POOL}

   update_with(run_feature: RUN_FEATURE) is
      require
	 run_feature /= Void
      local
	 current_type: TYPE;
	 key1, key2: STRING;
	 dictionary2: DICTIONARY[RUN_FEATURE,STRING];
	 running: ARRAY[RUN_CLASS];
      do
	 current_type := run_feature.current_type;
	 running := current_type.run_class.running;
	 if running /= Void and then running.count > 1 then
	    key1 := current_type.run_time_mark;
	    key2 := run_feature.name.to_key;
	    if dictionary.has(key1) then
	       dictionary2 := dictionary.at(key1);
	       if not dictionary2.has(key2) then
		  dictionary2.put(run_feature,key2);
	       end;
	    else
	       !!dictionary2.make;
	       dictionary2.put(run_feature,key2);
	       dictionary.put(dictionary2,key1);
	    end;
	    check
	       dictionary.at(key1).at(key2) = run_feature
	    end;
	 end;
      end;

feature {C_PRETTY_PRINTER}

   remove(run_feature: RUN_FEATURE) is
      require
	 run_feature /= Void
      local
	 current_type: TYPE;
	 key1, key2: STRING;
	 dictionary2: DICTIONARY[RUN_FEATURE,STRING];
      do
	 current_type := run_feature.current_type;
	 key1 := current_type.run_time_mark;
	 if dictionary.has(key1) then
	    dictionary2 := dictionary.at(key1);
	    key2 := run_feature.name.to_key;
	    dictionary2.remove(key2);
	    check
	       not dictionary.at(key1).has(key2)
	    end;
	 end;
      end;

feature {JVM}

   jvm_define is
	 -- Produce Java byte code for switches.
      local
	 dictionary2: DICTIONARY[RUN_FEATURE,STRING];
	 count1, count2, total: INTEGER;
	 switch: SWITCH;
	 up_rf: RUN_FEATURE;
      do
	 if not dictionary.empty then
	    from  
	       count1 := 1;
	    until
	       count1 > dictionary.count
	    loop
	       dictionary2 := dictionary.item(count1);
	       from  
		  count2 := 1;
	       until
		  count2 > dictionary2.count
	       loop
		  up_rf := dictionary2.item(count2);
		  jvm.set_current_frame(up_rf);
		  switch.jvm_define(up_rf);
		  total := total + 1;
		  count2 := count2 + 1;
	       end;
	       count1 := count1 + 1;
	    end;
	 end;
	 echo.print_count("Defined Switche",total);
      end;
   
end -- SWITCH_COLLECTION

