
#include "p.script_parser.h"

/*
 * array of callers of run action functions
 */

const unsigned c_script_run_action_cnt = 27;
void(*script_ra_callers[c_script_run_action_cnt])(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this) = {
   ra_flow_end,
   ra_return,
   ra_cmd_block_begin,
   ra_cmd_block_end,
   ra_false_jmp,
   ra_true_jmp,
   ra_jmp,
   ra_local_cross_jmp,
   ra_cmd_return,
   ra_exp_end,
   ra_this_var,
   ra_param_var,
   ra_local_var,
   ra_global_var,
   ra_this_call,
   ra_global_call,
   ra_s_element,
   ra_s_method_call,
   ra_new_object,
   ra_this,
   ra_thread,
   ra_new_char_array,
   ra_new_int_array,
   ra_new_double_array,
   ra_new_array,
   ra_array_element,
   ra_const,
};

/*
 * functions running during execution of code
 */

/*
 * function ends run of actual flow of program
 */

void ra_flow_end(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   code_idx = c_idx_not_exist;
}

/*
 * return from subprogram (function) at its end
 */

void ra_return(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   rc_position_array_s &rc_position_array = sp_thread.rc_position_array;
   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - remove of variable space of function -
   this_variables.used--;
   param_variables_array.used--;
   ui_array_s &locals = local_variables_array.pop();

   // - freeing of function local variables -
   if (locals.used != 0) {
      unsigned *l_var_ptr = locals.data;
      unsigned *l_var_ptr_end = l_var_ptr + locals.used;

      do {
	 value_location_pool.free_value(*l_var_ptr);
      } while(++l_var_ptr < l_var_ptr_end);
   }

   tmp_variables_array.used--;

   // - store of return value of function (end of function without return command always return 0) -
   unsigned ret_value_location_idx = value_location_pool.insert(c_value_type_INT,0,c_value_modifier_TMP);
   tmp_variables_array.last().push(ret_value_location_idx);
   exp_stack.push(ret_value_location_idx);

   // - return to code after function call -
   rc_position_array.pop();
}

/*
 * process of begin of new command block
 */

void ra_cmd_block_begin(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;

   // *****

   // - creation of new space for local variables -
   local_variables_array.push_blank();
   local_variables_array.last().used = 0;
}

/*
 * process of end of command block
 */

void ra_cmd_block_end(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;

   // *****

   ui_array_s &locals = local_variables_array.pop();

   // - release of local variables -
   if (locals.used != 0) {
      unsigned *l_var_ptr = locals.data;
      unsigned *l_var_ptr_end = l_var_ptr + locals.used;

      do {
	 value_location_pool.free_value(*l_var_ptr);
      } while(++l_var_ptr < l_var_ptr_end);
   }
}

/*
 * process of conditional jump, jump if condition is false
 */

void ra_false_jmp(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
  
   // - retrieve value from stack top -
   value_location_s &location = value_location_pool[exp_stack.pop()];

   // - test of value -
   switch (location.ui_first) {
   case c_value_type_CHAR:
      if (value_location_pool.get_char_value(location)) {
	 code_idx++;
      }
      else {
	 code_idx = code[code_idx];
      }
      break;
   case c_value_type_SHORT:
      if (value_location_pool.get_short_value(location)) {
	 code_idx++;
      }
      else {
	 code_idx = code[code_idx];
      }
      break;
   case c_value_type_INT:
      if (value_location_pool.get_int_value(location)) {
	 code_idx++;
      }
      else {
	 code_idx = code[code_idx];
      }
      break;
   case c_value_type_DOUBLE:
      if (value_location_pool.get_double_value(location)) {
	 code_idx++;
      }
      else {
	 code_idx = code[code_idx];
      }
      break;
   default:
      err_test2(0,c_R_ERR_EXPECTED_NUMBER_EXPRESSION,_this.get_line_number(a_thread_idx),(unsigned)"condition");
   }

   // - remove of expression temporary values -
   _this.remove_tmp_values(a_thread_idx);
}

/*
 * process of conditional jump, jump if condition id true
 */

