
#include "p.main.h"

@begin
   header "main.h";
@end

/*
 * function which prints DEBUG report about all parser symbols
 */

void DEBUG_print_symbol_records(string_array_s &symbol_names,symbol_records_s &symbol_records)
{
   if (symbol_records.used == 0) return;

   unsigned r_idx = 0;
   do {
      symbol_record_s &record = symbol_records[r_idx];
      printf("record %u: record: %u, type: %u, symbol: %u\n",r_idx,record.p_record_idx,record.p_symbol_type,record.p_symbol_idx);

      unsigned sa_idx = 0;
      do {
	 symbols_s &symbols = record.symbols_array[sa_idx];
	 if (symbols.used != 0) {
	    switch (sa_idx) {
	    case c_symbol_type_structure:
	       printf("\tstructures:\n");
	       break;
	    case c_symbol_type_function:
	       printf("\tfunctions:\n");
	       break;
	    case c_symbol_type_struct_variable:
	       printf("\tstruct_variables:\n");
	       break;
	    case c_symbol_type_fun_param:
	       printf("\tfun_params:\n");
	       break;
	    case c_symbol_type_local_variable:
	       printf("\tlocal_variables:\n");
	       break;
	    default:
	       assert(0);
	    }

	    unsigned s_idx = 0;
	    do {
	       symbol_s &symbol = symbols[s_idx];

	       printf("\t\tname: %s, data: %u, record_idx: %u\n",symbol_names[symbol.ui_first].data,symbol.ui_second,symbol.ui_third);
	    } while(++s_idx < symbols.used);
	 }
      } while(++sa_idx < c_symbol_type_cnt);
   } while(++r_idx < symbol_records.used);
}

/*
 * function which prints content of codes generated by parser
 */

void DEBUG_print_codes(run_codes_s &run_codes)
{
   if (run_codes.used == 0) return;
      
   unsigned cd_idx = 0;
   do {
      ui_array_s &code = run_codes[cd_idx].code;

      printf("CODE: %u size: %u\n",cd_idx,code.used);

      if (code.used != 0) {
	 unsigned *c_ptr = code.data;
	 unsigned *c_ptr_end = c_ptr + code.used;

	 do {
	    switch (*(c_ptr++)) {
	    
	    case i_flow_end:
	       printf("\ti_flow_end\n");
	       break;

	    case i_return:
	       printf("\ti_return\n");
	       break;

	    case i_cmd_block_begin:
	       printf("\ti_cmd_block_begin\n");
	       break;
	    case i_cmd_block_end:
	       printf("\ti_cmd_block_end\n");
	       break;

	    case i_false_jmp:
	       printf("\ti_false_jmp %u\n",*(c_ptr++));
	       break;
	    case i_true_jmp:
	       printf("\ti_true_jmp %u\n",*(c_ptr++));
	       break;
	    case i_jmp:
	       printf("\ti_jmp %u\n",*(c_ptr++));
	       break;
	    case i_local_cross_jmp:
	       printf("\ti_local_cross_jmp\n");
	       c_ptr += 2;
	       break;

	    case i_cmd_return:
	       printf("\ti_cmd_return: %u\n",*(c_ptr++));
	       break;

	    case i_exp_end:
	       printf("\ti_exp_end\n");
	       break;

	    case i_this_var:
	       printf("\ti_this_var: %u\n",*(c_ptr++));
	       break;
	    case i_param_var:
	       printf("\ti_param_var: %u\n",*(c_ptr++));
	       break;
	    case i_local_var:
	       {
		  unsigned tmp_num = *(c_ptr++);
		  printf("\ti_local_var: %u:%u\n",tmp_num,*(c_ptr++));
	       }
	       break;
	    case i_global_var:
	       printf("\ti_global_var: %u\n",*(c_ptr++));
	       break;

	    case i_this_call:
	       printf("\ti_this_call: %u\n",*(c_ptr++));
	       break;
	    case i_global_call:
	       printf("\ti_global_call: %u\n",*(c_ptr++));
	       break;

	    case i_s_element:
	       printf("\ti_s_element: %u\n",*(c_ptr++));
	       c_ptr += 2;
	       break;
	    case i_s_method_call:
	       {
		  unsigned parm_cnt = *(c_ptr++);
		  printf("\ti_s_method_call: %u:%u\n",parm_cnt,*(c_ptr++));
		  c_ptr += 2;
	       }
	       break;

	    case i_new_object:
	       printf("\ti_new_object: %u\n",*(c_ptr++));
	       break;

	    case i_this:
	       printf("\ti_this\n");
	       break;

	    case i_thread:
	       printf("\ti_thread\n");
	       c_ptr++;
	       c_ptr += *(c_ptr) + 1;
	       break;

	    case i_new_char_array:
	       printf("\ti_new_char_array\n");
	       break;
	    case i_new_int_array:
	       printf("\ti_new_int_array\n");
	       break;
	    case i_new_double_array:
	       printf("\ti_new_double_array\n");
	       break;
	    case i_new_array:
	       printf("\ti_new_array\n");
	       break;
	    case i_array_element:
	       printf("\ti_array_element\n");
	       break;

	    case i_const:
	       printf("\ti_const: %u\n",*(c_ptr++));
	       break;
	    default:
	       printf("UNKNOWN CODE: %u\n",*(c_ptr - 1));
	       assert(0);
	    }
	 } while(c_ptr < c_ptr_end);
      }
   } while(++cd_idx < run_codes.used);
}

/*
 * main function
 */

int main(int argc,char *argv[])
{
   mc_init();

   {
      // - test of parameter count -
      err_test(argc > 1,c_ERR_NOT_ENOUGH_CL_PARAMETERS);

      string_s source;
      source.init();
      bool s_res = source.load_text_file(argv[1]);

      // - test of script file open result -
      err_test1(s_res,c_ERR_CANNOT_OPEN_SOURCE_FILE,(unsigned)argv[1]);

      script_parser_s parser;
      parser.init();
      parser.initialize_parser(argc,argv);
      parser.parse_script(source);

      //DEBUG_print_symbol_records(parser.symbol_names,parser.symbol_records);
      //DEBUG_print_codes(parser.run_codes);

      // - creation of main thread -
      unsigned thread_idx = parser.sp_thread_pool.insert(pthread_self(),0,0);
      parser.run_main_thread(thread_idx);

      parser.value_location_pool.final_free_all_values();
      parser.clear();
      source.clear();
   }

   mc_clear(0);
}

