///////////////////////////////////////////////////////////////////////////////
//                             Lisaac Compiler                               //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program 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 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header
  
  + name        := ITM_LIST;

  - copyright   := "2003-2007 Benoit Sonntag";

  
  - author      := "Sonntag Benoit (bsonntag@loria.fr)";
  - comment     := "Instruction list";
  
Section Inherit
  
  + parent_itm_code:Expanded ITM_CODE;
  
Section Public
  
  // BSBS: OPTIM : Dans 95% des cas, les list sont sans local (il faudrait spécialiser)
  // Mais pb avec le parser...
  
  //
  // Data
  //

  + local_list:FAST_ARRAY[ITM_LOCAL];  // `+'
  
  + static_list:FAST_ARRAY[ITM_LOCAL]; // `-'

  + code:FAST_ARRAY[ITM_CODE];
  
  + is_check_name:BOOLEAN;
  
  - is_check_local:INTEGER;
  
  //
  // Constructor
  //

  - create p:POSITION :SELF <-
  ( + result:SELF;
    result := clone;
    result.make p;
    result
  );
  
  - make p:POSITION <-
  (
    position := p;   
  );
 
  //
  // Added
  //

  - set_local_list l:FAST_ARRAY[ITM_LOCAL] <-
  (
    ? {! l.is_empty};
    local_list := l;
  );

  - set_static_list l:FAST_ARRAY[ITM_LOCAL] <-
  (
    ? {! l.is_empty};
    static_list := l;
  );
  
  - set_code c:FAST_ARRAY[ITM_CODE] <-
  (
    code := c;
  );    
  
Section Public
  
  - is_affect:POSITION <-
  ( + result,default:POSITION;
    + j:INTEGER;
    + itm_r:ITM_RESULT;
    
    j := code.lower;
    {(j < code.upper) && {result = default}}.while_do {
      itm_r ?= code.item j;
      (itm_r != NULL).if {
	result := itm_r.is_affect;
      } else {
	result := code.item j.position;
      };
      j := j + 1;
    };
    (result = default).if {
      result := code.last.is_affect;
    };
    result
  );
  
  //
  // Runnable.
  //
  
  - to_run_extern <-
  // List extern.
  ( + nb_result_list:INTEGER;
    + nb_result_slot:INTEGER;
                     
    // Creation list.
    to_run_base FALSE;
    
    (verify).if {      
      // Verify Result cardinality.
      nb_result_list := stack_result.upper - stack_result_lower + 1;
      (profil_first.result_last != NULL).if {		
	(profil_first.result_list != NULL).if {
	  nb_result_slot := profil_first.result_list.count + 1;
	} else {
	  nb_result_slot := 1;
	};
      };
	
      (nb_result_list != nb_result_slot).if {	
	semantic_error ((profil_first.slot.position),"Value result missing");
      };      
    };
  );

  - to_run_expr:EXPR <- 
  // List intern.
  ( + result:EXPR;
                
    CONTEXT.push_intern position;        
    
    to_run_base TRUE;        
    result := create_result_expr;
    
    CONTEXT.pop_intern;    
    list_current.add_last last_expr;
    
    result
  );
  
  - to_run_contract:LIST <- 
  // List intern.
  ( + lst:LIST;
    ? {! code.is_empty};
    
    CONTEXT.push_intern position;        
    //    
    to_run_base TRUE;
    lst := list_current;
    //
    CONTEXT.pop_intern;    
    lst
  );
  
Section ITM_LIST, PROFIL_BLOCK
  
  - to_run_base last_out:BOOLEAN <-
  ( + i:INSTR;
    + var:LOCAL;
    + expr:EXPR;
    + stack_top:INTEGER;
    
    stack_top := stack_local.upper + 1;
    // Push Local.
    (local_list != NULL).if {      
      (local_list.lower).to (local_list.upper) do { j:INTEGER;
	var := local_list.item j.to_run;
	stack_local.add_last var;
	var.init;	
      };      
    };
    (static_list != NULL).if {            
      (static_list.lower).to (static_list.upper) do { j:INTEGER;
	var := static_list.item j.to_run_static;
	stack_local.add_last var;		
      };      
    };
        
    // Append code.
    (code.lower).to (code.upper - 1) do { j:INTEGER;
      i := code.item j.to_run;      
      list_current.add_last i;
    };    
    // Result
    (! code.is_empty).if {
      expr := code.last.to_run_expr;
      (expr.static_type.raw = TYPE_VOID).if {
	list_current.add_last expr;
      } else {
	i := expr.put_result last_out;
	list_current.add_last i;
	(last_out).if_false {
	  list_current.add_last (PROTOTYPE_CST.create position type (TYPE_VOID.default));
	};
      };
    };
    
    // Pop local.
    pop_stack_until stack_top;
  );
  
  //
  //
  //
  
  - last_expr:INSTR;
  
  - create_result_expr:EXPR <-
  ( + result:EXPR;
    + var:VARIABLE;
    + val:EXPR;
    + nb_result:INTEGER;
    + lr:FAST_ARRAY[EXPR];
    + has_last:BOOLEAN;
    
    has_last := (list_current.static_type.raw != TYPE_VOID);
    nb_result := stack_result.upper - stack_result_lower + 1 + has_last.to_integer;
    
    (nb_result = 0).if {      
      last_expr := list_current;
      result    := PROTOTYPE_CST.create position type (TYPE_VOID.default);      
    } else {
      (has_last).if {
	
	(list_current.static_type = NULL).if {
	  list_current.debug_display;
	};
	
	var := list_current.static_type.get_temporary position;
	last_expr := var.write position value list_current;	
      } else {
	var := stack_result.last;
      };      
      result := var.read position;
      (nb_result > 1).if {
	// Creation Vector.
	lr := FAST_ARRAY[EXPR].create_with_capacity nb_result;
	(stack_result_lower).to (stack_result_lower + nb_result - 2) do { j:INTEGER;
	  val := stack_result.item j.read position;
	  lr.add_last val;
	};
	lr.add_last result;
	result := EXPR_MULTIPLE.create lr;
      };
    };
          
    ? {result != NULL};
    result
  );
  
  - create_result_list:FAST_ARRAY[LOCAL] <-
  ( + result:FAST_ARRAY[LOCAL];
    + nb_result:INTEGER;
    + loc:LOCAL;
        
    nb_result := stack_result.upper - stack_result_lower + 1;    
        
    (nb_result != 0).if {      
      result := FAST_ARRAY[LOCAL].create_with_capacity nb_result;
      (stack_result_lower).to (stack_result.upper) do { j:INTEGER;
	loc := stack_result.item j;
	result.add_last loc; 	
      };
    };
    result
  );