void ra_true_jmp(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
  
   // - retrieve of value from stack top -
   value_location_s &location = value_location_pool[exp_stack.pop()];

   // - test of value -
   switch (location.ui_first) {
   case c_value_type_CHAR:
      if (value_location_pool.get_char_value(location)) {
	 code_idx = code[code_idx];
      }
      else {
	 code_idx++;
      }
      break;
   case c_value_type_SHORT:
      if (value_location_pool.get_short_value(location)) {
	 code_idx = code[code_idx];
      }
      else {
	 code_idx++;
      }
      break;
   case c_value_type_INT:
      if (value_location_pool.get_int_value(location)) {
	 code_idx = code[code_idx];
      }
      else {
	 code_idx++;
      }
      break;
   case c_value_type_DOUBLE:
      if (value_location_pool.get_double_value(location)) {
	 code_idx = code[code_idx];
      }
      else {
	 code_idx++;
      }
      break;
   default:
      err_test2(0,c_R_ERR_EXPECTED_NUMBER_EXPRESSION,_this.get_line_number(a_thread_idx),(unsigned)"condition");
   }

   // - remove of temporary value of expression -
   _this.remove_tmp_values(a_thread_idx);
}

/*
 * jump to other part of code
 */

void ra_jmp(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   code_idx = code[code_idx];
}

/*
 * jump which crosses local variables definition (jump from block of code)
 * - release of crossed local variables
 */

void ra_local_cross_jmp(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;

   // *****

   unsigned local_drop_cnt = code[code_idx++];
  
   // - release of local variables -
   if (local_drop_cnt != 0) {
      do {
	 ui_array_s &locals = local_variables_array.pop();

	 if (locals.used != 0) {
	    unsigned *l_var_ptr = locals.data;
	    unsigned *l_var_ptr_end = l_var_ptr + locals.used;

	    do {
	       value_location_pool.free_value(*l_var_ptr);
	    } while(++l_var_ptr < l_var_ptr_end);
	 }
      } while(--local_drop_cnt > 0);
   }

   // - jump in code -
   code_idx = code[code_idx];
}

/*
 * process of return from function, by command return
 */

void ra_cmd_return(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   rc_position_array_s &rc_position_array = sp_thread.rc_position_array;
   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - process of function return value -
   unsigned return_location_idx = exp_stack.last();
   value_location_s &return_location = value_location_pool[return_location_idx];
   
   if (!(return_location.uc_third & c_value_modifier_INDEXED) && (return_location.uc_third & c_value_modifier_WRITABLE)) {
      return_location.uc_third |= c_value_modifier_TMP;
   }

   // - move of temporary value one level down -
   ui_array_s &tmp_variables = tmp_variables_array.pop();
   ui_array_s &tmp_variables_last = tmp_variables_array.last();
   
   if (tmp_variables.used != 0) {
      unsigned *tv_ptr = tmp_variables.data;
      unsigned *tv_ptr_end = tv_ptr + tmp_variables.used;

      do {
	 tmp_variables_last.push(*tv_ptr);
      } while(++tv_ptr < tv_ptr_end);
   }

   // - release of variable space -
   this_variables.used--;
   param_variables_array.used--;

   // - registering of local variables as temporary one level down -
   unsigned local_space_cnt = code[code_idx++];
   do {
      ui_array_s &locals = local_variables_array.pop();

      if (locals.used != 0) {
	 unsigned *l_ptr = locals.data;
	 unsigned *l_ptr_end = l_ptr + locals.used;

	 do {
	    tmp_variables_last.push(*l_ptr);
	 } while(++l_ptr < l_ptr_end);
      }
   } while(--local_space_cnt > 0);

   // - return to code after function call -
   rc_position_array.pop();
}

/*
 * process of expression end
 */

void ra_exp_end(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
  
   // - release of temporary variables -
   _this.remove_tmp_values(a_thread_idx);

   // - remove of expression stack -
   exp_stack.pop();
}

/*
 * insertion of structure element to expression stack
 */

void ra_this_var(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &this_variables = sp_thread.this_variables;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - location which describes variable "this" -
   value_location_s &this_location = value_location_pool[this_variables.last()];

   // - insert of element position to stack -
   exp_stack.push((*IM_ACCESS_STRUCT_PTR(this_location.ulli_second))[code[code_idx++]]);
}

/*
 * insertion of variable which describes function parameter at stack
 */

void ra_param_var(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - insertion of parameter to stack -
   exp_stack.push(param_variables_array.last()[code[code_idx++]]);
}

/*
 * insertion of local variable to stack
 */

void ra_local_var(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   //*****

   // - selection of local variable record -
   ui_array_s &locals = local_variables_array[local_variables_array.used - 1 - code[code_idx++]];
   unsigned local_idx = code[code_idx++];

   // - creation of local variable if not exist yet -
   while(locals.used <= local_idx) {
      unsigned var_location_idx = value_location_pool.insert(c_value_type_BLANK,(unsigned long long)c_idx_not_exist,c_value_modifier_WRITABLE);

      locals.push(var_location_idx);
   }

   // - insertion of variable on top of stack -
   exp_stack.push(locals[local_idx]);
}

/*
 * insertion of global variable on expression stack
 */

void ra_global_var(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   ui_array_s &global_variables = _this.global_variables;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   //*****

   unsigned global_idx = code[code_idx++];

   // - creation of global variables if not exist yet -
   while(global_variables.used <= global_idx) {
      unsigned var_location_idx = value_location_pool.insert(c_value_type_BLANK,(unsigned long long)c_idx_not_exist,c_value_modifier_WRITABLE);

      global_variables.push(var_location_idx);
   }

   // - insertion of variable location at stack top -
   exp_stack.push(global_variables[global_idx]);
}

/*
 * call of method of actual structure
 */

void ra_this_call(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   symbol_records_s &symbol_records = _this.symbol_records;
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   rc_position_array_s &rc_position_array = sp_thread.rc_position_array;
   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - acquire of location of this variable -
   value_location_s &this_location = value_location_pool[this_variables.last()];

   // - selection of symbol describing called function -
   symbol_s &fun_symbol = symbol_records[this_location.ui_first].symbols_array[c_symbol_type_function][code[code_idx++]];

   // - retrieve of count of function parameters -
   symbols_s &fun_param_symbols = symbol_records[fun_symbol.ui_third].symbols_array[c_symbol_type_fun_param];
   unsigned fun_param_cnt = fun_param_symbols.used;

   // - creation of space for variables -
   this_variables.push(this_variables.last());
   param_variables_array.push_blank();
   param_variables_array.last().used = 0;

   // - copy of parameters of function from expression stack -
   ui_array_s &fun_params = param_variables_array.last();

   if (fun_param_cnt != 0) {
      symbol_s *fun_param_symbol_ptr = fun_param_symbols.data;
      unsigned *parm_ptr_end = exp_stack.data + exp_stack.used;
      unsigned *parm_ptr = parm_ptr_end - fun_param_cnt;

      do {
	 
	 // - if parameter is handed by copying -
	 if (fun_param_symbol_ptr->ui_second == c_parm_symbol_type_copy) {
	    unsigned param_location_idx = value_location_pool.copy_create_value(*parm_ptr);
	    fun_params.push(param_location_idx);
	    tmp_variables_array.last().push(param_location_idx);
	 }

	 // - else parameter is handed by reference -
	 else {
	    value_location_pool[*parm_ptr].uc_third &= ~c_value_modifier_TMP;
	    fun_params.push(*parm_ptr);
	 }
      } while(++fun_param_symbol_ptr,++parm_ptr < parm_ptr_end);

      exp_stack.used -= fun_param_cnt;
   }

   // - creation of space for variables -
   local_variables_array.push_blank();
   local_variables_array.last().used = 0;
   tmp_variables_array.push_blank();
   tmp_variables_array.last().used = 0;

   // - call of function code -
   rc_position_array.push_blank();
   rc_position_array.last().set(fun_symbol.ui_second,0);
}

/*
 * call of global function
 */

void ra_global_call(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   symbol_records_s &symbol_records = _this.symbol_records;
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   rc_position_array_s &rc_position_array = sp_thread.rc_position_array;
   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
  
   // - retrieve of symbol describing called function -
   symbol_s &fun_symbol = symbol_records[0].symbols_array[c_symbol_type_function][code[code_idx++]];

   // - index of called function code -
   unsigned call_idx = fun_symbol.ui_second;

   if (call_idx >= c_build_in_call_base) {

      // - call of build in function -
      script_bic_callers[call_idx - c_build_in_call_base](a_thread_idx,_this);
   }
   else {
      // - retrieve of function parameter count -
      symbols_s &fun_param_symbols = symbol_records[fun_symbol.ui_third].symbols_array[c_symbol_type_fun_param];
      unsigned fun_param_cnt = fun_param_symbols.used;

      // - creation of space for variables -
      this_variables.push(c_idx_not_exist);
      param_variables_array.push_blank();
      param_variables_array.last().used = 0;

      // - copying of function parameters from expression stack -
      ui_array_s &fun_params = param_variables_array.last();

      if (fun_param_cnt != 0) {
	 symbol_s *fun_param_symbol_ptr = fun_param_symbols.data;
	 unsigned *parm_ptr_end = exp_stack.data + exp_stack.used;
	 unsigned *parm_ptr = parm_ptr_end - fun_param_cnt;

	 do {
	    
	    // - parameter which is handed by copying -
	    if (fun_param_symbol_ptr->ui_second == c_parm_symbol_type_copy) {
	       unsigned param_location_idx = value_location_pool.copy_create_value(*parm_ptr);
	       fun_params.push(param_location_idx);
	       tmp_variables_array.last().push(param_location_idx);
	    }

	    // - parameter which is handed by reference -
	    else {
	       value_location_pool[*parm_ptr].uc_third &= ~c_value_modifier_TMP;
	       fun_params.push(*parm_ptr);
	    }
	 } while(++fun_param_symbol_ptr,++parm_ptr < parm_ptr_end);

	 exp_stack.used -= fun_param_cnt;
      }

      // - creation of space for local and temporary variables -
      local_variables_array.push_blank();
      local_variables_array.last().used = 0;
      tmp_variables_array.push_blank();
      tmp_variables_array.last().used = 0;

      // - call of function code -
      rc_position_array.push_blank();
      rc_position_array.last().set(fun_symbol.ui_second,0);
   }
}

/*
 * selection of element from structure
 */

void ra_s_element(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   symbol_records_s &symbol_records = _this.symbol_records;
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   unsigned element_n_idx = code[code_idx++];
   unsigned &last_struct_idx = code[code_idx++];
   unsigned &last_element_idx = code[code_idx++];

   // - location of variable describing object structure -
   value_location_s &this_location = value_location_pool[exp_stack.pop()];

   // - record of structure symbols -
   symbols_s &struct_var_symbols = symbol_records[this_location.ui_first].symbols_array[c_symbol_type_struct_variable];

   // - retrieve of symbol describing element of structure -
   if (this_location.ui_first != last_struct_idx) {
      last_struct_idx = this_location.ui_first;
      last_element_idx = struct_var_symbols.get_idx_by_ui_first(element_n_idx);
      err_test4(last_element_idx != c_idx_not_exist,c_R_ERR_STRUCT_X_NOT_DEFINED,_this.get_line_number(a_thread_idx),(unsigned)"Element",(unsigned)_this.symbol_names[element_n_idx].data,(unsigned)_this.symbol_names[symbol_records[0].symbols_array[c_symbol_type_structure][symbol_records[this_location.ui_first].p_symbol_idx].ui_first].data);
   }

   // - insertion of element location at expression stack -
   exp_stack.push((*IM_ACCESS_STRUCT_PTR(this_location.ulli_second))[last_element_idx]);
}

/*
 * calling of structure method
 */

void ra_s_method_call(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   symbol_records_s &symbol_records = _this.symbol_records;
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   rc_position_array_s &rc_position_array = sp_thread.rc_position_array;
   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   unsigned fun_param_cnt = code[code_idx++];
   unsigned op_n_idx = code[code_idx++];
   unsigned &last_struct_idx = code[code_idx++];
   unsigned &last_op_idx = code[code_idx++];

   // - retrieve location of variable describing structure -
   unsigned this_location_idx = exp_stack[exp_stack.used - 1 - fun_param_cnt];
   value_location_s &this_location = value_location_pool[this_location_idx];

   // - record of symbols describing methods of structure -
   symbols_s &fun_symbols = symbol_records[this_location.ui_first].symbols_array[c_symbol_type_function];
   
   // - retrieve of symbol describing called function -
   if (this_location.ui_first != last_struct_idx) {
      last_struct_idx = this_location.ui_first;
      last_op_idx = fun_symbols.get_idx_by_ui_first(op_n_idx);
      err_test4(last_op_idx != c_idx_not_exist,c_R_ERR_STRUCT_X_NOT_DEFINED,_this.get_line_number(a_thread_idx),(unsigned)"Method",(unsigned)_this.symbol_names[op_n_idx].data,(unsigned)_this.symbol_names[symbol_records[0].symbols_array[c_symbol_type_structure][symbol_records[this_location.ui_first].p_symbol_idx].ui_first].data);
   }

   // - position of called code, or index of build in function -
   unsigned call_idx = fun_symbols[last_op_idx].ui_second;

   if (call_idx >= c_build_in_call_base) {

      // - calling of build in function -
      script_bic_callers[call_idx - c_build_in_call_base](a_thread_idx,_this);
   }
   else {
      symbols_s &fun_param_symbols = symbol_records[fun_symbols[last_op_idx].ui_third].symbols_array[c_symbol_type_fun_param];

      // - creation of space for variables -
      this_variables.push(this_location_idx);
      param_variables_array.push_blank();
      param_variables_array.last().used = 0;

      // - copying of function parameters from expression stack -
      ui_array_s &fun_params = param_variables_array.last();

      if (fun_param_cnt != 0) {
	 symbol_s *fun_param_symbol_ptr = fun_param_symbols.data;
	 unsigned *parm_ptr_end = exp_stack.data + exp_stack.used;
	 unsigned *parm_ptr = parm_ptr_end - fun_param_cnt;

	 do {
	    // - parameter id handed by copying its value -
	    if (fun_param_symbol_ptr->ui_second == c_parm_symbol_type_copy) {
	       unsigned param_location_idx = value_location_pool.copy_create_value(*parm_ptr);
	       fun_params.push(param_location_idx);
	       tmp_variables_array.last().push(param_location_idx);
	    }

	    // - parameter is handed by reference -
	    else {
	       value_location_pool[*parm_ptr].uc_third &= ~c_value_modifier_TMP;
	       fun_params.push(*parm_ptr);
	    }
	 } while(++fun_param_symbol_ptr,++parm_ptr < parm_ptr_end);

	 exp_stack.used -= fun_param_cnt;
      }

      // - remove of this variable -
      exp_stack.pop();

      // - creation of space for local and temporary variables -
      local_variables_array.push_blank();
      local_variables_array.last().used = 0;
      tmp_variables_array.push_blank();
      tmp_variables_array.last().used = 0;

      // - jump to function code -
      rc_position_array.push_blank();
      rc_position_array.last().set(call_idx,0);
   }
}

/*
 * creation of new object based on structure type
 */

void ra_new_object(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   symbol_records_s &symbol_records = _this.symbol_records;
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   // - retrieve of structure index -
   unsigned struct_record_idx = code[code_idx++];
   unsigned value_location_idx;

   if (struct_record_idx < c_value_type_STRUCT_BASE) {
      if (struct_record_idx < c_value_type_STRING) {
	 switch (struct_record_idx) {
	 case c_value_type_CHAR:
	    value_location_idx = value_location_pool.insert(c_value_type_CHAR,(unsigned long long)0,c_value_modifier_TMP);
	    break;
	 case c_value_type_SHORT:
	    value_location_idx = value_location_pool.insert(c_value_type_SHORT,(unsigned long long)0,c_value_modifier_TMP);
	    break;
	 case c_value_type_INT:
	    value_location_idx = value_location_pool.insert(c_value_type_INT,(unsigned long long)0,c_value_modifier_TMP);
	    break;
	 case c_value_type_DOUBLE:
	    {
	       double double_num = 0.0;
	       value_location_idx = value_location_pool.insert(c_value_type_DOUBLE,*(unsigned long long *)&double_num,c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_COLOR:
	    value_location_idx = value_location_pool.insert(c_value_type_COLOR,(unsigned long long)0,c_value_modifier_TMP);
	    break;
	 case c_value_type_THREAD:
	 default:
	    err_test2(0,c_R_ERR_CANNOT_CREATE_THIS_OBJECT,_this.get_line_number(a_thread_idx),(unsigned)_this.symbol_names[symbol_records[0].symbols_array[c_symbol_type_structure][symbol_records[struct_record_idx].p_symbol_idx].ui_first].data);
	 }
      }
      else {
	 switch (struct_record_idx) {
	 case c_value_type_STRING:
	    {
	       string_s *str_ptr = (string_s *)cmalloc(sizeof(string_s));
	       str_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_STRING,IM_ACCESS_DATA_PTR(str_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_LOCAL_IMG:
	    {
	       local_img_s *local_img_ptr = (local_img_s *)cmalloc(sizeof(local_img_s));
	       local_img_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_LOCAL_IMG,IM_ACCESS_DATA_PTR(local_img_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_CHAR_ARRAY:
	    {
	       bc_array_s *char_array_ptr = (bc_array_s *)cmalloc(sizeof(bc_array_s));
	       char_array_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_CHAR_ARRAY,IM_ACCESS_DATA_PTR(char_array_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_INT_ARRAY:
	    {
	       bi_array_s *int_array_ptr = (bi_array_s *)cmalloc(sizeof(bi_array_s));
	       int_array_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_INT_ARRAY,IM_ACCESS_DATA_PTR(int_array_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_DOUBLE_ARRAY:
	    {
	       bd_array_s *double_array_ptr = (bd_array_s *)cmalloc(sizeof(bd_array_s));
	       double_array_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_DOUBLE_ARRAY,IM_ACCESS_DATA_PTR(double_array_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_OBJ_ARRAY:
	    {
	       ui_array_s *obj_array_ptr = (ui_array_s *)cmalloc(sizeof(ui_array_s));
	       obj_array_ptr->init();
	       value_location_idx = value_location_pool.insert(c_value_type_OBJ_ARRAY,IM_ACCESS_DATA_PTR(obj_array_ptr),c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_MUTEX:
	    {
	       unsigned sp_mutex_idx = _this.sp_mcs_pool.mutex_insert_new();
	       value_location_idx = value_location_pool.insert(c_value_type_MUTEX,(unsigned long long)sp_mutex_idx,c_value_modifier_TMP);
	    }
	    break;
	 case c_value_type_CONDITION:
	    {
	       unsigned sp_condition_idx = _this.sp_mcs_pool.condition_insert_new();
	       value_location_idx = value_location_pool.insert(c_value_type_CONDITION,(unsigned long long)sp_condition_idx,c_value_modifier_TMP);
	    }
	    break;
	 default:
	    err_test2(0,c_R_ERR_CANNOT_CREATE_THIS_OBJECT,_this.get_line_number(a_thread_idx),(unsigned)_this.symbol_names[symbol_records[0].symbols_array[c_symbol_type_structure][symbol_records[struct_record_idx].p_symbol_idx].ui_first].data);
	 }
      }
   }
   else {

      // - reference to record describing structure -
      symbol_record_s &struct_record = symbol_records[struct_record_idx];

      // - count of structure variables (elements) -
      unsigned s_var_cnt = struct_record.symbols_array[c_symbol_type_struct_variable].used;

      ui_array_s *struct_ptr = value_location_pool.create_structure(s_var_cnt);
      value_location_idx = value_location_pool.insert(struct_record_idx,IM_ACCESS_DATA_PTR(struct_ptr),c_value_modifier_TMP);
   }

   // - insertion of new value to record of temporary variables and to expression stack -
   tmp_variables_array.last().push(value_location_idx);
   exp_stack.push(value_location_idx);
}

/*
 * process of reference to actual structure
 */

void ra_this(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &this_variables = sp_thread.this_variables;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // ***** 

   exp_stack.push(this_variables.last());
}

/*
 * creation and setting of new thread
 */

void ra_thread(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   // - test of enabling multi threading -
   err_test1(_this.multiple_threads,c_R_ERR_NOT_ALLOWED_MULTITHREADING,_this.get_line_number(a_thread_idx));

   sp_thread_pool_s &sp_thread_pool = _this.sp_thread_pool;

   // *****

   unsigned parm_code_idx = code_idx + 2;
   unsigned parm_code_size = code[code_idx + 1];
   unsigned new_code_idx = parm_code_idx + parm_code_size;
   code_idx = code[code_idx];

   // - creation of description of new thread -
   unsigned new_thread_idx = sp_thread_pool.insert(pthread_self(),sp_thread_pool[a_thread_idx].rc_position_array.last().ui_first,new_code_idx);

   // -- REFS  --
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = sp_thread_pool[a_thread_idx];

   ui_array_s &this_variables = sp_thread.this_variables;
   ui_arrays_s &param_variables_array = sp_thread.param_variables_array;
   ui_arrays_s &local_variables_array = sp_thread.local_variables_array;
   ui_array_s &global_variables = _this.global_variables;

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // - REFS OF NEW THREAD -
   sp_thread_s &sp_new_thread = sp_thread_pool[new_thread_idx];
   ui_arrays_s &nt_local_variables_array = sp_new_thread.local_variables_array;

   // - creation of structure which hand over pointer to parser and index of new thread -
   parser_ptr_thread_idx_s *ppti = (parser_ptr_thread_idx_s *)cmalloc(sizeof(parser_ptr_thread_idx_s));
   
   ppti->ui_first = (unsigned)&_this;
   ppti->ui_second = new_thread_idx;

   // - creation of real thread -
   int ret = pthread_create(&sp_thread_pool[ppti->ui_second].pthread,NULL,new_thread_fun,ppti);

   // - test of result of thread function -
   if (ret != 0) {

      // - removing thread from record of threads -
      sp_new_thread.state = c_thread_state_NOT_EXIST;
      sp_thread_pool.remove(new_thread_idx);

      // - release of structure created for handling of parameters -
      cfree(ppti);

      // - return of err value -
      unsigned result_location_idx = value_location_pool.insert(c_value_type_INT,(unsigned long long)c_tc_THREAD_ERR_RESOURCES,c_value_modifier_TMP);
      tmp_variables_array.last().push(result_location_idx);
      exp_stack.push(result_location_idx);
   }
   else {

      // - creation of space for local variable (as in ra_cmd_block_begin) -
      nt_local_variables_array.push_blank();
      nt_local_variables_array.last().used = 0;

      ui_array_s &nt_local_variables_al = nt_local_variables_array.last();

      // - copying of variables handed as thread parameter -

      if (parm_code_size != 0) {
	 unsigned parm_code_idx_end = parm_code_idx + parm_code_size;
	 
	 do {
	    switch(code[parm_code_idx++]) {
	    case i_this_var:
	       {
		  value_location_s &this_location = value_location_pool[this_variables.last()];
		  unsigned old_variable = (*IM_ACCESS_STRUCT_PTR(this_location.ulli_second))[code[parm_code_idx++]];
		  unsigned new_variable = value_location_pool.copy_create_value(old_variable);
		  nt_local_variables_al.push(new_variable);
	       }
	       break;
	    case i_param_var:
	       {
		  unsigned old_variable = param_variables_array.last()[code[parm_code_idx++]];
		  unsigned new_variable = value_location_pool.copy_create_value(old_variable);
		  nt_local_variables_al.push(new_variable);
	       }
	       break;
	    case i_global_var:
	       {
		  unsigned new_variable = value_location_pool.copy_create_value(global_variables[code[parm_code_idx++]]);
		  nt_local_variables_al.push(new_variable);
	       }
	       break;
	    case i_local_var:
	       {
		  ui_array_s &locals = local_variables_array[local_variables_array.used - 1 - code[parm_code_idx++]];
		  unsigned new_variable = value_location_pool.copy_create_value(locals[code[parm_code_idx++]]);
		  nt_local_variables_al.push(new_variable);
	       }
	       break;
	    default:
	       assert(0);
	    }
	 } while(parm_code_idx < parm_code_idx_end);
      }

      // - return of index of new created thread -
      unsigned new_thread_idx_location = value_location_pool.insert(c_value_type_THREAD,(unsigned long long)new_thread_idx,c_value_modifier_TMP);
      tmp_variables_array.last().push(new_thread_idx_location);
      exp_stack.push(new_thread_idx_location);
   }
}

/*
 * process of begin of definition of new char array
 */

void ra_new_char_array(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   bc_array_s *bc_array_ptr = (bc_array_s *)cmalloc(sizeof(bc_array_s));
   bc_array_ptr->init();

   unsigned array_location_idx = value_location_pool.insert(c_value_type_CHAR_ARRAY,IM_ACCESS_DATA_PTR(bc_array_ptr),c_value_modifier_TMP);
   tmp_variables_array.last().push(array_location_idx);
   exp_stack.push(array_location_idx);
}

/*
 * process of begin of definition of new integer array
 */

void ra_new_int_array(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   bi_array_s *bi_array_ptr = (bi_array_s *)cmalloc(sizeof(bi_array_s));
   bi_array_ptr->init();

   unsigned array_location_idx = value_location_pool.insert(c_value_type_INT_ARRAY,IM_ACCESS_DATA_PTR(bi_array_ptr),c_value_modifier_TMP);
   tmp_variables_array.last().push(array_location_idx);
   exp_stack.push(array_location_idx);
}

/*
 * process of begin of definition of new float point array
 */

void ra_new_double_array(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   bd_array_s *bd_array_ptr = (bd_array_s *)cmalloc(sizeof(bd_array_s));
   bd_array_ptr->init();

   unsigned array_location_idx = value_location_pool.insert(c_value_type_DOUBLE_ARRAY,IM_ACCESS_DATA_PTR(bd_array_ptr),c_value_modifier_TMP);
   tmp_variables_array.last().push(array_location_idx);
   exp_stack.push(array_location_idx);
}

/*
 * process of definition of new object array
 */

void ra_new_array(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_arrays_s &tmp_variables_array = sp_thread.tmp_variables_array;
   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
   
   ui_array_s *ui_array_ptr = (ui_array_s *)cmalloc(sizeof(ui_array_s));
   ui_array_ptr->init();

   unsigned array_location_idx = value_location_pool.insert(c_value_type_OBJ_ARRAY,IM_ACCESS_DATA_PTR(ui_array_ptr),c_value_modifier_TMP);
   tmp_variables_array.last().push(array_location_idx);
   exp_stack.push(array_location_idx);
}

/*
 * process of insertion new element in array
 */

void ra_array_element(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   value_location_pool_s &value_location_pool = _this.value_location_pool;
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****

   unsigned element_location_idx = exp_stack.pop();
   unsigned array_location_idx = exp_stack.last();
   value_location_s &element_location = value_location_pool[element_location_idx];
   value_location_s &array_location = value_location_pool[array_location_idx];

   switch (array_location.ui_first) {

   // - array of chars -
   case c_value_type_CHAR_ARRAY:
      switch (element_location.ui_first) {
      case c_value_type_CHAR:
	 {
	    char char_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_CHAR_ARRAY_PTR(array_location.ulli_second)->push(char_value);
	 }
	 break;
      case c_value_type_SHORT:
	 {
	    short short_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_CHAR_ARRAY_PTR(array_location.ulli_second)->push((char)short_value);
	 }
	 break;
      case c_value_type_INT:
	 {
	    int int_value = value_location_pool.get_int_value(element_location);
	    IM_ACCESS_CHAR_ARRAY_PTR(array_location.ulli_second)->push((char)int_value);
	 }
	 break;
      case c_value_type_DOUBLE:
	 {
	    double double_value = value_location_pool.get_double_value(element_location);
	    IM_ACCESS_CHAR_ARRAY_PTR(array_location.ulli_second)->push((char)double_value);
	 }
	 break;
      default:
	 err_test3(0,c_R_ERR_NOT_COMPATIBLE_ARRAY_ELEMENT,_this.get_line_number(a_thread_idx),(unsigned)"char_array_s",(unsigned)_this.symbol_names[_this.symbol_records[0].symbols_array[c_symbol_type_structure][_this.symbol_records[element_location.ui_first].p_symbol_idx].ui_first].data);
      }
      break;

   // - array of integers -
   case c_value_type_INT_ARRAY:
      switch (element_location.ui_first) {
      case c_value_type_CHAR:
	 {
	    char char_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_INT_ARRAY_PTR(array_location.ulli_second)->push((int)char_value);
	 }
	 break;
      case c_value_type_SHORT:
	 {
	    short short_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_CHAR_ARRAY_PTR(array_location.ulli_second)->push((int)short_value);
	 }
	 break;
      case c_value_type_INT:
	 {
	    int int_value = value_location_pool.get_int_value(element_location);
	    IM_ACCESS_INT_ARRAY_PTR(array_location.ulli_second)->push(int_value);
	 }
	 break;
      case c_value_type_DOUBLE:
	 {
	    double double_value = value_location_pool.get_double_value(element_location);
	    IM_ACCESS_INT_ARRAY_PTR(array_location.ulli_second)->push((int)double_value);
	 }
	 break;
      default:
	 err_test3(0,c_R_ERR_NOT_COMPATIBLE_ARRAY_ELEMENT,_this.get_line_number(a_thread_idx),(unsigned)"int_array_s",(unsigned)_this.symbol_names[_this.symbol_records[0].symbols_array[c_symbol_type_structure][_this.symbol_records[element_location.ui_first].p_symbol_idx].ui_first].data);
      }
      break;

   // - array of float point numbers -
   case c_value_type_DOUBLE_ARRAY:
      switch (element_location.ui_first) {
      case c_value_type_CHAR:
	 {
	    char char_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_DOUBLE_ARRAY_PTR(array_location.ulli_second)->push((double)char_value);
	 }
	 break;
      case c_value_type_SHORT:
	 {
	    short short_value = value_location_pool.get_char_value(element_location);
	    IM_ACCESS_DOUBLE_ARRAY_PTR(array_location.ulli_second)->push((double)short_value);
	 }
	 break;
      case c_value_type_INT:
	 {
	    int int_value = value_location_pool.get_int_value(element_location);
	    IM_ACCESS_DOUBLE_ARRAY_PTR(array_location.ulli_second)->push((double)int_value);
	 }
	 break;
      case c_value_type_DOUBLE:
	 {
	    double double_value = value_location_pool.get_double_value(element_location);
	    IM_ACCESS_DOUBLE_ARRAY_PTR(array_location.ulli_second)->push(double_value);
	 }
	 break;
      default:
	 err_test3(0,c_R_ERR_NOT_COMPATIBLE_ARRAY_ELEMENT,_this.get_line_number(a_thread_idx),(unsigned)"double_array_s",(unsigned)_this.symbol_names[_this.symbol_records[0].symbols_array[c_symbol_type_structure][_this.symbol_records[element_location.ui_first].p_symbol_idx].ui_first].data);
      }
      break;

   // - array of objects -
   case c_value_type_OBJ_ARRAY:
      {
	 ui_array_s *ui_array_ptr = IM_ACCESS_OBJ_ARRAY_PTR(array_location.ulli_second);

	 unsigned value_location_idx = value_location_pool.copy_create_value(element_location_idx);
	 ui_array_ptr->push(value_location_idx);
      }
      break;
   default:
      assert(0);
   }
}

/*
 * insert of constant position to expression stack
 */

void ra_const(ui_array_s &code,unsigned &code_idx,unsigned a_thread_idx,script_parser_s &_this)
{
   sp_thread_s &sp_thread = _this.sp_thread_pool[a_thread_idx];

   ui_array_s &exp_stack = sp_thread.exp_stack;

   // *****
   
   exp_stack.push(code[code_idx++]);
}


