/*
//------------------------------------------------------------
// C# version: creates C# project from a compiled AL4 program 
//------------------------------------------------------------
// (C) by Vladimir Kladov, 2016-2021                          
//------------------------------------------------------------

CLASS {Generator|_of_CSharp_code},
	RECURSIVE, UNTESTED, STOPPING :

IMPORT: {Compiler}, {Type}, {Text_file}, {Variable}, {Function},
        {Statement}, {Assignment}, {For}, {Case}, {Limit}, {Local},
        {Expression}, {String_functions}, {System_functions}, {Console}, 
        {File_path}, {Parser}, {Text_parser}, {Mathematics},
        {Localize_str}, {Bytes_array}, {Date_time}, {Statistics} ;
        
IMPORT: {Testing} ;
        
IMPORT: {Collect_native_functions}, {Import_native_functions} ;

CONSTRUCT:
	FINAL_CODE = TRUE .

FUN Tests_available ==> BOOL : RESULT = TRUE .

FUN Additional_classes|_maybe_add_Console_app(
{Compiler} C|ompiler_obj_Dummy) : .


FUN Allow_optimizations(
{Compiler} C|ompiler_with_its_options_dummy,
STR Optimizations|_found) ==> STR
    :
    RESULT = Optimizations .

CONST BOOL: ALLOW_EXIT_IN_NATIVE|_FUNCTIONS_BEFORE_NATIVE_CODE = TRUE .

METHOD Need_compile({Type} C|lass_to_check) ==> BOOL :
	CASE "$REBUILD" IN Comp.Defined_name[] ? RESULT = TRUE ==> ;
	BOOL no_tests|_mode = !Need_any_tests(Comp)
	CASE !no_tests ? Comp.At_least_1_class_need_testing = TRUE ;
    //DEBUG: "Need_compile(" C.Names[0] ")? no_tests=" no_tests.S #NL ;
	CASE !Comp.Local_optimizations && Comp.Optimizations.Trim != "" ? 
	     RESULT = TRUE ==> ;
	STR class_path = Output_path_class(C)
    CASE !class_path.Exists ? RESULT = TRUE ==> ;
    CASE (!no_tests || Comp.TEST_value) && !Output_test_path_class(C).Exists ? 
         RESULT = TRUE ==> ;
    STR d_in|put_file = Get_file_modified_time_formatted(C.Path) 
    CASE !no_tests && Output_test_path_class(C).Exists ? 
         STR d_out|_file = Get_file_modified_time_formatted(
         	Output_test_path_class(C))
         	
         CASE d_out < d_in ? RESULT = TRUE ==> ;
    ;
    d_out = Get_file_modified_time_formatted(class_path)
    CASE d_out > d_in ? ==> ;
    RESULT = TRUE .
    
METHOD Output_path_class|_compiled({Type} C|lass_to_path) ==> STR :
    STR path|_output = C.Final_name ".cs" 
    RESULT = Comp.Destination.Trailing_slash "" path.Extract_file_name .
        
METHOD Output_test_path_class|_compiled({Type} C|lass_to_path) ==> STR :
	CASE "TEST$" IN Comp.Destination ? RESULT = Output_path_class(C) ==> ;
    STR path|_output = C.Final_name ".cs"
     
    RESULT = Comp.Destination.Trailing_slash "TEST$".Trailing_slash 
    	"" path.Extract_file_name .
        
*/

using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using AL4Compiler._CSharp;
using AL4_project;

using AL4Compiler.Statements;
using AL4;

namespace AL4Compiler.Generate
{

    public class AL4_Exception : Exception 
    {
    }

    public class Generator
    {

        /*
        {Collect_native_functions}.{rtti_type_info} Rtti_all_types[]
        
        FUN TARGET_LANG|UAGE({Compiler} C|ompiler_dummy) ==> STR :
			RESULT = "C#" .
        
		CONST BOOL: SUPPORTS_NATIONAL_NAMES
		|_FOR_VARS_FUNCTIONS_TYPES = FALSE .
		
        {Compiler} Comp|iler
        STR o|out_source[]
        STR spaces|_prefix
        -------------------- 'log methods'
        BOOL LOGGING_METHODS
        STR LOGGING_RESET
        STR do_not_log_classes[]
        STR do_not_log_methods[]
        
		FUNCTION Prepare_project_generator(
			{Compiler} C|ompiler_obj) ==> {Generator}, NEW
			:
			g|enerator_temp = {Generator}(Comp = C)
			RESULT = g .	
			
		
		FUNCTION Create_project(
			{Generator} G|enerator, {Compiler} C|ompiler_obj) ==> BOOL
			:
			{Generator} g|enerator_passed = G
		    FOR dfn IN C.Defined_name[] :
		        CASE ?
		        [dfn !IN [
		        	 "$ICON", "$VISUAL", "$ALLTESTS", "$NOTESTS", "$COMPILER",
		        	 "$CCC",
		        	 "$PROFILER", "$LOG_RESET", "$LOG_METHODS", "$x64",
		        	 "$REPORT_LEAKS", "$Title", "$Description", "$Configuration",
		        	 "$Company", "$ProductName", "$Copyright", "$Trademark",
		        	 "$Version", "$FileVersion", "$INTERPRETER", 
		        	 "$INC", "$INCREMENTAL", "$NOLONGOP", "$NO_STMT_NUM",
		        	 "$NO_SIDE_EFFECTS", "$Visual", "$FRAMEWORK", "$CHCH",
		        	 "$MSVSTUDIO", "$PAUSE", "$DO_NOT_LOG", "$DEBUG", "$REBUILD" 
		        	 ]] ?
		             C.Error("Unknown option"._EUnkOp ": " dfn)
		        [dfn == "$DEBUG"] ?
		             C.Warning("Option ignored"._WOptionIgnored ": " dfn)
		        ;
		    ;
			------------------------------------------- 'logging'
			CASE "$LOG_METHODS" IN C.Defined_name[] ?
			     g.LOGGING_METHODS = TRUE
			     
			     Split(g.do_not_log_classes[], C.Defined_value[C.Defined_name[
			     	].Find("$DO_NOT_LOG")], ",")
			     	
			     FOR i_s IN [g.do_not_log_classes[].Count-1 DOWNTO 0] :
			         STR s|_at_line_i = g.do_not_log_classes[i_s]
			         CASE "." IN s ?
			              g.do_not_log_methods[] << s
			              g.do_not_log_classes[].Delete(i_s) ;
			     ;
			     //DEBUG: << "$LOG_METHODS ON" >> STR debug_log_methods ;
			     CASE "$LOG_RESET" IN C.Defined_name[] ?
			          g.LOGGING_RESET = C.Defined_value[C.Defined_name[].Find(
			          "$LOG_RESET")]
			     ;
			;
            ------------------------------------------- 'generate project'
            g.Delete_cs_files(C.Destination.Trailing_slash)
            RESULT = g.do_generate_project
            CASE !RESULT || "test" IN Start_dir.Lower ? ==> ;
            ------------------------------------------- 'count tests'
            FOR c IN C.All_classes[] :
                INT total_tests += c.Test[].Count ;
            CASE total_tests == 0 && C.TEST_value ?
                 C.Warning("There are no tests in entire project"._Wthere )
                 RESULT = TRUE ==> ;
			------------------------------------------ 'prepare response file'
            STR text|_rsp_file[] << "/unsafe /target:"
            CASE !C.TEST_value && C.Noconsole ? text[*] = text[*] "win" ;
            CASE "$x64" IN C.Defined_name[] ? 
                 STR platform = "/platform:x64 "
            ELSE platform = "/platform:x86 " ;
            text[*] = text[*] "exe " platform " -warn:0"
            CASE "$ICON" IN C.Defined_name[] ?
                 STR ico_def|ined= C.Defined_value[
                 	 C.Defined_name[].Find("$ICON")]
                 	 
                 STR test_ico|n_path = Absolute_path(ico_def)
                 	
                 CASE !test_ico.Exists && ":" !IN ico_def ?
                      STR ico|n_path = Absolute_path(
                      	C.Source_paths[0].Trailing_slash ico_def)
                 ELSE ico = test_ico ;
                 CASE !ico.Exists ?
                      C.Error("Icon file was not found"._EIcon ": " ico) ;
                 text[] << "/win32icon:" #QU ico #QU ;
            text[] << "/o /out:" C.Project ".exe *.cs"
            
            ----------------------- 'remove exe.config'
            STR remove_exe_config = C.Project ".exe.config"
            remove_exe_config.Delete_file
            
            ----------------------- 'save rsp'
            STR dest|ination_test_project = Absolute_path(
            	C.Destination).Trailing_slash
            	
            rsp|_file_temp = {Text_file}(Path = dest C.Project ".rsp")
            NONE = rsp.Save_strings(text[])
            ------------------------------------------- 'compile tests project'
            STR exe|_path = dest C.Project ".exe"
			FOR attempt IN [1 TO 2] :
			    CASE exe.Exists ?
			    	 Delete_file(exe) ;
			    CASE ?
			    [exe.Exists && attempt == 1] ?
			         Console_color('CYAN')
			         
			         << "Executable can not be deleted. Close application "
			         	"which opened it and press Enter"._MCannotdelete >>
			         	
			         Console_color('SILVER')
			    [exe.Exists && attempt == 2] ?
			         C.Error("Can not delete"._Ecannot1 " " exe)
			         RESULT = FALSE ==>
			    ELSE BREAK attempt ;
			;            
            //Delete_file(exe)
            //CASE exe.Exists ?
            //     C.Error("Can not delete"._Ecannot " " exe)
            //     RESULT = FALSE ==> ;
            Set_working_dir(dest)
            CASE !"csc.exe".Exists ?
                 STR csc|_path = find_csc_compiler
            ELSE csc = "csc.exe" ;
            ------------------------------------------- 'execute csc'
            text[].Clear
            text[] << csc " @" C.Project ".rsp" << "pause"
            
            cmd|_file_temp = {Text_file}(Path = dest C.Project.Extract_path
            	"_compile.cmd")
            	
            NONE = cmd.Save(text[])
            text[].Clear
            STR mes|sages = Execute_program(csc, "@" C.Project ".rsp", 1)
            Split(text[], mes, #NL)
            ------------------------------------------- 'save csc messages'
            CASE FALSE ?
                 m|essages_temp = {Text_file}(Path = dest C.Project
                     ".compiler-messages.txt")
                 NONE = m.Save_strings(text[])
                 STR tests|_temp = ""
                 CASE C.TEST_value ? tests = "tests " ;
                 CASE !exe.Exists ?
                      C.Error("Can not compile"._Ecannot2 " " tests "(file " exe
                      " was not created)")
                      Start_program(m.Path, "")
                      RESULT = FALSE ==> ;
            ELSE ------------------------- 'messages text[] to console'
                 out_messages_to_console(text[])
                 FOR ss IN text[] :
                     CASE errors_in(ss.Lower) ? RESULT = FALSE ==> ;
                 ;
            ;
            C.Executable = exe
    		C.Time_finished = Now
    		Statistics_show(C)
            CASE !C.TEST_value && !C.Run ? ==> ;
            -------------------------------------------- 'run tests / program'
            CASE C.Verbose && C.TEST_value ?
                 << "Running tests"._Mrunn #NL ;
            CASE !C.TEST_value && C.Run ?
                 //BOOL run_program = TRUE
                 CASE C.Verbose ?
                 	  << "Running compiled application"._Mrunn2 #NL ;
            ;
            INT wait|_redirect_output = 0
            CASE C.TEST_value ? wait = 0 ;
            CASE ("$INC" IN C.Defined_name[] || 
            	  "$INCREMENTAL" IN C.Defined_name[]) && FALSE // run_program
            	 ?
                 Start_program(exe, C.Param) ==>
            ELSE NONE = Execute_program(exe, C.Param, wait) ; 
            ----------------------------------- 'if report leaks was requested'
            CASE C.Defined_name[].Find("$REPORT_LEAKS") >= 0 ?
                 STR path_rep|ort = C.Destination.Trailing_slash 
                     "Report_leaks.txt"
                 CASE ! path_rep.Exists ?
                      Console_color({Console}.{colors}.'RED')
                      << "Could not report leaks" #NL
                      Console_color({colors}.'SILVER') ==> ;
                 text[].Clear
                 m.Path = path_rep
                 NONE = m.Load_strings(text[])
                 CASE text[].Count == 0 ?
                      Console_color({colors}.'GREEN')
                      << "There were not leaks detected" #NL
                      Console_color({colors}.'SILVER')
                 ELSE Console_color({colors}.'RED')
                 
                      << "There were leaks in " (text[].Count-1).Str 
                         " classes" #NL
                         
                      Console_color({colors}.'SILVER') ;
            ; .
            
		METHOD Delete_cs_files(STR Path|_where):
			CASE Comp.Optimizations.Trim=="" ? ==> ;
            //FOR c IN Comp.All_classes[] :
            //    CASE c.Loaded_from_ccc ? ==> ;
            //;
			----------------------- 'delete some cs files'
			STR cat|alog_all_files_in_directory[]
			Catalog(Path, cat[])
			FOR i IN [cat[].Count-1 DOWNTO 0] :
			    CASE cat[i].Ext.Lower != ".cs" ? 
			         cat[].Delete(i) 
			         CONTINUE i ;
			;
            //FOR i IN [cat[].Count-1 DOWNTO 0] :
            //    STR s|_at_i_in_cat = cat[i]
            //    //FOR c IN Comp.All_classes[] :
            //    //    CASE c.Final_name ".cs" != s ? CONTINUE c ;
            //    //    //CASE c.Loaded_from_ccc ?
            //    //    //     cat[].Delete(i)
            //    //    //     BREAK c ;
            //    //;
            //;
			STR bat|_file[]
			FOR i IN [0 TO cat[].Count-1] :
				bat[] << "del /q " #QU Path cat[i] #QU ;
			rsp|_file_temp = {Text_file}(Path = Path "del_cs.bat")
            NONE = rsp.Save_strings(bat[])
			NONE = Execute_program(Path "del_cs.bat", "", 0) .
            

        FUN out_messages_to_console(STR T|ext_messages[]) :
            Console_color({colors}.'CYAN')
            FOR s IN T[] :
                CASE "error" IN s.Lower ?
                     INT pos|ition_error = s.Lower.Find("error")
                     << s.[0 TO pos-1]
                     Console_color({colors}.'RED')
                     << s.[pos TO pos+4]
                     Console_color({colors}.'CYAN')
                     << s.[pos+5 TO *] #NL
                ELSE << s #NL ;
            ;
            Console_color({colors}.'SILVER') .
            
        FUNCTION errors_in(
        	STR S|tring_from_compiler_output ) ==> BOOL
        	:
            FOR i IN [0 TO S.Len-6] :
                CASE S.[i] != "e" ? CONTINUE i ;
                CASE S.[i TO i+"error".Len-1] == "error" ?
                     CASE !is_letter_digit_underline(S.[i-1]) && (
                          !is_letter_digit_underline(S.[i+"error".Len]))
                          ?
                          RESULT = TRUE ==> ;
                ;
            ; .
            
        FUNCTION is_letter_digit_underline(
        	STR S|tring_char_test ) ==> BOOL
        	:
            RESULT = S IN "abcdefghijklmnopqrstuvwxyz0123456789_" .
        */

        public const string TARGET_LANG = "C#";

        Compiler Comp = null;
        List<string> o = new List<string>();
        string spaces_prefix = "";

        public static bool Create_project(Compiler C)
        {
            //-------------------------------- 'generate tests project'
            Generator G = new Generator();
            G.Comp = C;
            bool Result = G.do_generate();
            if (!Result || System_functions.Start_dir().ToLower().Contains("test"))
            	return Result;
            //-------------------------------- 'prepare response file'
            List<string> text = new List<string>();
            text.Add("/target:exe /out:" + C.Project_name + ".exe");
            text[text.Count - 1] += " *.cs";
            string dest = StringFunctions.Trailing_slash(C.Destination);
            Text_file rsp = new Text_file(dest + C.Project_name + ".rsp");
            rsp.Save_strings(text);
            //-------------------------------- 'compile tests project'
            string exe = dest + C.Project_name + ".exe";
            try
            {
                File.Delete(exe);
            }
            catch (Exception Ex)
            {
            	if (Ex is AL4_Exception) throw;
                C.Error("Exception while deleting " + exe + ": " +
                    Ex.Message);
            }
            if (File.Exists(exe))
            {
                C.Error("Can not delete " + exe);
                return false;
            }
            Directory.SetCurrentDirectory(dest);
            string csc = "csc.exe";
            if (!File.Exists(csc)) 
                csc = find_csc_compiler();
            text.Clear();
            text.Add(System_functions.Execute_program(csc, "@" + C.Project_name + ".rsp", true));
            //-------------------------------- 'save csc messages
            Text_file messages = new Text_file(dest + C.Project_name + ".compiler-messages.txt");
            messages.Save_strings(text);
            if (!File_path.Exists(exe))
            {
                string tests = "";
                if (C.Test()) tests = "tests ";
                C.Error("Can not compile " + tests + "(file " + exe + " was not created)");
                if (!File_path.Exists(exe))
                { }
                System_functions.Start_program(messages.Path, "");
                return false;
            }
            if (!C.Test()) return true;
            //-------------------------------- 'run tests'
            if (C.Verbose)
                Console.WriteLine("Running tests");
            System_functions.Execute_program(exe, "", false);
            return true;
        }

        /*
        
        FUN find_csc_compiler ==> STR :
	        STR csc_path = Get_environment_var("CSC_PATH")
	        CASE csc_path != "" ? 
	             CASE !Ending(csc_path.Lower,"csc.exe") ? 
	                  csc_path = csc_path.Trailing_slash "csc.exe" ;
	             CASE !csc_path.Exists ? 
	                  << "csc_path=" csc_path #NL
	                  STOP "Environment variable CSC_PATH is wrong" ;
	             RESULT = #QU csc_path #QU ==>
	        ;
            STR win|ows_directory = Get_windows_dir.Trailing_slash
            STR net|framework_dir = win "Microsoft.NET\Framework\"
            STR cat|alogue[]
            Catalog(net, cat[])
            FOR dir IN cat[] :
                CASE dir.[*] == "\" && (net dir "csc.exe").Exists && (
                     net dir "csc.exe" > RESULT)
                     ?
                     RESULT = net dir "csc.exe" ;
            ;
            CASE RESULT == "" ? STOP "Can not find csc.exe" ; .
        */
        private static string find_csc_compiler()
        {
            string win = StringFunctions.Trailing_slash(
            	System_functions.Get_windows_dir());
            string net = win + "Microsoft.NET\\Framework\\";
            List<string> cat = new List<string>();
            File_path.Catalog(net, cat);
            string Result = "";
            foreach (string dir in cat)
            {
                if (dir != "" && (dir[dir.Length-1] + "") == "\\" && 
                    File.Exists(net + dir + "csc.exe") && 
                    (net + dir + "csc.exe").CompareTo(Result) > 0)
                    Result = net + dir + "csc.exe";
            }
            return Result;
        }

        /*
        
		METHOD skip_class({Type} C|lass_may_be_to_skip) ==> BOOL :
			CASE Comp.TEST_value || Comp.Optimizations.Trim == "" ? ==> ;
			CASE C.Anyway ? ==> ;
			RESULT = FALSE
            //CASE C !IN Comp.Classes_used[] ?
            //     RESULT = TRUE ;
            .
            
		BOOL renumber_classes
		
		METHOD renumber|_type(
		INT Curr|ent_value, INT Next|_value) ==> INT
			:
			CASE renumber_classes ? RESULT = Next ==> ;
			RESULT = Curr .

		STR use_profiler
        
        METHOD do_generate_project ==> BOOL :
            FINAL_CODE = Comp.Final
            CASE TRUE || "$INTERPRETER" IN Comp.Defined_name[] ?
	             PUSH renumber_classes = TRUE :
	                  output_RTTI_info_tables ;
            ;
			----------------------------------------- 'setup profiler'
		    CASE "$PROFILER" IN Comp.Defined_name[] ? 
		         CASE Comp.Final ?
		              Comp.Warning("Option /FINAL is set, so /$PROFILER "
		              "is ignored"._Wfinal_Profiler_ignored)
		              
		         ELSE INT i_prof|iler INDEXING STR 
		         	  i_prof = Comp.Defined_name[].Find("$PROFILER")
		         	  use_profiler = Comp.Defined_value[i_prof].Upper
		         	  CASE use_profiler == "" ? use_profiler = "FUNCTIONS" ;
		         	  CASE use_profiler.[0] !IN "FCBLA" ?
		         	       Comp.Warning("Unknown $PROFILER option"
		         	       ""._WunknownProfiler 
		         	       " " use_profiler ", " (
		         	       "options allowed: FUNCTONS, COMMENTS"
		         	       ", BRANCHES, LOOPS, ALL"._MallowedProfiler))
		         	  ;
		         ;
		    ;            
            generate_project(Comp.Project)
            
            FOR c IN Comp.All_classes[] :
                //CASE c.Is_translation ? CONTINUE c ;
                CASE skip_class(c) ? CONTINUE c ;
                CASE !c.Compiled ? CONTINUE c ;     
                STR path|_output = c.Final_name ".cs"
                
                STR class_path = Comp.Destination.Trailing_slash
                    "" path.Extract_file_name
                    
                //CASE c.Index > 0 && c.Loaded_from_ccc && class_path.Exists
                //     && time_file(c.Get_ccc.Path_ccc) > time_file(class_path)
                //     ?
                //     CONTINUE c ;
                    
                o[].Clear
                CASE !generate_class(c) ? ==> ;
                
                CASE "/$CHCH" IN Comp.Defined_name[] || 
                	 "/$CHECK_CHANGED" IN Comp.Defined_name[]
                	 ?
                     BOOL changed|_really = check_changed(class_path, o[]) 
                ELSE changed = TRUE ;
                CASE changed ?
	                 tf|ile_text_temp = {Text_file}(
	                     Path = class_path)
	                 CASE Comp.Verbose ?
	                      << "Saving"._Msav ": " tf.Path
	                      " (" o[].Count.Str ")" #NL
	                 ;
	                 NONE = tf.Save(o[])
                     //CASE c.Loaded_from_ccc ?
                     //     Renew_file_time(tf.Path, c.Get_ccc.Path_ccc)
                     //;
                ;
                ------------------------------- 'save localizations in file'
                CASE c.Localize_n[].Count > 0 ? 
                     o[].Clear
                     FOR n IN c.Localize_n[] :
                         o[] << n "=" c.Localize_s[n.Index].Var_arg.Str_c ;
                     tf.Path = class_path ".localize"
                     NONE = tf.Save(o[])
                ;
            ;
            FOR sf IN Comp.Copy_files[] :
                //DEBUG: << "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwant to copy: " sf
                //;               
                CASE !Comp.TEST_value && "R" IN Comp.Optimizations && (
                	 Comp.Copy_for_class[sf.Index] != NONE) && (
                	 Comp.Copy_for_class[sf.Index] !IN Comp.All_classes[]) //Comp.Copy_for_class[sf.Index] !IN Comp.Classes_used[])
                	 ?
                     //DEBUG: << "--------------------------- copy skept !!!!"
                     //" " sf " Comp.TEST_value=" Comp.TEST_value.Str
                     //" Comp.Optimizations=" Comp.Optimizations
                     //"" #NL ;
                     CONTINUE sf ;
                CASE ?
                [Starting(sf, "<bin>")] ?
                     STR dest|ination_name = sf.["<bin>".Len TO *]
                ELSE dest = sf.Extract_file_name ;
                
                copy_file_removing_comments(sf,
                    Comp.Destination.Trailing_slash dest)
            ;
            RESULT = TRUE
            ------------------------------ 'debug info on functions / methods'
            CASE Comp.Debugging ?
	             FOR i IN [All_methods[].Count-1 DOWNTO 1] :
	                 CASE All_methods[i] == All_methods[i-1] ?
	                      All_methods[].Delete(i) ;
	             ;
	             generate_methods_info ;
            .
            
        //FUN time_file(STR path|_of_file) ==> STR :
        //    RESULT = Get_file_modified_time_formatted(path) .
		    
            
        FUNCTION check_changed(
        STR Path|_text, STR Text|_new[]) ==> BOOL
        	:
        	tf|ile_text_loader_temp = {Text_file}(Path = Path)
        	STR old|_version[]
        	NONE = tf.Load(old[])
        	CASE old[].Count != Text[].Count ? RESULT = TRUE ==> ;
        	FOR s IN old[] :
        	    CASE s != Text[s.Index] ? RESULT = TRUE ==> ;
        	; .
            

        METHOD copy_file_removing_comments(
        	STR Src|_file_path, STR Dst|_path)
        	:
            -------------------------------------- 'remove old instance'
            CASE Dst.Exists ? 
                 Dst.Delete_file 
	             CASE Dst.Exists ? 
	                  Comp.Error("Can not remove old version of file"._Ecannot3
	                  " " Dst) ;
            ;
            -------------------------------------- 'search  source file to copy'
            STR source|_actual = Src
            CASE Starting(Src, "<bin>") ?
                 source = Src.["<bin>".Len TO *]
                 Copy_file(source, Dst)
                 CASE !Dst.Exists ?
                      << "Can not copy " source " to " Dst " " >> ;
                 ==> ;
            CASE "\" !IN source && "/" !IN source ?
                 FOR s IN Comp.Source_paths[] :
                     CASE (s.Trailing_slash source).Exists ?
                          source = s.Trailing_slash source
                          BREAK s ;
                 ;
            ;
            CASE Comp.Verbose ? 
                 << "COPY"._Mcopy ": " source " to " Dst #NL ;
            ------------------------------------ 'load and remove comments'
            STR text|_copying[]
            temp|_file = {Text_file}(Path = source)
            NONE = temp.Load_strings(text[])
            comment_unnecessary_parts(text[])
            ------------------------------------ 'replace comments to a warning'
            FOR i IN [text[].Count-1 DOWNTO 0] :
                CASE Starting(text[i], "//?") || Starting(text[i], "//-->") || (
                     text[i].Trim == "//.")
                     ? 
                     CONTINUE i ;
                CASE text[i].Trim[0 TO 1] == "//" ?
                     text[i] = "//-this is a copy only - do not change: "
                     "changes will not take effect on the next compile"._Mthis
                ;
            ;
            ------------------------------- 'save modified text'
            temp.Path = Dst
            BOOL saved|_okay = temp.Save_strings(text[])
            CASE !saved ? 
                 Comp.Error("Can not save copy of"._Ecannot4 
                 " " source " " ("to"._Eto) " " Dst) ; .
                 
                 
                 


        */
        private bool do_generate()
        {
            generate_project();
            foreach (Type c in Comp.All_classes)
            {
                string path = c.Final_name + ".cs";
                o.Clear();
                if (!generate_class(c)) return false;
                Text_file tf = new Text_file(
                	StringFunctions.Trailing_slash(Comp.Destination) + 
                       Path.GetFileName(path));
                if (Comp.Verbose) Console.WriteLine("Saving: " + tf.Path + " (" +
                    o.Count.ToString() + " lines)");
                tf.Save_strings(o);
            }
            foreach (string cf in Comp.Copy_files)
            {
                copy_file_removing_comments(cf, 
                	StringFunctions.Trailing_slash(Comp.Destination) +
                    Path.GetFileName(cf));
            }
            return true;
        }

        private static void copy_file_removing_comments(string Src, string Dst)
        {
            Text_file temp = new Text_file(Src);
            List<string> text = new List<string>();
            temp.Load_strings(text);
            for (int i = 0; i < text.Count; i++)
            {
                if (text[i].Trim().Length >= 2 && text[i].Trim().Substring(0, 2) == "//")
                    text[i] = "// this is a copy only - do not change: " +
                     "changes will not take effect on the next compile";
            }
            temp.Path = Dst;
            temp.Save_strings(text);
        }

        /*
        
        METHOD generate_project( STR Exe|cutable_name ) :
			CASE ?
			["$FRAMEWORK" IN Comp.Defined_name[]] ?
			     STR framework|_version = Comp.Defined_value[
			     	Comp.Defined_name[].Find("$FRAMEWORK")]
			     CASE framework !IN ["4.0", "4", "4.5", "4.5.1", "4.5.2", 
			          "4.6.1", "4.7.2", "4.8"] 
			          ?
			          Comp.Warning("We do not know such framework, but believe "
			          "you set it correctly"._WFramework)
			     ;
        	[Get_environment_var("AL4Framework") != ""] ?
        	     framework = Get_environment_var("AL4Framework")
        	     CASE framework < "3.5"  
        	          ?
        	          Comp.Warning("Unknown framework in AL4Framework "
        	          "environment variable: " framework ", will reset to default")
        	          
        	          framework= "" ;
			ELSE
				 CASE Comp.Verbose ?
				      Console_color({colors}.'RED')
				      
				      << "Option /$FRAMEWORK is not set, /$FRAMEWORK=4.8 "
				         "supposed"._MOptionFrameWork #NL
				         
				 	  Console_color({colors}.'SILVER') ;
			;
			CASE framework == "4" 
			     || framework=="" && "Windows 1" IN Platform_info
			     ? framework = "4.0" ;
			CASE framework == "" ? framework = "4.8" ;
            ------------------------------- 'generate csproj'
			tf|ile_text_temp = {Text_file}(
                    Path = Comp.Destination.Trailing_slash
                    "" Comp.Project ".csproj") 
                           
			NONE = tf.Load(o[])
			FOR s IN o[] :
			    s =s.Trim
			    CASE Starting(s, "<Compile Include=") ? 
			         s = s.[s.Find(#QU)+1 TO *] 
			         s = s.[0 TO s.Find(#QU)-1]
			         STR include_old[] << s
			    ;
			;
			o[].Clear
            --------------------- 'new csproj content'        
            INT m1|_csproj1 = DATA[].Find("--CSPROJ--1")
            INT m2|_csproj2 = DATA[].Find("--CSPROJ--2")
            STR tools_v|ersion = "4.0"
            CASE framework >= "4.6" ? tools_v = "12.0" ;
            FOR i INDEXING STR IN [m1+1 TO m2-1] : 
                o[] << Replace_all(Replace(DATA[i], "TOOLS-VERSION", tools_v),
                	"FRAMEWORK-VERSION", framework)
                CASE o[*].Trim == "<OutputPath>.</OutputPath>" ?
                     o[*] = "<OutputPath>" Comp.Destination.Trailing_slash 
                     	    "</OutputPath>"
                ;
                CASE ?
				[Starting(o[*], "FRAMEWORK")] ?
				     STR f|wk_version = o[*].[0 TO o[*].Find(":")-1]
				     o[*] = o[*].[f.Len + 1 TO *]
				     f = f.["FRAMEWORK".Len TO *]
				     CASE ?
				     [f.[*]=="+" && Starting(framework, f.[0 TO *-1])] ? NONE
				     [f != framework] ? o[].Delete(o[].Count-1) ;
                [Starting(o[*], "CONSOLE:")] ?
                     CASE is_console_app ?
                          o[*] = o[*].["CONSOLE:".Len TO *]
                     ELSE o[].Delete(o[].Count-1) ;
                [Starting(o[*], "VISUAL:")] ?
                	 CASE !is_console_app ?
                	      o[*] = o[*].["VISUAL:".Len TO *]
                	 ELSE o[].Delete(o[].Count-1) ;
                [Starting(o[*].Trim, "<PlatformTarget>")] ?
                     CASE ?
                     ["$x64" IN Comp.Defined_name[]] ?
                 	 	o[*] = "<PlatformTarget>x64</PlatformTarget>"
                     [framework >= "4.6"] ?
                        o[] << "  <Prefer32Bit>false</Prefer32Bit>" ;
                ;
            ;
            
            STR compile_inc|lude[]
            FOR c IN Comp.All_classes[] :
                //DEBUG: << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
                //	"" c.Names[0] "-->" c.Final_name 
                //	" ????????? " skip_class(c).Str #NL ;
                //CASE c.Is_translation ? CONTINUE c ;
                CASE skip_class(c) ? CONTINUE c ;
				compile_inc[] << c.Final_name ".cs"
				include_old[].Remove(c.Final_name ".cs")
                o[] << "   <Compile Include="#QU c.Final_name ".cs" #QU" />"
            ;
            o[] << "    <Compile Include="#QU"AssemblyInfo.cs"#QU " />"
            o[] << "    <Compile Include="#QU"AL4.cs"#QU" />"
            	   
            FOR s IN Comp.Copy_files[] :
                CASE !Comp.TEST_value && Comp.Optimizations.Trim != "" && (
                	 Comp.Copy_for_class[s.Index] != NONE) && (
                	 skip_class(Comp.Copy_for_class[s.Index]))
                	 ?
                     CONTINUE s ;  
                CASE !Comp.TEST_value && "R" IN Comp.Optimizations && (
                	 Comp.Copy_for_class[s.Index] != NONE) && (
                	 Comp.Copy_for_class[s.Index] !IN Comp.All_classes[]) //Comp.Copy_for_class[sf.Index] !IN Comp.Classes_used[])
                	 ?
                     //DEBUG: << "--------------------------- copy skept !!!!"
                     //" " sf " Comp.TEST_value=" Comp.TEST_value.Str
                     //" Comp.Optimizations=" Comp.Optimizations
                     //"" #NL ;
                     CONTINUE s ;                   
                CASE Change_ext(s, ".cs") == s ?
                     STR s_f|ile_name = Extract_file_name(s)
                     CASE s_f IN compile_inc[] ?
                          Comp.Warning("Ambiguous COPY command for class "
                          "file"._EAmbigCopy ": " s_f)
                          CONTINUE s ;
                     compile_inc[] << s_f
                     include_old[].Remove(s_f)
                     o[] << "   <Compile Include="#QU s_f #QU" />" ;
            ;
            FOR s IN include_old[] :
                STR st|otal_inserting = "<Compile Include="#QU s #QU " />"
                FOR ss IN o[] :
                    CASE ss.Trim==st ? BREAK ss, CONTINUE s ;
                ;
                CASE Exists(Comp.Destination.Trailing_slash s) ? 
                     o[] << "  " st ;
            ;
            INT m3|_csproj3 = DATA[].Find("--CSPROJ--3")
            FOR i INDEXING STR IN [m2+1 TO m3-1] : o[] << DATA[i] ;
            CASE Comp.Noconsole ?
                 FOR s IN o[] :
                     CASE "<OutputType>" IN s ?
                          o[s.Index] = "<OutputType>WinExe</OutputType>"
                          BREAK s ;
                 ;
            ;
            --------------------- 'provide executable name (to build in VS IDE)'
            FOR s IN o[] :
                CASE s.Trim == "<AssemblyName>Program</AssemblyName>" ?
                     o[s.Index] = "<AssemblyName>" Exe "</AssemblyName>" ;
            ;
            ------------------------------ 'save csproj'
            NONE = tf.Save(o[])
            o[].Clear
            --------------------- 'provide Assembly.cs'
            INT a1|_start_assembly = DATA[].Find("--ASSEMBLY--(")
            INT a2|_end_assembly = DATA[].Find("--ASSEMBLY--)")
            STR omit|ted_options[]
            FOR i INDEXING STR IN [a1+1 TO a2-1] :
                o[] << DATA[i]
                CASE ?
                ["ASSEMBLY-TITLE" IN o[*]] ?
                     CASE "$Title" IN Comp.Defined_name[] ?
                          STR title|_option = Comp.Defined_value[
                          		 Comp.Defined_name[].Find("$Title")]
                     ELSE omit[] << "$Title" ;
                     o[*] = Replace(o[*], "ASSEMBLY-TITLE", title)
                ["ASSEMBLY-DESCRIPTION" IN o[*]] ?
                	 CASE "$Description" IN Comp.Defined_name[] ?
                	      STR descr|iption_application = Comp.Defined_value[
                	      	  Comp.Defined_name[].Find("$Description")]
                	 ELSE omit[] << "$Description" ;
                	 o[*] = Replace(o[*], "ASSEMBLY-DESCRIPTION", descr)
                ["ASSEMBLY-CONFIGURATION" IN o[*]] ?
                     CASE "$Configuration" IN Comp.Defined_name[] ?
                          STR config|uration = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$Configuration")]
                     ELSE omit[] << "$Configuration" ;
                     o[*] = Replace(o[*], "ASSEMBLY-CONFIGURATION", config)
                ["ASSEMBLY-COMPANY" IN o[*]] ?
                     CASE "$Company" IN Comp.Defined_name[] ?
                          STR company|_option = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$Company")]
                     ELSE omit[] << "$Company" ;
                     o[*] = Replace(o[*], "ASSEMBLY-COMPANY", company)
                ["ASSEMBLY-PRODUCT" IN o[*]] ?
                     CASE "$ProductName" IN Comp.Defined_name[] ?
                          STR prod|uct_name = Comp.Defined_value[
                          		 Comp.Defined_name[].Find("$ProductName")] 
                     ELSE omit[] << "$ProductName" ;
                     o[*] = Replace(o[*], "ASSEMBLY-PRODUCT", prod)
                ["ASSEMBLY-COPYRIGHT" IN o[*]] ?
                     CASE "$Copyright" IN Comp.Defined_name[] ?
                          STR copyright|_option = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$Copyright")]
                     ELSE omit[] << "$Copyright" ;
                     o[*] = Replace(o[*], "ASSEMBLY-COPYRIGHT", copyright)
                ["ASSEMBLY-TRADEMARK" IN o[*]] ?
                     CASE "$Trademark" IN Comp.Defined_name[] ?
                          STR trademark|_option = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$Trademark")]
                     ELSE omit[] << "$Trademark" ;
                     o[*] = Replace(o[*], "ASSEMBLY-TRADEMARK", trademark)
                ["ASSEMBLY-VERSION" IN o[*]] ?
                     CASE "$Version" IN Comp.Defined_name[] ?
                          STR version|_option = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$Version")]
                     ELSE omit[] << "$Version"
                     	  version = "1.0.0.0" 
                     ;
                     CASE !valid_version(version) ?
                          Comp.Error("$Version is not valid"._EVersionInvalid) ;
                     o[*] = Replace(o[*], "ASSEMBLY-VERSION", version)
                ["ASSEMBLY-FILE-VERSION" IN o[*]] ?
                     CASE "$FileVersion" IN Comp.Defined_name[] ?
                          STR fversion|_option = Comp.Defined_value[
                          	  Comp.Defined_name[].Find("$FileVersion")]
                     ELSE omit[] << "$FileVersion"
                     	  fversion = "1.0.0.0"
                     ;
                     CASE !valid_version(fversion) ?
                          Comp.Error("$FileVersion is not "
                          "valid"._EFileVersionInvalid)
                     ;
                     o[*] = Replace(o[*], "ASSEMBLY-FILE-VERSION", fversion)
                ["ASSEMBLY-GUID" IN o[*]] ?
                    STR guid|_assembly = Comp.Defined_value[
                    	Comp.Defined_name[].Find("$AssemblyGuid")]
                    	
                    CASE ?
                    [guid == "" && framework < "4.5"] ? 
                        guid = "60632088-2212-47f0-8a7a-2224d0b93bd9"
                        
                    [guid == "" && framework <= "4.6"] ? 
                        guid = "e2bf218c-9e3d-46bb-8f2a-6f35706e3eca"
                        
                    [guid == ""] ?
                        guid = "b61c1ff2-945e-4757-babe-e43b68b26aed"
                    ;
                    o[*] = Replace(o[*], "ASSEMBLY-GUID", guid)
                ;
            ;
            CASE omit[].Count > 0 ?
            	 STR s_omit|ted_options = ""
            	 FOR s IN omit[]:
            	     s_omit = s_omit s "; " ;
            	     
                 Comp.Warning("Some assembly-related options are not "
                 "set"._WOmitAssembly ": " s_omit)
            ;
            tf.Path = Comp.Destination.Trailing_slash "AssemblyInfo.cs"
            NONE = tf.Save(o[])
			o[].Clear            
            ------------------------------ 'copy AL4.cs to destination folder'
            INT al4_cs|_start = DATA[].Find("--AL4.cs--(")
            INT al4_end|_line = DATA[].Find("--AL4.cs--)")
            BOOL skipping|_until_dot_commented = FALSE
            FOR i INDEXING STR IN [al4_cs + 1 TO al4_end-1] :
                STR d|ate_string = DATA[i]
                STR t|rimmed_d = d.Trim
                CASE ?
                [Comp.Diagnostics
                 && Starting(d, "//#define DIAGNOSTICS")] ?
                    CASE Find_from(d, 0, "LIGHT") < 0 
                         || Comp.Diagnostics_light 
                         ? d = Remove_starting(d, "//") ;
                [Comp.Diagnostics 
                 && Starting(d, 
                 "//#initialize diagnostics except classes list")] ?
                    d = Merge(Comp.Diag_except[], ", ")
                [Starting(d, "@int32:")] ?
                    CASE Comp.Int32 ? 
                         d = "     " d.["@int32:".Len TO *]
                    ELSE d = "" ;
                [Starting(d, "@int64:")] ?
                    CASE !Comp.Int32 ? 
                         d = "     " d.["@int64:".Len TO *]
                    ELSE d = "" ;
                [d == "//." && skipping] ?
                     skipping = FALSE
                [skipping] ? CONTINUE i
                [Starting(d, "/" "/?{")] ?
                     CASE !class_present(d.[3 TO *].Trim) ?
                          skipping = TRUE ;
                [d.Trim == "/" "/#RTTI_type_info"] ?
                     CASE "$INTERPRETER" IN Comp.Defined_name[] ?
                          o[] << "public Ref_obj Origin_;"
                     ;
                     output_RTTI_info_tables
                     CONTINUE i
                [Starting(d, "/" "/#test:")] ?
                     d = sp(6) d.[8 TO *]
                     CASE !Comp.TEST_value ? CONTINUE i ;
                [Starting(d, "//#not_test:")] ?
                     d = sp(10) d.[12 TO *]
                     CASE Comp.TEST_value ? CONTINUE i ;
                [Starting(d, "#debug" ":")] ?
                	 CASE Comp.Debugging ?
                	      d = d.[d.Find(":")+1 TO *]
                	 ELSE d = "//" d ;
                [t == "/" "/#localize"] ?
                     add_localize_data
                     CONTINUE i
                     
                [t == "/" "/#app_icon"] ?
                     CASE "$ICON" IN Comp.Defined_name[] ? add_app_icon
                     
                     ELSE o[] << "public static byte[] App_icon "
                     		"= new byte[] {}; "
                     ;
                     CONTINUE i
                     
                [t == "/" "/#function_names"] ?
                     output_all_function_names
                     CONTINUE i
                [t == "/" "/#native_functions_table" && (
                 "$INTERPRETER" IN Comp.Defined_name[])] ?
                     coll|ect_native_functions = {Collect_native_functions}(
                     	Generator_ = THIS), OWNED BY THIS
                     FOR cd IN coll.Code[] :
                         o[] << cd ;
                     CASE coll.Code[].Count == 0 ?
                          o[] << "public static string[] "
                          		 "Native_functions_declarations "
								 "= new string[];"
                     ;
                     CONTINUE i
                     
                [t == "/" "/#shadow_classes" && (
                 "$INTERPRETER" IN Comp.Defined_name[])] ?
                 	o[] << "// Back[].Count=" coll.Back[].Count.Str
                 	FOR cd IN coll.Back[] :
                 	    o[] << cd ;
                 	CONTINUE i
                 	
                [Starting(d, "/" "/#profiler_save_reset")] ?
                    o[] << d
		            CASE use_profiler == "" ?
		                 CONTINUE i ;
	            	o[] << sp(16) 
	            	o[*] = o[*] "List<string> all_cnts = new List<string>();"
			        FOR c IN Comp.All_classes[] :
			            CASE c == NONE ? CONTINUE c ;
			         	o[] << sp(16) c.Final_name ".Collect_cnt(all_cnts);"
			        ;
			        o[] << sp(16) "File.WriteAllLines("#QU
			        o[*] = o[*] "profiler_data.prof"#QU", all_cnts.ToArray());"
			        --------------- 'add output to console a message'
			        o[] << sp(16) "WriteLine("#QU"Profiler data written to:"
			        o[*] = o[*] #QU" + Path.GetFullPath("#QU"profiler_data.prof"
			        o[*] = o[*] #QU"));"
                     
                [Starting(d.Trim, "/" "/")] ?
                     d = "/" "/ this is generated file, source is in "
                     "{Generator|_of_CSharp_code} class"
                     
                [LOGGING_METHODS && Starting(d.Trim,
                 "public static string LOG_METHODS_PATH;")] ?
                     
                     d = Replace(d, ";", " = "#QU Comp.Defined_value[
                  		Comp.Defined_name[].Find("$LOG_METHODS")] #QU";")
                ;
                o[] << d ;
            tf.Path = Comp.Destination.Trailing_slash "AL4.cs"
            NONE = tf.Save(o[])
            o[].Clear
            ------------------------------ 'app.config'
            INT app_cfg|_from = DATA[].Find("--app.config--(")
            INT app_end|_of_config = DATA[].Find("--app.config--)")
            FOR i INDEXING STR IN [app_cfg+1 TO app_end-1] : 
                o[] << Replace_all(DATA[i], "FRAMEWORK-VERSION", framework) ;
            tf.Path = Comp.Destination.Trailing_slash "app.config"
            NONE = tf.Save(o[])
            o[].Clear
            .
            
METHOD output_RTTI_info_tables :
	STR all_r|ecords_and_enums_list[]
	STR all_e|num_items[]
	STR k|inds_array[] << sp(4) "public static int[] RTTI_type_kinds = {"
	STR add_k|inds_array[]
	o[] << sp(4) "public static string[] RTTI_type_info = {"
	-------------------- '{Object} base for all objects always number 0'
	k[] << sp(8) "7, "
	o[] << sp(8) #QU "{|Object}" #QU ","
	-------------------- '5 simple types always numbers are 1 to 6'
	k[] << sp(8) "0, 1, 2, 3, 4, "
	o[] << sp(8) #QU "BOOL|EAN" #QU ","
	o[] << sp(8) #QU "BYTE" #QU ","
	o[] << sp(8) #QU "INT|EGER" #QU ","
	o[] << sp(8) #QU "REAL" #QU ","
	o[] << sp(8) #QU "STR|ING" #QU ","
	-------------------- 'rest of all classes, then all structures & enums'
	FOR c IN Comp.All_classes[] :
	    c.Type_total_index = renumber(c.Type_total_index,  6 + c.Index)
	    k[] << sp(8) "7, // " c.Names[0]
	    STR w_name|_class = c.Whole_name
	    o[] << sp(8) #QU w_name
	    CASE c.Base_ != NONE ?
	         o[*] = o[*] ",base:" (Comp.All_classes[].Find(c.Base_) + 6).Str ;
	    CASE c.Enums_[].Count + c.Structures_[].Count > 0 ?
	    	 o[*] = o[*] ",rec:" (6 + Comp.All_classes[].Count + all_r[].Count).Str
	    	 		 ",count:" (c.Enums_[].Count + c.Structures_[].Count).Str 
	    	 FOR e IN c.Enums_[] :
	    	 	 e.Type_total_index = renumber(e.Type_total_index, 6 
	    	 	 	+ Comp.All_classes[].Count + all_r[].Count)
	    	 	 add_k[] << sp(14) "5, //" e.Names[0]
	    	 	 
	    	     all_r[] << sp(14) #QU e.Whole_name
	    	     			",items:" all_e[].Count.Str 
	    	     			",count:" e.Items[].Count.Str #QU ","
	    	     			
	    	     add_items_of_enum(all_e[], e)
	    	 ;
	    	 FOR st IN c.Structures_[] :
	    	     st.Type_total_index = renumber(st.Type_total_index, 6 
	    	 	 	+ Comp.All_classes[].Count + all_r[].Count)
	    	 	 	
	    	     add_k[] << sp(14) "7, //" c.Names[0] "." st.Names[0]
	    	     
	    	     all_r[] << sp(14) #QU st.Whole_name #QU ","
	    	     			"/" "/ / " st.Type_total_index.Str
	    	 ;
	    ;
	    o[*] = o[*] #QU ", // " c.Type_total_index.Str
	    //DEBUG: o[*] << " // " (6 + c.Index).Str ; 
	;
	FOR sr IN add_k[] : k[] << sr ;
	FOR sr IN all_r[] : o[] << sr ;
	k[] << sp(8) "-1 };" << ""
	o[] << sp(4) #QU#QU "};" << ""
	FOR sr IN k[] : o[] << sr ; 
	---------------------------- 'all enum item names'
	o[] << sp(4) "public static string[] RTTI_enum_items = {"
	FOR se IN all_e[] : o[] << se ;
	o[*] = Remove_trailing(o[*], ",")
	o[] << sp(4) "};" << ""
	---------------------------- 'base RTTI methods to work with fields'
	o[] << sp(4) "public virtual int RTTI_object_field_count()"
	o[] << sp(4) "{"
	o[] << sp(8) "return 0;"
	o[] << sp(4) "}"
    ---------------------------- 'get object field name'
	o[] << sp(4) "public virtual string RTTI_object_field_name(int index)"
	o[] << sp(4) "{"
	o[] << sp(8) "return "#QU#QU";"
	o[] << sp(4) "}"
	---------------------------------------- 'get object field info'
	o[] << sp(4) "public virtual int RTTI_object_info_field("
				 "int index, int What)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return  0;"
	o[] << sp(4) "}"
	------------------ 'get object field (simple types only, w/o STR)'
	o[] << sp(4) "public virtual bool RTTI_object_get_bool("
				 "int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	--------------------- ', get byte'
	o[] << sp(4) "public virtual byte RTTI_object_get_byte("
				 "int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return 0;"
	o[] << sp(4) "}"
	--------------------- ', get int'
	o[] << sp(4) "public virtual "
	CASE Comp.Int32 ? o[*] = o[*] "int"
	ELSE o[*] = o[*] "long" ;
	o[*] = o[*] " RTTI_object_get_int(int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return 0;"
	o[] << sp(4) "}"
	--------------------- ', get real'
	o[] << sp(4) "public virtual double RTTI_object_get_real("
				 "int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return 0;"
	o[] << sp(4) "}"
	--------------------- ', get array'
	o[] << sp(4) "public virtual ArrayAny RTTI_object_get_array(int index)"
	o[] << sp(4) "{"
	o[] << sp(8) "return null;"
	o[] << sp(4) "}"
	------------------ 'set object field (simple types only, w/o STR)'
	o[] << sp(4) "public virtual bool RTTI_object_set_bool("
				 "int index, bool Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	-------------------- ', byte'
	o[] << sp(4) "public virtual bool RTTI_object_set_byte("
				 "int index, int Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	-------------------- ', int'
	o[] << sp(4) "public virtual bool RTTI_object_set_int(int index, "
	CASE Comp.Int32 ? o[*] = o[*] "int"
	ELSE o[*] = o[*] "long" ;
	o[*] = o[*] " Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	------------------- ', real'
	o[] << sp(4) "public virtual bool RTTI_object_set_real("
				 "int index, double Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	------------------------------------------------------------ 'strings'
	o[] << sp(4) "public virtual string RTTI_object_get_string("
				 "int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return "#QU#QU";"
	o[] << sp(4) "}"
	---------------- 'set object field of type STR value'
	o[] << sp(4) "public virtual bool RTTI_object_set_string("
				 "int index, string Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	----------------------------------------------------------- 'objects'
	o[] << sp(4) "public virtual Ref_obj RTTI_object_get_object("
				 "int index, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return NoneObj_AL4_object.hard_link;"
	o[] << sp(4) "}"
	---------------- 'set object field of object type value'
	o[] << sp(4) "public virtual bool RTTI_object_set_object("
				 "int index, Ref_obj Value, int Index_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(8) "return false;"
	o[] << sp(4) "}"
	---------------- 'insert item into array field of object'
	o[] << sp(4) "public virtual void RTTI_object_field_array_insert("
				 "int index, int Insert_pos_in_array)"
				 
	o[] << sp(4) "{"
	o[] << sp(4) "}"
	---------------- 'delete item in array field of object'
	o[] << sp(4) "public virtual void RTTI_object_field_array_delete("
				 "int index, int Delete_pos_in_array, int Count_to_delete)"
				 
	o[] << sp(4) "{"
	o[] << sp(4) "}"
	---------------- 'allocate items in array field of object'
	o[] << sp(4) "public virtual void RTTI_object_field_array_allocate("
				 "int index, int Count_to_allocate)"
				 
	o[] << sp(4) "{"
	o[] << sp(4) "}"
	.
	
ENUM {what_return} :
	'FIELD_COUNT',
	'FIELD_NAME',
	'FIELD_INFO',
	'GET_STRING',
	'SET_BOOL',
	'SET_INT',
	'SET_REAL',
	'SET_STRING',
	'GET_OBJECT',
	'SET_OBJECT' .
	
METHOD generate_RTTI_methods({Type} Class|_generate_for) :
	generate_1_RTTI_method(Class,
		"int RTTI_object_field_count", 'FIELD_COUNT')
		
	generate_1_RTTI_method(Class,
		"string RTTI_object_field_name", 'FIELD_NAME')
		
	generate_1_RTTI_method(Class,
		"int RTTI_object_info_field", 'FIELD_INFO')
		
	generate_1_RTTI_method(Class,
		"string RTTI_object_get_string", 'GET_STRING')
		---------------------------- 'simple types value set'
	generate_1_RTTI_method(Class,
		"bool RTTI_object_set_bool", 'SET_BOOL')
		
	generate_1_RTTI_method(Class,
		"bool RTTI_object_set_int", 'SET_INT')
		
	generate_1_RTTI_method(Class,
		"bool RTTI_object_set_real", 'SET_REAL')
		
	generate_1_RTTI_method(Class,
		"bool RTTI_object_set_string", 'SET_STRING') .
	
	
METHOD generate_1_RTTI_method(
{Type} Class|_generate_for,
STR Method_name|_together_with_return_type,
{what_return} What|_return_or_do_in_method)
	:
	o[] << sp(4) "public override " Method_name "("
	CASE What != 'FIELD_COUNT' ? o[*] = o[*] "int index" ;
	CASE What ?
	['SET_BOOL']: o[*] = o[*] ", bool Value, int Index_in_array"
	['SET_INT']: 
	    o[*] = o[*] ", " 
	    CASE Comp.Int32 ? o[*] = o[*] "int"
	    ELSE o[*] = o[*] "long" ;
	    o[*] = o[*] " Value, int Index_in_array"
	['SET_REAL']: o[*] = o[*] ", double Value, int Index_in_array"
	['SET_STRING']: o[*] = o[*] ", string Value, int Index_in_array"
	['GET_STRING', 'GET_OBJECT', 'SET_OBJECT']:
					o[*] = o[*] ", int Index_in_array"
	['FIELD_COUNT', 'FIELD_NAME']: NONE
	['FIELD_INFO']: o[*] = o[*] ", int What"
	;
	o[*] = o[*] ")"
	--------------------- 'body'
	o[] << sp(4) "{"
	CASE What != 'FIELD_COUNT' ?
		 o[] << sp(8) "switch(index)" ;
	o[] << sp(8) "{"
	INT x|_dummy_not_used = generate_RTTI_fields(Class, 0, What)
	o[] << sp(8) "}"
	CASE What ?
	['FIELD_COUNT']: STR rtti|_fields = generate_RTTI_fields(Class, 0, What).Str
					 o[] << sp(8) "return " rtti ";"
	['GET_STRING', 'FIELD_NAME']: o[] << sp(8) "return "#QU#QU";"
	['SET_BOOL', 'SET_INT', 'SET_REAL', 'SET_STRING', 'SET_OBJECT']:
					o[] << sp(8) "return false;"
	['GET_OBJECT']: o[] << sp(8) "return NoneObj_AL4_object;"
	['FIELD_INFO']: NONE ;
	CASE What == 'FIELD_INFO' ? o[] << sp(8) "return 0;" ;
	o[] << sp(4) "}" << ""
	.
	
STR RTTI_prefix|_name
	
METHOD generate_RTTI_fields(
{Type} Class|_generate_for,
INT Case|_start_from,
{what_return} What|_return) ==> INT //RESULT|_continue_case_from
, RECURSIVE
	:
	INT current|_case = Case
	CASE Class.Kind == 'CLASS' && Class.Base_ != NONE ?
		 current = generate_RTTI_fields(Class.Base_, current, What) ;
	FOR f IN Class.Field[] :
	    CASE What == 'FIELD_COUNT' ?
	         current += 1
	         CONTINUE f ;
	    o[] << sp(12) "case " current.Str ":"
	    current += 1
	    CASE What ?
	    ['FIELD_COUNT']: NONE

	    ['FIELD_NAME']:
	    	o[] << sp(16) "return " #QU RTTI_prefix f.Names[0] #QU";"
	    	CONTINUE f

		['SET_BOOL', 'SET_INT', 'SET_REAL']:
			o[*] = o[*] "// " What.Name ": " RTTI_prefix f.Final_name
	    	CASE ?
	    	[f.Is_array || f.Type_.Kind IN ['CLASS', 'STRUCTURE', 'STR']] ?
	    	     o[] << sp(16) "return false;"
	    	     CONTINUE f
	    	;
	    	CASE f.Type_.Kind == 'BOOL' && What != 'SET_BOOL' || (
	    		 f.Type_.Kind == 'REAL' && What != 'SET_REAL') || (
	    		 f.Type_.Kind IN ['INT', 'ENUM'] && What != 'SET_INT')
	    		 ?
	    	     o[] << sp(16) "return false;"
	    	     CONTINUE f ;
	    	o[] << sp(16) RTTI_prefix f.Final_name " = "
	    	CASE f.Type_.Kind ?
	    	['BOOL', 'INT', 'REAL']: o[*] = o[*] "Value;"
	    	['ENUM']: o[*] = o[*] "(byte)Value;"
	    	['STR', 'CLASS', 'STRUCTURE']:
	    		o[*] = sp(16) "return false;"
	    		CONTINUE f
	    	;
	    	o[] << sp(16) "return true;"
	    	CONTINUE f

		['GET_STRING']:
	    	CASE f.Is_array || f.Type_.Kind != 'STR' ?
	    	     o[] << sp(16) "return "#QU#QU";"
	    	     CONTINUE f ;
	    	o[] << sp(16) "return " RTTI_prefix f.Final_name ";"
	    	CONTINUE f

		['GET_OBJECT']:
	    	CASE ?
	    	[f.Is_array && f.Type_.Kind IN ['CLASS', 'STRUCTURE']] ?
	    	     o[] << sp(16) "return " RTTI_prefix f.Final_name
	    	     		".GetObjects(Index_in_array);"
	    	[f.Type_.Kind IN ['CLASS', 'STRUCTURE']] ?
	    		 o[] << sp(16) "return " RTTI_prefix f.Final_name" ;"
	    	ELSE o[] << sp(16) "return "#QU#QU";" ;
	    	CONTINUE f

		['SET_STRING']:
			o[*] = o[*] "// SET_STRING: " RTTI_prefix f.Final_name
	    	CASE f.Is_array || f.Type_.Kind != 'STR' ?
	    	     o[] << sp(16) "return false;"
	    	     CONTINUE f ;
	    	o[] << sp(16) RTTI_prefix f.Final_name " = Value;"
	    	o[] << sp(16) "break;"
	    	CONTINUE f

		['SET_OBJECT']:
			o[*] = o[*] "// SET_OBJECT: " RTTI_prefix f.Final_name
	    	CASE ?
	    	[f.Is_array && f.Type_.Kind IN ['CLASS', 'STRUCTURE']] ?
	    	     o[] << sp(16) RTTI_prefix f.Final_name
	    	     		".SetObjects(Index_in_array, Value);"
	    	     o[] << sp(16) "return true;"
	    	[f.Type_.Kind IN ['CLASS', 'STRUCTURE'] && f.Is_weak] ?
	    	     o[] << sp(16) "Object_assign_weak("
	    	     		"" RTTI_prefix f.Final_name ", Value);"
	    	     o[] << sp(16) "return true;"
	    	[f.Type_.Kind IN ['CLASS', 'STRUCTURE']] ?
	    	     o[] << sp(16) "Object_assign_hard("
	    	     		"" RTTI_prefix f.Final_name ", Value);"
	    	     o[] << sp(16) "return true;"
	    	ELSE o[] << sp(16) "return false;" ;
	    	CONTINUE f

	    ['FIELD_INFO']: NONE ;
	    o[*] = o[*] "// FIELD_INFO: " RTTI_prefix f.Names[0]
	    o[] << sp(16) "switch(What)"
	    o[] << sp(16) "{"
	    -------------------------- 'TYPE_INDEX'
	    o[] << sp(20) "case 0:"
	    o[] << sp(24) "return " f.Type_.Type_total_index.Str ";"
	    -------------------------- 'IS_ARRAY'
	    o[] << sp(20) "case 1:"
	    o[] << sp(24) "return " f.Is_array.bool_as_int.Str ";"
	    -------------------------- 'IS_FIXED|_ARRAY'
	    o[] << sp(20) "case 2:"
	    o[] << sp(24) "return " f.Is_fixed.bool_as_int.Str ";"
	    -------------------------- 'IS_PUBLIC'
	    o[] << sp(20) "case 3:"

	    o[] << sp(24) "return " (f.Names[0].[0].Upper == f.Names[
	    	   0].[0]) .bool_as_int.Str ";"
	    -------------------------- 'SIZE_ARRAY'
	    o[] << sp(20) "case 4:"
	    CASE f.Is_array ?
	    o[] << sp(24) "return " f.Final_name ".Count;"
	    ELSE
	    o[] << sp(24) "return 0;" ;
	    o[] << sp(16) "}"
	    o[] << sp(16) "break;"
	;
	RESULT = current .
	
FUN bool_as_int(BOOL Value|_to_represent) ==> INT :
	CASE Value ? RESULT = 1 ; .
	

	
FUNCTION add_items_of_enum(
STR List|_of_enum_items[], {Type} E|numeration)
	:
	FOR v IN E.Items[] :
		List[] << sp(8) #QU  v.Whole_name #QU "," ; .
            
	
BOOL no_visual_option_reported            
            
METHOD is_console_app|lication ==> BOOL :
	CASE Comp.Noconsole ? ==> ;
	CASE "$Visual" IN Comp.Defined_name[] ? ==> ;
	RESULT = TRUE
	CASE no_visual_option_reported ? ==> ;
	no_visual_option_reported = TRUE
	//DEBUG:
	//	Comp.Warning("Neither option $Visual nor option /noconsole is not set, "
	//		"the application is supposed to be console in "
	//		"options."._WVisualNoconsole)
	//; 
	.
		
FUN valid_version(STR V|ersion_string) ==> BOOL :
	CASE V == "" ? RESULT = TRUE ==> ;
	STR split|ted_version[]
	Split(split[], V, ".")
	//CASE split[].Count != 4 ? ==> ;
	FOR s IN split[] :
	    FOR i IN [0 TO s.Len-1] :
	        CASE s.[i] !IN "0123456789" ? ==> ;
	    ;
	;
	RESULT = TRUE .
            
METHOD output_all_function_names:
	STR fn|ames_of_all_functions[]
	FOR c IN Comp.All_classes[] :
	    FOR f IN c.Method[] :
	        CASE f.Final_name == "-" ? CONTINUE f ;
	        FOR i|dummy IN [fn[].Count TO f.Global_n] :
	            fn[] << "?" ;
	        INT i_fn INDEXING STR = f.Global_n
	        fn[i_fn] = unique_class_name(c) "." f.Names[0] ;
	;
	FOR s IN fn[]:
	    o[] << #QU s #QU "," ;
	CASE o[*].[*] == "," ? o[*] = o[*].[0 TO *-1] ; .
	
METHOD unique_class_name(
	{Type} Class|_which_name_needed) ==> STR
	:
	FOR c IN Comp.All_classes[]:
	    CASE c == Class ? CONTINUE c ;
	    CASE c.Names[0].[1] != Class.Names[0].[1] ? CONTINUE c ;
	    CASE c.Names[0] == Class.Names[0] ?
	         RESULT = Class.Whole_name ==> ;
	;
	RESULT = Class.Names[0] .
	            
            
METHOD generate_methods_info :
	STR info|_on_all_methods[]
	FOR i IN [0 TO All_methods[*].Total_fn] :
	    {Fun} m|ethod_at_i = find_method_by_total_fn(i)
	    CASE m == NONE ?
	    	 //info[] << i.Str
	    	 CONTINUE i ;
	    CASE m.Overloaded_[].Count > 0 ? CONTINUE i ;
	    	 
	    STR mc_w|hole_name = m.Class.Whole_name
	    STR m_w|hole_name = m.Whole_name
	    info[] << i.Str " " mc_w "." m_w "("
	    
	    CASE !m.Modifiers['STATIC'] ? info[*] = info[*] "THIS," ;
	    FOR p IN m.Param[] :
	        STR p_w|hole_name = p.Whole_name 
	    	info[*] = info[*] type_represent(p.Type_) " " p_w
	        CASE ?
	        [p.Is_fixed && p.Size_n != ""] ? info[*] = info[*] "[" p.Size_n "]"
	        [p.Is_fixed] ? info[*] = info[*] "[*]"
	        [p.Is_array] ? info[*] = info[*] "[]" ;
	        info[*] = info[*] "," ;
	    info[*] = info[*].[0 TO *-1] ")"
	    CASE m.Result != NONE ?
	         info[*] = info[*] "==>" type_represent(m.Result.Type_) ; 
	    info[*] = info[*] ":L["
		-------------------------------- 'list local variables of simple types'
	    FOR v IN m.Local_var[] :
	        CASE v.Is_array 
	        	 || v.Type_.Kind IN ['CLASS', 'STRUCTURE', 'REAL', 'STR']
	        	 ?
	             CONTINUE v ;
	        STR v_w|hole_name = v.Whole_name 
	    	info[*] = info[*] v.Index.Str ":" 
	    	info[*] = info[*] type_represent(v.Type_) 
	    	info[*] = info[*] " " v_w ","
	    ;
	    CASE info[*].[*] == "," ? info[*] = info[*].[0 TO *-1] ;
	    -------------------------------- 'list of real scalar variables'
	    info[*] = info[*] "],R["
	    FOR v IN m.Local_var[] :
	        CASE v.Is_array || v.Type_.Kind != 'REAL' ? CONTINUE v ;
	        v_w = v.Whole_name 
	        info[*] = info[*] v.Index.Str ":" type_represent(v.Type_) " " v_w ","
	    ;
	    CASE info[*].[*] == "," ? info[*] = info[*].[0 TO *-1] ;
	    ------------------------ 'object variables, records, strings and arrays'
	    info[*] = info[*] "],o["
	    FOR v IN m.Local_var[] :
	        CASE !v.Is_array && v.Type_.Kind !IN ['CLASS', 'STRUCTURE',
	        	 'STR'] || v.Index < 0
	        	 ?
	             CONTINUE v ;
	        v_w = v.Whole_name 
	        info[*] = info[*] v.Index.Str ":" type_represent(v.Type_) " " v_w ","
	    ;
	    CASE info[*].[*] == "," ? info[*] = info[*].[0 TO *-1] ;
	    info[*] = info[*] "]."
	;
	----------------------------- 'now, output it ot the destination directory'
	tsave|_temp = {Text_file}(Path = Comp.Destination.Trailing_slash 
		"debug_functions.txt")
		
	NONE = tsave.Save(info[]) .
	
INT last_found_method|_index_to_optimize_search
	
METHOD find_method_by_total_fn(
	INT Index|_of_method) ==> {Fun}
	:
	FOR i IN [last_found_method TO All_methods[].Count-1] :
	    CASE All_methods[i].Total_fn == Index ?
	         RESULT = All_methods[i]
	         last_found_method = i ==> ;
	;
	FOR m IN All_methods[] :
	    CASE m.Total_fn == Index ?
	         RESULT = m 
	         last_found_method = m.Index ==> ;
	; .
	
FUNCTION type_represent({Type} T|ype_to_represent) ==> STR :
	CASE T.Kind ?
    ['BOOL', 'INT', 'REAL', 'STR']:
	   RESULT = T.Kind.Name
	   RESULT = RESULT.[1 TO *-1]
	   
    ['ENUM']:
    	STR b_w|hole_name = T.Base_.Whole_name
    	STR w|hole_name = T.Whole_name  
        RESULT = RESULT b_w "." w
    	
    ['CLASS', 'STRUCTURE']: RESULT = RESULT T.Whole_name ; .

METHOD add_app_icon :
	STR ico|n_path = Comp.Defined_value[Comp.Defined_name[].Find("$ICON")]
	CASE ":" !IN ico ? ico = Comp.Source_paths[0].Trailing_slash ico ;
	CASE !ico.Exists ?
	     Comp.Error("Icon file was not found"._EIconFileNotFound ": " ico) ;
	File_as_bytes_array(o[], ico)
	. 
	
            
METHOD add_localize_data :
    ----------------- 'if localized string are present?'
    STR l_names|_localize_strings[] << sp(6) "public static string[]"
    l_names[] << " Localize_name = new string[] {"
    PUSH generating_localized_strings = TRUE :
         INT start|_index_for_class = 0 
         FOR c IN Comp.All_classes[] :
             CASE c.Localize_n[].Count == 0 ? CONTINUE c ;
             CASE start == 0 ?
				  ---------------- 'add initial values for localized strings'
				  o[] << sp(6) "public static string[] Localize_str = new "
				  "string[] {"
             ;
             o[] << sp(10) #QU#QU ","
             l_names[] << sp(10) #QU "[" c.Names[*] "]"#QU ","
             start += 1
             c.Localize_1st_item = start
             FOR ns IN c.Localize_s[] :
             	 l_names[] << sp(10) #QU c.Localize_n[ns.Index] #QU ","
                 o[] << sp(10) gen_expr(ns) ","
                 start += 1
             ;
         ;
    ;
    CASE start == 0 ? ==> ;
    
    --------------------------- 'finish localization arrays'
    o[*] = o[*].[0 TO *-1] "};"             
    l_names[*] = l_names[*].[0 TO *-1] "};"
    FOR s IN l_names[] : o[] << s ; .
                 
    */
    private void add_localize_data(int Insert_at)
    {
        //----------------- 'if localized string are present?'
        if (Comp.All_localize_n.Count == 0) return;
        o.Insert(Insert_at++, sp(6) + "public static staring[] Localize_name = "
        + " new string[]{");
        for (int i = 0; i < Comp.All_localize_n.Count; i++)
        {
            string nloc = Comp.All_localize_n[i];
            o.Insert(Insert_at++, sp(10) + "\"" + nloc + "\","); 
        }
        int ia = Insert_at-1;
        o[ia] = o[ia].Substring(0, o[ia].Length - 1) + " };";
        //---------------- 'add initial values for localized strings'
        o.Insert(Insert_at++, sp(6) + "public static string[] Localize_str = "
        + " new string[] {");
        generating_localized_strings = true;
        try
        {
            for (int i = 0; i < Comp.All_localize_s.Count; i++)
            {
                Expression nstr = Comp.All_localize_s[i];
                if (nstr == null)
                    o.Insert(Insert_at++, sp(10) + "\"" + "\",");
                else o.Insert(Insert_at++, sp(10) + gen_expr(nstr) + ",");
            }
            int ib = Insert_at-1;
            o[ib] = o[ib].Substring(0, o[ib].Length - 1) + " };";
        }
        finally
        {
            generating_localized_strings = false;
        }
    }
    
        private void generate_project()
        {
            o.Clear();
            string nl = "\r\n";
            o.Add(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" + nl +
"<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">" + nl +
"  <PropertyGroup>" + nl +
"    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>" + nl +
"    <Platform Condition=\" '$(Platform)' == '' \">x86</Platform>" + nl +
"    <ProjectGuid>{907A09F7-30EC-49DB-BACC-40881CEDD6AE}</ProjectGuid>" + nl +
"    <OutputType>Exe</OutputType>" + nl +
"    <NoStandardLibraries>false</NoStandardLibraries>" + nl +
"    <AssemblyName>AL4Compiler</AssemblyName>" + nl +
"    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>" + nl +
"    <TargetFrameworkProfile>" + nl +
"    </TargetFrameworkProfile>" + nl +
"    <FileAlignment>512</FileAlignment>" + nl +
"  </PropertyGroup>" + nl +
"  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x86' \">" + nl +
"    <DebugSymbols>true</DebugSymbols>" + nl +
"    <DebugType>full</DebugType>" + nl +
"    <Optimize>false</Optimize>" + nl +
"    <OutputPath>.\\</OutputPath>" + nl +
"    <DefineConstants>DEBUG;TRACE</DefineConstants>" + nl +
"    <ErrorReport>prompt</ErrorReport>" + nl +
"    <WarningLevel>4</WarningLevel>" + nl +
"    <PlatformTarget>x86</PlatformTarget>" + nl +
"    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>" + nl +
"  </PropertyGroup>" + nl +
"  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|x86' \">" + nl +
"    <DebugType>pdbonly</DebugType>" + nl +
"    <Optimize>true</Optimize>" + nl +
"    <OutputPath>.\\</OutputPath>" + nl +
"    <DefineConstants>TRACE</DefineConstants>" + nl +
"    <ErrorReport>prompt</ErrorReport>" + nl +
"    <WarningLevel>4</WarningLevel>" + nl +
"    <PlatformTarget>x86</PlatformTarget>" + nl +
"    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>" + nl +
"  </PropertyGroup>" + nl +
"  <PropertyGroup>" + nl +
"    <RootNamespace>Compiled</RootNamespace>" + nl +
"  </PropertyGroup>" + nl +
"  <ItemGroup>" + nl +
"    <Reference Include=\"System\" />" + nl +
"    <Reference Include=\"System.Core\" />" + nl +
"    <Reference Include=\"System.Data\" />" + nl +
"    <Reference Include=\"System.Data.DataSetExtensions\" />" + nl +
"    <Reference Include=\"System.Drawing, Version=2.0.0.0, Culture=neutral," +
" PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL\" />" + nl +
"    <Reference Include=\"System.Windows.Forms, Version=2.0.0.0, " +
"Culture=neutral, PublicKeyToken=b77a5c561934e089, " +
"processorArchitecture=MSIL\" />" + nl +
"    <Reference Include=\"System.Xml\" />" + nl +
"    <Reference Include=\"System.Xml.Linq\" />" + nl +
"  </ItemGroup>" + nl +
"  <ItemGroup>");
            
            foreach (Type c in Comp.All_classes)
            {
                o.Add("    <Compile Include=\"" + c.Final_name + ".cs\" />");
            }
            foreach (string s in Comp.Copy_files)
            {
                o.Add("    <Compile Include=\"" + Path.GetFileName(s) + "\" />");
            }
            o.Add("    <Compile Include=\"AL4.cs\" />" + nl +
"  </ItemGroup>" + nl +
"  <ItemGroup>" + nl +
"    <None Include=\"app.config\" />" + nl +
"  </ItemGroup>" + nl +
"  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSHARP.Targets\" />" + nl +
"  <ProjectExtensions>" + nl +
"    <VisualStudio AllowExistingFolder=\"true\" />" + nl +
"  </ProjectExtensions>" + nl +
"</Project>");
            Text_file tf = new Text_file(StringFunctions.Trailing_slash(Comp.Destination) + 
                       Comp.Project_name + ".csproj");
            tf.Save_strings(o);
            o.Clear();
            tf.Path = System_functions.Start_dir() + "AL4.cs";
            tf.Load_strings(o);
            for (int i = 0; i < o.Count; i++)
            {
                if (o[i].Trim() == "/" + "/#localize")
                {
                    add_localize_data(i);
                    break;
                }
            }
            tf.Path = StringFunctions.Trailing_slash(Comp.Destination) + "AL4.cs";
            tf.Save_strings(o);
            o.Clear();
            //---------------------- 'app.config'
            o.Add("<?xml version=\"1.0\"?>" + nl +
                  "<configuration>" + nl +
                  "<startup><supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.0\"/></startup></configuration>");
            tf.Path = StringFunctions.Trailing_slash(Comp.Destination) + "app.config";
            tf.Save_strings(o);
            o.Clear();
        }
        
        //" - just to balance quotas for Notepad++
        /*
        INT tcl|_test_counter_lines[]

        METHOD generate_class(
        	{Type} Class|_to_generate) ==> BOOL
        	:
            ---------------------------------- 'module class header'
            total_gen_field = (total_gen_field + 99)
            total_gen_field -= total_gen_field % 100
            Comp.Current_class = Class
            tcl[].Clear
            
            ---------------------------------- 'option /INT32'
            CASE Comp.Int32 ? 
                 o[] << "#define i_32" << "" ;
            ---------------------------------- '#define DIAGNOSTICS'
            CASE Comp.Diagnostics ? 
                 o[] << "" << "#define DIAGNOSTICS"
                 CASE Comp.Diagnostics_light ? 
                      o[] << "#define DIAGNOSTICS_LIGHT" ;
            ;
                 
            o[] << @"using System;"
                "using System.Collections.Generic;"
                "using System.Linq;"
                "using System.Text;"
                "using AL4;"
                     
            CASE Comp.Debugging ?
                 o[] << "using System.Runtime.InteropServices;" ;
                 
            CASE use_profiler != "" ? o[] << "using System.IO;" ;
                
            ---------------------------------- 'root native code'
            FOR f IN Class.Method[] :
                CASE f == NONE ? CONTINUE f ;
                CASE f.Final_name == "-" ?
                     CASE Starting(f.Native_code, "using") ?
                          o[] << f.Native_code ;
                ELSE BREAK f ;
            ;            
            ---------------------------------- 'main part of class'
            o[] << "" << "namespace AL4_project"
            CASE Comp.TEST_value ? o[*] = o[*] " //Test" ;
            o[] << "{"
            ----------------------------- 'Methods of class in a separate class'
            o[] << "    public class Methods_" Class.Final_name ": Methods_"
            CASE Class.Base_ == NONE ? o[*] = o[*] "AL4_object"
            ELSE o[*] = o[*] Class.Base_.Final_name ;
            o[] << "    {"
            CASE Class.Base_ != NONE ? STR new|_prefix = "new " ;
            
            STR cfn|_Class_final_name = Class.Final_name
            
            o[] <<@"        public " new cfn " THIS {"
                   "              get {"
                   "//---------------- todo: is it possible to avoid this if ?"     
                   "				  if (This_obj==null)"
                   "						return " cfn ".NoneObj_" cfn ";" 
                   "                  return (" Class.Final_name ")This_obj;"
                   "              }" 
                   "          }"
                   
            o[] << "        public Methods_" Class.Final_name 
                   "(" Class.Final_name " obj_this) "
                   "{ This_obj = obj_this; }" 
                        
            o[] << "        public Methods_" Class.Final_name 
                   "() { }" << ""
            ------------------- 'trap methods only'
            FOR v IN Class.Field[] :
                CASE !Comp.Debugging && !Comp.TEST_value ? BREAK v ;
                CASE !v.Modifiers['TRAP'] ? CONTINUE v ;
                CASE v.Trap_read_ != NONE ?
                     implementation_of_trap(v, TRUE) ;
                CASE v.Trap_write_ != NONE ?
                     implementation_of_trap(v, FALSE) ;
            ;
            ------------------- 'non-static methods only'
            BOOL root_outer|_code = TRUE
            FOR f IN Class.Method[] :
                CASE f == NONE ? CONTINUE f ;
                CASE f.Final_name == "-" && root_outer ?
					 CONTINUE f ;
                root_outer = FALSE
                CASE f.Modifiers['STATIC'] ? CONTINUE f ;
                CASE f.Overloaded_[].Count > 0 ? CONTINUE f ;
                generate_method(f) ;
            o[] << "    }"
            ------------------------------------------ 'Class itself now'
            o[] << "    public "
            o[*] = o[*] "class " Class.Final_name
            CASE Class.Base_ == NONE ? o[*] = o[*] ": AL4_object"
            ELSE o[*] = o[*] ":" Class.Base_.Final_name ;
            o[] << "    {"
            o[] << "        public static int " 
               	   " First_localize_item_" Class.Final_name  " = "
               	        
            o[*] = o[*] Class.Localize_1st_item.Str ";"
            
            ---------------------------------- 'RTTI'
            CASE class_present("{RTTI}") ?
                 o[] << sp(8) "public override int RTTI_object_type() {"
                 
                 o[] << sp(12) "return " (Comp.All_classes[].Find(Class)+7).Str
                 		";"
                 		
                 o[] << sp(8) "}" << ""
                 generate_RTTI_methods(Class)
            ;
    		//DEBUG: o[] << "//1@#$%^&*()_"#NL ;
            ---------------------------------- 'root native code'
            FOR f IN Class.Method[] :
                CASE f == NONE ? CONTINUE f ;
                CASE f.Final_name == "-" ?
                     CASE !Starting(f.Native_code, "using") ?
                          o[] << f.Native_code ;
                ELSE BREAK f ;
            ;                                              
    		//DEBUG: o[] << "//2@#$%^&*()_"#NL ;
            generate_ref(Class)
    		//DEBUG: o[] << "//3@#$%^&*()_"#NL ;
            generate_NONE(Class)
    		//DEBUG: o[] << "//4@#$%^&*()_"#NL ;
            CASE Class == Comp.All_classes[0] ?
                generate_main(Class) ;
            --------------------------------- 'enums'
            FOR e IN Class.Enums_[] :
                generate_enum(e) ;
            --------------------------------- 'structures'
            FOR obj IN Class.Structures_[] :
                generate_structure_decl(obj) ;
            --------------------------------- 'fields'
            FOR v IN Class.Field[] :
                generate_field(v) ;
            --------------------------------- 'constant arrays'
            FOR c IN Class.Constants[] :
                CASE !c.Is_array ? CONTINUE c ;
                generate_constant_array(c) ;
            --------------------------------- 'methods'
            o[] << @
                "" sp(8) "public " new "Methods_" Class.Final_name " Do"
                "" sp(8) "{"
                "" sp(8) "    get { return (Methods_" Class.Final_name ")DO; }"
                "" sp(8) "}"
                "" sp(8) "public " Class.Final_name "() {" 
                "" sp(8) "   DO = new Methods_" Class.Final_name "(this);"
                "" sp(8) "}"
                ""
            ----------------------- 'only static methods'
            root_outer = TRUE
            FOR f IN Class.Method[] :
                CASE f == NONE ? CONTINUE f ;
                CASE f.Final_name == "-" && root_outer ?
					 CONTINUE f ;
                root_outer = FALSE
                CASE f.Overloaded_[].Count > 0 ? CONTINUE f ;
                CASE f.Modifiers['STATIC'] ?
                     //DEBUG : CASE f.Final_name == "" ?
                     //              Console_color('WHITE') 
                     //              << "final name is not defined for function "
                     //              "#" f.Total_fn.Str
                     //              "" f.Whole_name #NL
                     //              Console_color('SILVER') ;
                     //;
                     generate_method(f) ;
            ;
            --------------------------------- 'tests'
            CASE Comp.TEST_value ? 
                 FOR t IN Class.Test[] :
                     CASE t.Param[].Count == 0 ?
                          BOOL has_tests|_without_parameters = TRUE ;
                     generate_method(t) ;
                 o[] << #NL "public static "
                 CASE Class.Base_ != NONE ? o[*] = o[*] "new " ;
                 o[*] = o[*] "void Do_tests() {"
                 
                 o[] << sp(4) "AL4_system.Clear_test_data(test_lines" 
                        "_" Class.Final_name
                        ", init_test_lines_" Class.Final_name ");"
                        
                 CASE Class.Base_.Modifiers['ABSTRACT'] ?
                      o[] << sp(4) "AL4_system.Clear_test_data("
                      "" Class.Base_.Final_name ".test_lines"
                      "_" Class.Base_.Final_name ", "
                      "" Class.Base_.Final_name
                      ".init_test_lines_" Class.Base_.Final_name ");"
                      FOR f IN Class.Method[] :
                          CASE f == NONE ? CONTINUE f ;
                          remove_overridden_method_lines_from_tests_of_base(f) ;
                 ;
                 FOR t IN Class.Test[] :
                     CASE !Class_needs_testing(Class) ? BREAK t ; 
                     CASE t.Param[].Count != 0 ? CONTINUE t ;
                     o[] << sp(4) t.Final_name "();" ;
                 CASE Comp.Verbose && has_tests ?
                      o[] << "    AL4_system.WriteLine(@" #QU
                             "Saving test data: "
                             "" Comp.Destination.Trailing_slash
                             "" Class.Final_name ".test" #QU ");"
                      //o[] << "    Console.ReadLine();"
                 ;
                 CASE has_tests ?
                      o[] << sp(4) "AL4_system.Output_test_data(test_lines"
                      "_" Class.Final_name 
                      ", test_assert_" Class.Final_name
                      ", test_assert_failed_text_" Class.Final_name
                      ", @" #QU Comp.Destination.Trailing_slash 
                      "" Class.Final_name ".test" #QU 
                      ", @" #QU Class.Path #QU ");"
                      CASE Class.Base_.Modifiers['ABSTRACT'] ?
                           o[] << sp(4) "AL4_system.Output_test_data("
                           "" Class.Base_.Final_name ".test_lines"
                           "_" Class.Base_.Final_name ", "
                           "" Class.Base_.Final_name ".test_assert"
                           "_" Class.Base_.Final_name 
                           ", " Class.Base_.Final_name 
                           ".test_assert_failed_text_" Class.Base_.Final_name 
                           ", @" #QU Comp.Destination.Trailing_slash 
                           "" Class.Final_name 
                           "." Class.Base_.Final_name ".test" #QU 
                           ", @" #QU Class.Base_.Path #QU ");" ;
                 ;
                 o[] << "}"
                 ---------------------------- 'counters array'
                 o[] << "" << "public static long[] test_lines"
                     "_" Class.Final_name " = new long[" tcl[].Count.Str "];"
                     
                 o[] << "" << "public static long[] init_test_lines"
                     "_" Class.Final_name " = new long[]{"
                     
                 FOR line IN tcl[] :
                     CASE line >= 0 ?
                          Class.Total_lines_in_test = line.Index + 1 ;
                     o[*] = o[*] line.Str ","
                     CASE o[*].Len >= 80 ? o[] << "" ;
                 ;
                 o[] << "-1 };"
                 ---------------------------- 'assertions list'
                 o[] << "" << "public static List<int> test_assert"
                        "_" Class.Final_name " = null;" <<
                        "public static List<string> test_assert_failed_text"
                        "_" Class.Final_name " = null;"
            ;
            CASE use_profiler != "" ? 
                 o[] << "" 
                 o[] << "      public static void "
                 o[*] = o[*] "Collect_cnt(List<string> all_cnts)"
                 o[] << "      {"
                 -------------------------------------- 'class name'
                 STR c_w|hole_name = Class.Whole_name 
                 	 c_w = c_w " " Class.Path
                 o[] << sp(8) "all_cnts.Add("#QU#QU");"
                 o[] << sp(8) "all_cnts.Add(@"#QU c_w #QU");"
                 BOOL static_methods = TRUE
                 FOR i IN [o[].Count-1 DOWNTO 0] :
                     STR s|tring_at_i = o[i].TrimL
                     //CASE !Starting(s,"if (++CNT_") && !Starti	ng(s,"++CNT_") ?
                     CASE !Starting(s,"if (AL4_system.inc_cnt(ref CNT_") 
                          && !Starting(s,"AL4_system.inc_cnt(ref CNT_")
                          ?
                          CASE Starting(s,"public class C_") ? 
                               static_methods = FALSE ;
                     	  CONTINUE i ;
                     //DEBUG: o[] << "//s=" s #NL ;
                     ---------------------------- 'extract CNT_xxx'
                     s = s.[s.Find("ref") + 3 TO *].Trim
                     s = s.starting_ident
                     ------------------- 'create line a in all_cnts.Add(a)'
                     STR a|dding_line = #QU 
                     a = a s ":" #QU " + "
                     CASE !static_methods ? STR w|hat_cnt = "Methods_" 
                     ELSE w = "" ;
                     w = w Class.Final_name "." s
                     a = a w ".ToString()"
                     ----------------------------------- 'add it finally'
                     o[] << sp(8) "all_cnts.Add(" a ");"
                     ---------------------- 'and reset'
                     o[] << sp(8) w " = 0;"
                 ;
                 o[] << "      }" 
            ;
            o[] << "    }" << ""
            --------------------------------- 'split by #NL'
            split_o_by_NL
            --------------------------- 'comment portions of code by conditions'
            comment_unnecessary_parts(o[])
            ----------------------------- 'generate Noneclass_ ?'
            generate_Noneclass(Class)
            o[] <<  "}"                                      
            RESULT = Comp.Errors_count == 0 .
            
FUNCTION starting_ident(STR S|ource_string) ==> STR :
	FOR i IN [0 TO S.Len] :
		CASE !S.[i].Lower.is_letter_digit_underline ? 
		     RESULT = S.[0 TO i-1] ==> ;
	; .            
            
METHOD implementation_of_trap(
	{Var} F|eild_trapping,
	BOOL Read|_trap)
	:
	STR t|ype_name_final = F.Type_.Final_name
	CASE Read ?
	     o[] << "public " t " Trap_read_" F.Final_name "("
	     CASE F.Is_array ? o[*] = o[*] "int Index" ;
	     o[*] = o[*] ")"
	ELSE o[] << "public void Trap_write_" F.Final_name "("
		 CASE F.Is_array ? o[*] = o[*] "int Index, " ;
		 CASE F.Type_.Kind == 'STRUCTURE' ?
		      o[*] = o[*] F.Type_.In_class_.Final_name "." ;
		 CASE F.Type_.Kind == 'CLASS' ?
		      o[*] = o[*] "Ref_obj Value)"
		 ELSE o[*] = o[*] t " Value)" ;
	;
	o[] << "{"
	CASE Read ?
	     o[] << sp(4)  F.Trap_read_.Final_name "("
	     CASE F.Is_array ? o[*] = o[*] "Index" ;
	     o[*] = o[*] ");"
	     o[] << sp(4) "return "
	     CASE !Comp.Int32 && t == "int" ? o[*] = o[*] "(int)" ;
	     o[*] = o[*] "(THIS." F.Final_name ")" 
	     CASE F.Is_array ?
	          CASE F.Type_.Kind ?
	          ['STR']: o[*] = o[*] ".get_str"
	          ['BOOL']: o[*] = o[*] ".get_bool"
	          ['ENUM']: o[*] = o[*] ".get_byte"
	          ['INT']: o[*] = o[*] ".get_int"
	          ['CLASS', 'STRUCTURE']: o[*] = o[*] ".get_obj"
	          ['REAL']: o[*] = o[*] ".get_real" ;
	          o[*] = o[*] "(Index)"
	     ;
	     o[*] = o[*] ";"
	ELSE o[] << sp(4) F.Trap_write_.Final_name "("
		 CASE F.Is_array ? o[*] = o[*] "Index, " ;
		 o[*] = o[*] "Value"
		 o[*] = o[*] ");"
		 ---------------- 'now assignment trapped'
		 CASE F.Type_.Kind IN ['CLASS', 'STRUCTURE'] && !F.Is_array ? 
		      o[] << sp(4) "AL4_object.Object_assign_"
		      CASE F.Is_weak ? o[*] = o[*] "weak"
		      ELSE o[*] = o[*] "hard" ;
		      o[*] = o[*] "(ref THIS." F.Final_name ", Value.Obj);"
		 ELSE
			  o[] << sp(4) "THIS." F.Final_name
			  CASE F.Is_array ? o[*] = o[*] "[Index]" ; 
			  o[*] = o[*] " = Value"
			  o[*] = o[*] ";" ;
	;
	o[] << "}" << "" .
            
        METHOD remove_overridden_method_lines_from_tests_of_base(
            {Fun} F|unction)
            :
            {Fun} a|ncsector_method = F.Ancestor_
            CASE a == NONE || a.Class != F.Class.Base_ ? ==> ;
            STR a_w|hole_name = a.Whole_name
            ----------------------------------------------- '1'
            o[] << sp(4) "//--- remove ancestor method " a_w
            STR b_w|hole_name = F.Class.Base_.Whole_name 
            o[*] = o[*] " from test data of class " b_w
            STR f_w|hole_name = F.Whole_name
            o[*] = o[*] " (method " f_w ")"
            ----------------------------------------------- '2'
            o[] << sp(4) "AL4_system.Remove_test_data(" F.Class.Base_.Final_name
            o[*] = o[*] ".test_lines_" F.Class.Base_.Final_name 
            o[*] = o[*] ", " a.Line_start.Str ", " a.Line_end.Str ");" .


   		FUN array_type({Type} Type|_of_array) ==> STR :
   			CASE Type.Kind ?
            ['BOOL']:  STR nam|e_type = "Bool"
            ['ENUM']:  nam = "Byte"
            ['INT']:   nam = "Int"
            ['STR']:   nam = "Str"
            ['REAL']:  nam = "Real"
            ['CLASS', 'STRUCTURE']: nam = "Obj" ;
            RESULT = nam .
            
		FUN clamp_array({Var} Field|_may_be_clamp) ==> STR :
			CASE !Field.Modifiers['CLAMP'] ? ==> ;
			RESULT = "_clamp" .
            
        METHOD calculate_size_value(
        STR S|tring_value ) ==> INT
    	:
            CASE S.[0] == "{" ?
                 {Type} enum|eration = Comp.Current_class.Find_type(S)
                 CASE enum == NONE ?
                      Comp.Error("Enumeration type was not found"._Eenum 
                      ": " S)
                 ;
                 CASE enum.Kind != 'ENUM' ?
                      Comp.Error("Type is not a enumeration"._Etype ": " S) ;
                 RESULT = enum.Items[].Count ==> ;
            RESULT = int_from_str(S)
            CASE RESULT <= 0 ?
                 Comp.Error("Array size value must be greater "
                 "then 0"._Earray) ; .            
                 
        FUNCTION int_from_str( STR S|tring_only_digits ) ==> INT :
            FOR i IN [0 TO S.Len-1] :
                CASE S.[i] IN "0123456789" ?
                     RESULT = RESULT * 10 + S.[i].Ord - "0".Ord
                ELSE ==> ;
            ; .
                         
        METHOD split_o_by_NL :
            FOR i IN [o[].Count-1 DOWNTO 0] :
                STR prev|ios_line_of_o = o[i]
                CASE #NL !IN prev ? CONTINUE i ;
                STR splitted[]
                Split(splitted[], prev, #NL)
                o[].Delete(i)
                FOR s IN splitted[] :
                    o[].Insert(i + s.Index, s) ;
            ; .
            
            
        METHOD comment_unnecessary_parts( STR Lines|_of_code[] ) :
            STR comment|ing_lines = ""
            FOR s IN Lines[] :
                CASE Starting(s, "//?") ?
                     STR w|ords_splitted[]
                     Split(w[], s.[3 TO *], ".")
                     STR nclass|_name = w[0].Trim
                     CASE !class_present(nclass) ?
                          comment = comment "."
                          CONTINUE s
                     ;
                     CASE w[].Count <= 1 ? CONTINUE s ;
                     //DEBUG: << "+++++++++++++++++++++++++++++++++++++++++"#NL
                     //"check if method " w[1] " is overridden in descendants"
                     //" of class " w[0] #NL ;
                     -------------------------- '/ / ? {class}.event'
                     STR m|ethod_to_check_if_overridden = w[1].Trim
                     STR b|ase_class_to_check_descendants_of = w[0].Trim
                     w[].Delete(1)
                     w[].Delete(0)
                     CASE !Comp.Overridden(m, b, w[]) ?
                          comment = comment "." ;
                     CONTINUE s ;
                CASE comment != "" ?
                     CASE Starting(s, "//.") && s.Trim == "//." ?
                          comment = comment.[0 TO *-1]
                     ELSE Lines[s.Index] = "//-->" s ;
                     CONTINUE s ;
            ; .

        METHOD class_present|_in_All_classes(
        	STR Name|_of_class ) ==> BOOL
        	:
            FOR t IN Comp.All_classes[] :
                CASE Name == t.Names[0] ? RESULT = TRUE ==> ;
            ; .
            
        METHOD generate_structure_decl(
        {Type} Obj|ect_type)
        	:
            o[] << sp(4) "public class " Obj.Final_name " : Structure_any"
        	o[] << sp(4) "{"
        	--------------------------------- 'constructor of record'
        	o[] << sp(8) "public " Obj.Final_name "() {"
        	init_object_arrays(o[], Obj, sp(12))
            o[] << sp(8) "}"
            FOR f IN Obj.Field[] :
                o[] << sp(8) "public "
                CASE f.Is_fixed ?
                     CASE f.Size_value == 0 ?
                     	  f.Size_value = calculate_size_value(f.Size_n) ;
                     	  
                     o[*] = o[*] "FixA" array_type(f.Type_) 
                     		 "" clamp_array(f) " " f.Final_name
                     		 "; // size array: " f.Size_value.Str
                     		 
                ELSE o[*] = o[*] var_type_gen(f) " " f.Final_name ";" ;
            ;
            ------------------------ 'Clone overridden'
            o[] << sp(8) "public override Ref_obj Clone() {"
            o[] << sp(12) Obj.Final_name " result = new " Obj.Final_name "();"
            o[] << sp(12) "result.hard_link = new Ref_obj(result, 1);"
            o[] << sp(12) "result.weak_link = new Ref_obj(result, 1);"
            o[] << sp(12) "result.Write = result;"
            o[] << sp(12) "//------------------- fields:"
            ------------------------ 'assign fields'
            FOR f IN Obj.Field[] :
                CASE f.Is_array ?
                	 o[] << sp(12) "result." f.Final_name 
                	 		" = (" type_gen(f.Type_,
                	 		"A" F_if(f.Is_fixed) W_if(f.Is_weak))
                	 CASE f.Modifiers['CLAMP'] ? o[*] = o[*] "_clamp" ;
                	 o[*] = o[*] ")" f.Final_name
                	 CASE f.Type_.Kind == 'STRUCTURE' ? 
                	 	  o[*] = o[*] ".Clone_struct_array();"
                	 ELSE o[*] = o[*] ".Clone_array();" ;
                	 CONTINUE f ;
            	CASE f.Type_.Kind ?
            	['BOOL', 'ENUM', 'INT', 'REAL', 'STR']:
                	o[] << sp(12) "result." f.Final_name " = " f.Final_name ";"
                	
            	['CLASS']:
                	o[] << sp(12) "result." f.Final_name " = "
                		"((" f.Type_.Final_name ")" f.Final_name 
                		".Obj).NONE_obj_instance();"
                		
            		CASE f.Is_weak ?
                		 o[] << sp(12) "Object_assign_weak("
            		ELSE o[] << sp(12) "Object_assign_hard(" ;
            		o[*] = o[*] "ref result." f.Final_name ", " f.Final_name ".Obj);"
            		
            	['STRUCTURE']:
                	o[] << sp(12) "result." f.Final_name " = "
                		   "((Structure_any)" f.Final_name ".Obj).Clone();"
            	;
            ;
            o[] << sp(12) "return result.hard_link;"
            o[] << sp(8) "}"
			generate_ref(Obj)
            generate_NONE(Obj)
            o[] << sp(4) "}" << "" .
            
        METHOD init_object_arrays|_and_strings(
        	STR Out|put_strings[], {Type} Obj|ect_type,
            STR Prefix|_before_field_name)
            :
            FOR f IN Obj.Field[] :
                CASE ?
                [f.Is_fixed] ?
					 CASE f.Size_value == 0 ?
                     	  f.Size_value = calculate_size_value(f.Size_n) ;
					 STR nam|e_type = array_type(f.Type_)
					 
                     Out[] << Prefix f.Final_name 
                     		  " = new FixA" nam clamp_array(f) 
                     		  "(" f.Size_value.Str ");"
                     		  
                     CONTINUE f
                [f.Is_array] ?
                	 nam = array_type(f.Type_)
                	 //DEBUG: Out[] << Prefix "// init object array:" ;
                	 CASE ?
                	 [f.Type_.Kind == 'STRUCTURE'] ?
                	 	Out[] << Prefix f.Final_name 
                	 		" = DynAObjHard.new_DynAStruct("
                	 		"" f.Type_.In_class_.Final_name 
                	 		"." f.Type_.Final_name 
                	 		".NoneObj_" f.Type_.Final_name ".hard_link"
                	 		");"
                	 		     
                	 	CONTINUE f
                	      
                	 [f.Type_.Kind IN ['CLASS'] && f.Is_weak] ?
                	    nam = nam "Weak"
                	      
                	 [f.Type_.Kind IN ['CLASS']] ?
                	    nam = nam "Hard"
                	      
                	 ELSE 
                	 	Out[] << Prefix f.Final_name " = new DynA" nam "();"
                	 	CONTINUE f
                	 ;
                	 Out[] << Prefix f.Final_name " = new DynA" nam "("
                	 CASE f.Type_.Kind == 'STRUCTURE' ?
                	      Out[*] = Out[*] f.Type_.In_class_.Final_name "." ;
                	      
                	 Out[*] = Out[*] f.Type_.Final_name 
                	 		  ".NoneObj_" f.Type_.Final_name ".hard_link"
                	 		  
                	 Out[*] = Out[*] ");"
                [f.Type_.Kind == 'STR'] ?
                     Out[] << Prefix f.Final_name " = " #QU#QU ";"
                ;
            ; .
                        
        */
        private List<int> tcl = new List<int>();

        private bool generate_class(Type Class)
        {
            Comp.Current_class = Class;
            tcl.Clear();
            o.Add("using System;\r\n" +
                "using System.Collections.Generic;\r\n" +
                "using System.Linq;\r\n" +
                "using System.Text;\r\n" +
                "using AL4;");
            //--------------------------------- 'root native code'
            foreach  (Function f in Class.Method)
            {
                if (f.Final_name == "-")
                    o.Add(f.Native_code);
                else break;
            }
            //---------------------------------- 'main part of class'
            o.Add("namespace AL4_project");
            if (Comp.Test()) o[o.Count - 1] += "//_Test";
            o.Add("{\r\n" +
                "    public class " + Class.Final_name);
            if (Class.Base_ == null) o[o.Count-1] += ": AL4_object";
            else o[o.Count-1] += ":" + Class.Base_.Final_name;
            o.Add("    {");
            generate_ref(Class);
            generate_NONE(Class);
            if (Class == Comp.All_classes[0])
                generate_main(Class);
            //-------------------------------- 'enums'
            foreach (Type e in Class.Enums_)
                generate_enum(e);
            //-------------------------------- 'fields'
            foreach (Variable v in Class.Field)
                generate_field(v);
            //-------------------------------- 'methods'
            bool root_outer = true;
            foreach (Function f in Class.Method)
            {
                if (f.Final_name == "-" && root_outer) continue;
                root_outer = false;
                generate_method(f);
            }
            //-------------------------------- 'tests'
            if (Comp.Test())
            {
                foreach (Function t in Class.Test)
                    generate_method(t);
                o.Add("\r\npublic static ");
                if (Class.Base_ != null) o[o.Count - 1] += "new ";
                o[o.Count-1] += "void Do_tests() {";
                //generate_init_classes();
                o.Add(sp(4) + "AL4_system.Clear_test_data(test_lines);");
                foreach (Function t in Class.Test)
                    o.Add(sp(4) + t.Final_name + "();");
                if (Comp.Verbose)
                {
                    o.Add("    Console.WriteLine(@\"Saving test data: " +
                        StringFunctions.Trailing_slash(Comp.Destination) +
                        Class.Final_name + ".test\");");
                    //o.Add("    Console.ReadLine();");
                }
                o.Add(sp(4) + "AL4_system.Output_test_data(test_lines, test_assert, " +
                    "@\"" + StringFunctions.Trailing_slash(Comp.Destination) +
                    Class.Final_name + ".test\");");
                o.Add("}");
                //---------------------------- 'counters array'
                o.Add("");
                o.Add("private static long[] test_lines = new long[]{");
                foreach (int line in tcl)
                {
                    o[o.Count - 1] += line.ToString() + ",";
                    if (o[o.Count - 1].Length >= 80)
                        o.Add("");
                }
                o.Add("-1 };");
                o.Add("");
                //---------------------------- 'assertions list'
                o.Add("private static List<int> test_assert = null;");
            }
            o.Add("    }\r\n");
            generate_Noneclass(Class);
            o.Add("}");
            bool Result = Comp.Errors_count == 0;
            return Result;
        }

        /*
        
        FUN sp|aces_sequence(INT Count|_spaces) ==> STR :
            RESULT = Sp(Count) .
        */
        private static string sp(int count)
        {
            return Parser.Sp(count);
        }

        /*
        
        METHOD generate_ref({Type} Class|_to_generate) :
            STR n|ame_of_class = Class.Final_name
                STR new|_keyword_add = "new "
                
            o[] << @"" sp(8) "public " new n " Write"
            "" get_set_link("write", n)
            ""
            
            generate_New(Class, Class.Final_name)
            
            o[] << @""                                                           
            "" sp(8) "public static " new "Ref_obj New_owned(Ref_obj owner)"
            "" sp(8) "{"                                                 
            "" sp(8) "    Ref_obj Result = New();"
            "" sp(8) "    Result.Obj.Owned_by(owner);"  
            "" sp(8) "    return Result;"                      
            "" sp(8) "}"                                                 
            "" .
        */
        private void generate_ref(Type Class)
        {
            string n = Class.Final_name;
            string new_ = "";
            if (Class.Base_ != null)
                new_ = "new ";
            o.Add(sp(8) + "public " + new_ + n + " Write" + 
                get_set_link("write", n));
            generate_New(Class, Class.Final_name);
            o.Add("");
            o.Add(sp(8) + "public static " + new_ + "Ref_obj New_owned(Ref_obj owner)");
            o.Add(sp(8) + obr);
            o.Add(sp(8) + "    Ref_obj Result = New();");
            o.Add(sp(8) + "    Result.Obj.Owned_by(owner);");
            o.Add(sp(8) + "    return Result;");
            o.Add(sp(8) + cbr);
            o.Add("");
        }

        /*
        
        METHOD generate_New(
            {Type} Class|_to_generate_New,
            STR N|ame_of_class)
            :
            -------------------------------------- 'New() { ... }'
            STR new|_instance = "new "
                 
            o[] << @"" sp(8) "public static " new "	Ref_obj New()"                     
                    "" sp(8) "{"                                                 
                    "" sp(8) "    " N " Result = new " N "();"   
                         
            CASE Class.Kind != 'STRUCTURE' ? 
                 o[] << sp(8) "    Result.hard_link = new Ref_obj(Result, 0);"
            ELSE o[] << sp(8) "    Result.hard_link = new Ref_obj(Result, 1);"
            ;
            o[] << @"" sp(8) "    Result.weak_link = new Ref_obj(Result, 1);"
                    "" sp(8) "    Result.Write = Result;"
                         
            CASE Class.Kind != 'STRUCTURE' ? 
             o[] << "" sp(8) "    Result.Do.This_obj = Result.weak_link.Obj;"
            ;
                    
            CASE N.Find("Noneclass_") < 0 ?
                 o[] << "" sp(12) "Do_init_fields_simple(Result);"
                 o[] << "" sp(12) "Do_init_fields_not_simple(Result);"
                 BOOL want_init_fields = TRUE ;
            gen_create_base(Class)
            
            o[] << @""
                    "" sp(8) "    return Result.hard_link;"
                    "" sp(8) "}"
                    ""
            ------------------------------------ 'Do_init_fields'
            CASE want_init_fields ?
                o[] << "" sp(8) "public static void Do_init_fields_simple(" N 
                       " Result)" << "" sp(8) "{"
                            
                STR text|_gen_init_fields = gen_init_fields(Class, FALSE, TRUE) 
                o[] << text #NL
                o[] << sp(8) "}" << ""
                ---------------------- 'not simple' 
                o[] << "" sp(8) "public static void Do_init_fields_not_simple(" 
                	   "" N " Result)" << "" sp(8) "{"
                            
                text = gen_init_fields(Class, FALSE, FALSE) 
                o[] << text #NL
                o[] << sp(8) "}" << "" 
            ;
            ------------------------------------ 'New_nofields'
            o[] << @"" sp(8) "public static " new "Ref_obj New_nofields()"                     
                    "" sp(8) "{"                                                 
                    "" sp(8) "    " N " Result = new " N "();"   
                         
            CASE Class.Kind != 'STRUCTURE' ? 
                 o[] << sp(8) "    Result.hard_link = new Ref_obj(Result, 2);"
            ELSE o[] << sp(8) "    Result.hard_link = new Ref_obj(Result, 1);"
            ;
            o[] << @"" sp(8) "    Result.weak_link = new Ref_obj(Result, 1);"
                    "" sp(8) "    Result.Write = Result;"
                         
            CASE Class.Kind != 'STRUCTURE' ?
             o[] << "" sp(8) "    Result.Do.This_obj = Result.weak_link.Obj;"
            ;
            o[] <<  "" sp(8) "    return Result.hard_link;"
                    "" sp(8) "}"
                    ""
            .
        */
        private void generate_New(Type Class, string n)
        {
            string new_ = "";
            if (Class.Base_ != null || n.IndexOf("Noneclass_") == 0)
                new_ = "new ";
            o.Add(
                sp(8) + "public static " + new_ + "Ref_obj New()\r\n" +
                sp(8) + "{\r\n" +
                sp(8) + "    " + n + " Result = new " + n + "();\r\n" +
                sp(8) + "    Result.hard_link = new Ref_obj(Result, 2);\r\n" +
                sp(8) + "    Result.weak_link = new Ref_obj(Result, 1);\r\n" +
                sp(8) + "    Result.Write = Result;\r\n");
            if (n.IndexOf("Noneclass_") < 0)
                o.Add(gen_init_fields(Class, false) + "\r\n");
            gen_create_base(Class);
            o.Add("\r\n" + sp(8) + "    return Result.hard_link;\r\n" +
                sp(8) + "}");
        }

        /*
        
        METHOD gen_create_base(
        	{Type} Class|_to_generate), RECURSIVE
        	:
            CASE Class.Kind == 'CLASS' && Class.Base_ != NONE ?
                 gen_create_base(Class.Base_) ;
            INT from|_line = o[].Count
            PUSH new_init = Class.Create_base.Source :
                 CASE new_init == NONE ? ==> ;
                 o[] << sp(12) "// init base: " Class.Whole_name
                 tfun|ction_temp = {Fun}(Parse = Class.Parse, A_Name_1 = "")
                 
                 r|esult_def_temp = {Assign}(Line = 0, Function_ = tfun,
                 	Level = 0,
                    Dest = {Expr}(Operation = 'VAR', Var_arg = {Var}(Line = 0,
                            Type_ = Class)))
                            
                 r.Dest.Var_arg.Set_final_name("Result")
                 o[] << gen_init_new_obj(r) ;
            FOR line IN [from TO o[].Count-1] :
                STR s|tring_line = o[line]
                CASE s.[0 TO 1] == "//" ? CONTINUE line ;
                INT dot|_position = s.Find(".write).")
                CASE dot > 0 ?
                     o[line] = sp(12) "Result" s.[dot+7 TO *] ;
            ; .
        */
        private void gen_create_base(Type Class)
        {
            if (Class.Base_ != null)
                gen_create_base(Class.Base_);
            Expression save_new_init = new_init;
            if (Class.Create_base == null) return;
            int from = o.Count;
            o.Add(sp(12) + "// init base: " + Class.Name());
            new_init = Class.Create_base.Source;
            {
                Assignment r = new Assignment();
                {
                    r.Dest = new Expression();
                    {
                        r.Dest.Operation = Expression.Operation_kind.VAR;
                        r.Dest.Var_arg = new Variable(Comp);
                        {
                            r.Dest.Var_arg.Type_ = Class;
                            r.Dest.Var_arg.Final_name = "Result";
                        }
                    }

                }
                gen_init_new_obj(r);
            }
            new_init = save_new_init;
            for (int line = from; line < o.Count; line++)
            {
                string s = o[line];
                if (s.Substring(0, 2) == "//") continue;
                int dot = s.IndexOf(".write).");
                if (dot > 0) o[line] = sp(12) + "Result" + s.Substring(dot + 7);
            }
        }

        /*
        INT total_init_fld

        METHOD gen_init_fields(
            {Type} Class|_to_generate_fields,
            BOOL Non|e_instance_initializing,
            BOOL Simple|_fields_only) ==> STR, RECURSIVE
            :
	        --------------- '1st initialize fields of base class'
            CASE Class.Base_ != NONE ?
                RESULT = gen_init_fields(Class.Base_, FALSE, Simple) #NL RESULT 
            ; 
            ----------------------------------------------- 'initialize fields'
            FOR f IN Class.Field[] :
            	CASE ?
            	[Simple && (f.Is_array 
            	 || f.Type_.Kind IN ['STRUCTURE', 'CLASS'])] ? CONTINUE f
            	[!Simple && !(f.Is_array 
            	 || f.Type_.Kind IN ['STRUCTURE', 'CLASS'])] ? CONTINUE f
            	;
                CASE f.Final_name == "DATA" ? CONTINUE f ;
                
                STR s|tring_to_add = #NL sp(12) 
                    "// init fld: " total_init_fld.Str #NL
                    "" sp(12) "Result." f.Final_name " = "
                    
                CASE total_init_fld == 60 ? NONE ;
                    
                total_init_fld += 1
                    
                CASE f.Is_array ?
                        CASE f.Type_.Kind ?
                            ['BOOL']: STR suf|fix_fn = "Bool"
                            ['ENUM']: suf = "Byte"
                            ['INT']: suf = "Int"
                            ['REAL']: suf = "Real"
                            ['STR']: suf = "Str"
                            ['CLASS', 'STRUCTURE']: suf = "Obj" ;
                        CASE ?
                        [suf == "Obj" && f.Is_weak && !f.Is_fixed] ?
                             suf = suf "Weak"
                        [suf == "Obj" && !f.Is_fixed && f.Type_.Kind IN [
                         'CLASS', 'STRUCTURE']] ?
                             suf = suf "Hard" ;
                        CASE ?
                        [f.Is_fixed && f.Size_n[0] == "{"] ?
                             RESULT = RESULT s "new FixA" suf clamp_array(f)
                             "(" f.Size_type_.Items[].Count.Str ");"#NL
                             CONTINUE f
                        [f.Is_fixed
                        && f.Type_.Kind !IN ['CLASS', 'STRUCTURE']] ?
                             RESULT = RESULT s "new FixA" suf clamp_array(f) "("
                             CASE ?
                             [f.Size_n == "*"] ? 
                                  RESULT = RESULT "0"
                             [f.Size_value > 0] ? 
                                  RESULT = RESULT f.Size_value.Str
                             ELSE RESULT = RESULT f.Size_n ; 
                             RESULT = RESULT ");"#NL
                             CONTINUE f
                        [f.Is_fixed && f.Type_.Kind == 'STRUCTURE' 
                         && (f.Size_n != "" || f.Size_value > 0)] ?
                             CASE f.Size_n == "" ? f.Size_n = f.Size_value.Str ;
                        	 total_temp_new_obj += 1
                        	 STR tmp|_variable = "temp__" total_temp_new_obj.Str
                        	 ------------ 'declare temp array of structures'
                             RESULT = RESULT spaces "DynAObjHard " tmp 
                             	" = new DynAObjHard("
                             	"" f.Type_.In_class_.Final_name
                             	"." f.Type_.Final_name
                             	".NoneObj_" f.Type_.Final_name ".hard_link);"#NL
                             	
                             RESULT = RESULT spaces "for (int k=0; k < "
                             "" f.Size_n "; k++)"
                             ------------ 'add NONE objects'
                             RESULT = RESULT spaces "  " tmp ".Add(" 
                             "" f.Type_.In_class_.Final_name
                             "." f.Type_.Final_name ".New());"
                             ------------ 'create fixed array on base on it'
                             s = s "new FixA" suf clamp_array(f)
                             		"(" tmp ", 0, " tmp ".Count-1);"
                             		
                             RESULT = RESULT s #NL
                             CONTINUE f
                        ;
                        CASE f.Is_fixed ?
                        	 s = s "new FixA" suf clamp_array(f)
                        ELSE s = s "new DynA" suf ;
                        --------------------------- 'suffix for DynA...'
                        CASE ?
                        [f.Type_.Kind == 'CLASS'] ?
                             s = s "(" f.Type_.Final_name
                                  ".NoneObj_" f.Type_.Final_name
                                  ".hard_link)"
                        [f.Type_.Kind == 'STRUCTURE'] ?
                             s = s "(" f.Type_.In_class_.Final_name 
                             	  "." f.Type_.Final_name
                                  ".NoneObj_" f.Type_.Final_name
                                  ".hard_link)"
                        ELSE s = s "()" ;
                ELSE 
                     CASE Non && f.Type_.Kind IN ['BOOL', 'INT', 'REAL',
                          'ENUM', 'STR']
                          ?
                          CONTINUE f ;
                     CASE ?
                     [f.Initial_ != NONE] ? s = s gen_expr(f.Initial_)
                     
                     [f.Type_.Kind == 'STRUCTURE'] ?
                     	s = s f.Type_.In_class_.Final_name 
                     		"." f.Type_.Final_name ".New()"
                     		 
                     ELSE s = s gen_none_val(f.Type_) ;
                ;
                RESULT = RESULT s ";" ;
            CASE RESULT != "" ?
            	 -------------- 'prepend which fields are initializing'
                 RESULT = #NL sp(12) 
                 "// init fields: " Class.Final_name #NL RESULT
            ;
            .
                
        INT total_temp_new_obj
        */
        private int TOTAL_init_field;

        private string gen_init_fields(Type Class, bool None_inst)
        {
            string Result = "";
            foreach (Variable f in Class.Field)
            {
                if (TOTAL_init_field == 0)
                { }
                if (f.Final_name == "DATA") continue;
                if (TOTAL_init_field == 1381)
                { } 
                string s = "\r\n" + sp(12) + "// init fld: " + (TOTAL_init_field++).ToString() +
                            "\r\n" + sp(12) + "Result." + f.Final_name + " = ";
                

                if (f.Is_array)
                {
                    string suf = "";
                    if (f.Type_ == null) continue; // ????????????????????
                    switch (f.Type_.Kind)
                    {
                        case Type.Kind_type.BOOL: suf = "Bool"; break;
                        case Type.Kind_type.INT: 
                        case Type.Kind_type.ENUM: suf = "Int"; break;
                        case Type.Kind_type.REAL: suf = "Real"; break;
                        case Type.Kind_type.STR: suf = "Str"; break;
                        case Type.Kind_type.CLASS: suf = "Obj"; break;
                    }
                    if (f.Is_fixed)
                    {
                        Result += s + "new FixA" + suf + "(" + f.Size_type_.Items.Count.ToString() + ");";
                        continue;
                    }
                    s += "new DynA" + suf;
                    if (f.Type_.Kind == Type.Kind_type.CLASS) {
                    	if (f.Type_.Final_name == "obj")
                        	s += "(AL4_object.NoneObj_AL4_object.hard_link)";
                    	else s += "(" + f.Type_.Final_name + ".NoneObj_" 
                    		 + f.Type_.Final_name + ".hard_link)";
                    }
                    else s += "()";
                }
                else
                {
                    if (None_inst && (
                        f.Type_.Kind == Type.Kind_type.BOOL ||
                        f.Type_.Kind == Type.Kind_type.INT ||
                        f.Type_.Kind == Type.Kind_type.REAL ||
                        f.Type_.Kind == Type.Kind_type.ENUM)) continue;
                    if (f.Initial_ != null)
                        s += gen_expr(f.Initial_);
                    else s += gen_none_val(f.Type_);
                }
                Result += s + ";";
            }
            if (Result != "")
                Result = "\r\n" + sp(12) + "// init fields: " + Class.Final_name + "\r\n" + Result;
            if (Class.Base_ != null)
                Result = gen_init_fields(Class.Base_, false) + "\r\n" + Result;
            return Result;
        }

        /*
        FUNCTION get_set_link(STR Link|_name, STR Cl|ass_name) ==> STR :
            RESULT = @"" sp(8) "{"
            "" sp(8) "    get { return (" Cl ")" Link "; }"
            "" sp(8) "    set { " Link " = value; }"
            "" sp(8) "}" .
        */
        const string obr = "{";
        const string cbr = "}";
        
        private static string get_set_link(string Link, string Cl)
        {
            return "\r\n" +
                sp(8) + obr + "\r\n" +
                sp(8) + "    get " + obr + " return (" + Cl + ")" + Link + "; " + cbr + "\r\n" +
                sp(8) + "    set " + obr + " " + Link + " = value; " + cbr + "\r\n" +
                sp(8) + cbr + "\r\n";
        }

        /*
        
        METHOD generate_NONE({Type} Class|_to_generate) :
            STR n|ame_of_class = Class.Final_name
            
            o[] << @""
                "" sp(8) "public static " n " NoneObj_" n ";"
                "" sp(8) "public static " n " DummyObj_" n ";"
                ""
                "" sp(8) "public static void init_class_" n "()"
                "" sp(8) "{"                                       
                "" sp(8) "    NoneObj_" n " = (" n ")" n ".New_nofields().Obj;"
                "" sp(8) "	  NoneObj_" n ".hard_link.Count = -1;"
                "" sp(8) "    NoneObj_" n ".Is_NONE_object = true;"
                "" sp(8) "    DummyObj_" n " = (" n ")" n ".New_nofields().Obj;"                
                "" sp(8) "    NoneObj_" n ".write = DummyObj_" n ";"
                
            CASE Class.Kind != 'STRUCTURE' ?
            	o[] << @""
                "" sp(8) "    NoneObj_" n ".DO = new Noneclass_" n "("
                "" sp(8) "          NoneObj_" n ");"
                "" sp(8) "    DummyObj_" n ".DO = new Noneclass_" n "("
                "" sp(8) "          DummyObj_" n ");"
            ;
            o[] << @
                "" sp(8) "}"                                       
                ""
                "" sp(8) "public override AL4_object NONE_base_obj()"
                "" sp(8) "{"
                "" sp(8) "    return "
                
            CASE Class.Base_ == NONE ? o[*] = o[*] "null"
            
            ELSE o[*] = o[*] Class.Base_.Final_name 
                         ".NoneObj_" Class.Base_.Final_name
            ;
            o[*] = o[*] ";"
            
            o[] << @"" sp(8) "}"
                ""
                "" sp(8) "public override Ref_obj NONE_obj_instance()"
                "" sp(8) "{"
                "" sp(8) "    return NoneObj_" n ".hard_link;"
                "" sp(8) "}"
                "" .
        */
        private void generate_NONE(Type Class)
        {
            string n = Class.Final_name;
            o.Add("");
            o.Add(sp(8) + "public static Noneclass_" + n + " NoneObj_" + n + ";");
            o.Add(sp(8) + "public static Noneclass_" + n + " DummyObj_" + n + ";");
            o.Add("");
            o.Add(sp(8) + "public static void init_class_" + n + "()");
            o.Add(sp(8) + obr);
            o.Add(sp(8) + "    NoneObj_" + n + " = (Noneclass_" + n + ")Noneclass_" + n);
            o.Add(sp(8) + "                        .New().Obj;");
            o.Add(sp(8) + "    DummyObj_" + n + " = (Noneclass_" + n + ")Noneclass_" + n);
            o.Add(sp(8) + "                        .New().Obj;");
            o.Add(sp(8) + "    NoneObj_" + n + ".write = DummyObj_" + n + ";");
            o.Add(sp(8) + cbr);
            o.Add("");
            o.Add(sp(8) + "public override AL4_object NONE_base_obj()");
            o.Add(sp(8) + obr);
            o.Add(sp(8) + "    return ");
            if (Class.Base_ == null) o[o.Count - 1] += "null";
            else o[o.Count - 1] += Class.Base_.Final_name + ".NoneObj_" + Class.Base_.Final_name;
            o[o.Count - 1] += ";";
            o.Add(sp(8) + cbr);
            o.Add("");
            o.Add(sp(8) + "public override Ref_obj NONE_obj_instance()");
            o.Add(sp(8) + obr);
            o.Add(sp(8) + "    return NoneObj_" + n + ".hard_link;");
            o.Add(sp(8) + cbr);
            o.Add("");
        }

        /*
        METHOD generate_Noneclass({Type} Class|_to_generate) :
            ------------------------------------ 'start Noneclass_'
            STR n|ame_class = Class.Final_name
            
            o[] << @""
                    "" sp(4) "public class Noneclass_" n ": Methods_" n
                    "" sp(4) "{"
                    "" sp(4) "    public Noneclass_" n "(" n " obj_this)"
                    "" sp(4) "           : base(obj_this)"
                    "" sp(4) "    {"
                    "" sp(4) "    "
                    "" sp(4) "    }"
                    "" sp(4) "    public override void Erase() { }"
                    ""
                    
            o[] << @""
                    "" sp(4) "    //public void Init_none()"
                    "" sp(4) "    //{"
                    "" sp(4) "    //    Noneclass_" n " Result = this;"
                    "" sp(4) "    //    Result.Is_NONE_object = true;"
                    
            o[] << @"" sp(4) "    //}"
                    ""
            ---------------------------- 'methods for NONE to ignore all calls'
            generate_noneclass_methods(Class)
            
            o[] << @"" sp(4) "}"
                    "" .
        */
        private void generate_Noneclass(Type Class)
        {
            string n = Class.Final_name;
            o.Add(sp(4) + "public class Noneclass_" + n + ": " + n);
            o.Add(sp(4) + obr);
            o.Add(sp(4) + "    public override void Erase() " + obr + " " + cbr);
            o.Add("");
            generate_New(Class, "Noneclass_" + n);
            o.Add("");
            o.Add(sp(4) + "    public void Init_none()");
            o.Add(sp(4) + "    " + obr);
            o.Add(sp(4) + "        Noneclass_" + n + " Result = this;");
            o.Add(sp(4) + "        Result.Is_NONE_object = true;");
            o.Add(gen_init_fields(Class, true));
            o.Add(sp(4) + "    " + cbr);
            generate_noneclass_methods(Class);
            o.Add("");
            o.Add(sp(4) + cbr);
            o.Add("");
        }

        /*
        
        METHOD generate_noneclass_methods|_overridden(
            {Type} C|lass_to_generate)
            :
            ---------------------------------- 'for all non-static methods'
            FOR m IN C.Method[] :
                CASE m == NONE ? CONTINUE m ;
                CASE m.Final_name == "-" ? CONTINUE m ;
                CASE m.Modifiers['STATIC'] ? CONTINUE m ;
                CASE m == C.Construct || m == C.Destruct ? CONTINUE m ;
                o[] << "" << sp(8) "public override "
                CASE m.Result !=  NONE ?
                     o[*] = o[*] type_gen(m.Result.Type_, "") " "
                ELSE o[*] = o[*] "void " ;
                o[*] = o[*] m.Final_name "( "
                ------------------------------ 'parameters'
                FOR p IN m.Param[] :
                    o[] << sp(16) type_gen_A(p.Type_, A_if(p.Is_array)
                           "" F_if(p.Is_fixed) W_if(p.Is_weak))
                           " " p.Final_name ","
                ;
                CASE m.Modifiers['STORE'] ?
                     o[] << sp(8) "ref int " m.Stored_param.Final_name "," ;
                o[*] = o[*].[0 TO *-1] ")"
                ------------------------------ 'body'
                o[] << sp(8) "{"
                CASE m.Result != NONE ?
                     o[] << sp(12) "return " gen_none_val(m.Result.Type_) ";" ;
                o[] << sp(8) "}" ; .
        */
        public void generate_noneclass_methods(Type Class)
        {
            foreach (Function m in Class.Method)
            {
                if (m.Final_name == "-") continue;
                if (m.Modifiers[(int)Function.Fun_mod.STATIC]) continue;
                o.Add("");
                o.Add(sp(8) + "public override ");
                if (m.Result != null)
                    o[o.Count - 1] += type_gen(m.Result.Type_, false, false) + " ";
                else o[o.Count - 1] += "void ";
                o[o.Count - 1] += m.Final_name + "( ";
                //---------------------------------------- 'parameters'
                foreach (Variable p in m.Param)
                {
                    o.Add(sp(16) + type_gen(p.Type_, p.Is_array, p.Is_fixed) +
                        " " + p.Final_name + ",");
                }
                o[o.Count - 1] = o[o.Count - 1].Substring(0, o[o.Count - 1].Length - 1) + ")";
                //--------------------------------------- 'body'
                o.Add(sp(8) + "{");
                if (m.Result != null)
                    o.Add(sp(12) + "return " + gen_none_val(m.Result.Type_) + ";");
                o.Add(sp(8) + "}");
            }
        }

        /*
        
        METHOD generate_main({Type} Class|_main) :
            ------------------------------------------------ 'Report_leaks'
            CASE Comp.Defined_name[].Find("$REPORT_LEAKS") >= 0 ?
                 generate_report_leaks 
                 BOOL report_leaks = TRUE ;
            ------------------------------------------------ 'function Main'
            {Fun} f|unction_main = Class.Find_fun("Main", TRUE)
            //CASE Comp.Noconsole ? o[] << "[STAThread]" ;
            o[] << @""
            "" sp(8) "[STAThread]"
            "" sp(8) "static void Main(string[] args)"
            "" sp(8) "{"
            "" sp(8) "	for (int i = 0; i < args.Length; i++)"
            "" sp(8) "		AL4_system.System_parameters.Add(args[i]);"
            --------------------------- 'init classes'
            generate_init_classes
            
            o[] << @""
            "" sp(8) "    try {"
            
            CASE Comp.Noconsole ?
                 o[] << sp(8) "AL4_system.Need_console = true;" ;
                 
            CASE Comp.TEST_value ?
                 o[] << sp(16) "Do_tests();"
                 FOR c IN Comp.All_classes[] :
                     CASE c == Class ? CONTINUE c ;
                     CASE c.Test[].Count == 0 ? CONTINUE c ;
                     //CASE c.Tests_already_done ? CONTINUE c ;
                     CASE !Class_needs_testing(c) ? CONTINUE c ;
                     o[] << sp(16) c.Final_name ".Do_tests();" ;
            ELSE o[] << sp(16) f.Final_name "();" ;
            
		    CASE LOGGING_METHODS ?
		     	 o[] << sp(16) "AL4_log_methods.log_method("#QU#QU");" ;
		     	 
		    CASE Comp.Diagnostics ? 
		         o[] << sp(16) "AL4_system.diag_report("#QU"#"#QU");" ;
		     	 
		    CASE use_profiler != "" ?
		         o[] << sp(16) "AL4_system.Profiler_save_reset();" ;
		
            CASE report_leaks ?
                 o[] << sp(16) "Report_leaks();" ;
                 
            o[] <<  "" sp(8) "    } catch (Stop S) {" <<
                    "" sp(8) "      AL4_system.Any_exception(S);" <<
                    "" sp(8) "		if (S.Stop_message != "#QU#QU") {" <<
                    "" sp(8) "      	AL4_system.WriteLine("#QU
                    						"STOP: "#QU" + " <<
                    "" sp(8) "          	S.Stop_message);" <<
                    "" sp(8) "      	Console.ReadLine();" <<
                    "" sp(8) "		}" <<
                    "" sp(8) "    }" <<
                    "" sp(8) "}" <<
                    "" .
                    
METHOD generate_report_leaks :
    o[] << @""
            "    static void add_report(String class_nm,"
            "         long n_constr, long n_destr, List<String> RL)"
            "    {"
            "        if (n_constr == n_destr) return;"
            "        RL.Add(n_constr.ToString() + '\t' +"
            "          n_destr.ToString() + '\t' + class_nm);"
            "    }"
            ""
            "    static void Report_leaks()"
            "    {"
            "        List<String> RL = new List<String>();"
    FOR c IN Comp.All_classes[] :
        //CASE c.Is_translation ? CONTINUE c ;
        CASE c.Construct == NONE || c.Destruct == NONE ? CONTINUE c ;
        CASE skip_class(c) ? CONTINUE c ;
        
        o[] << sp(8) "add_report("#QU c.Final_name #QU 
        ", Methods_" c.Final_name ".CNT_CONSTRUCT"
        ", Methods_" c.Final_name ".CNT_DESTRUCT, RL);"
    ;
    o[] << @"        if (RL.Count() > 0)"
            "        {"
            "           RL.Insert(0, "#QU"constr"#QU" + '\t' + " 
            "               "#QU"destr"#QU" + '\t' + "#QU"class"#QU");"
            "        }"
            "        AL4_system.Save_strings(RL, " 
            "@"#QU Comp.Destination.Trailing_slash "Report_leaks.txt"#QU
            "        );"
            "    }"
            "" .

                    
        */
        private void generate_main(Type Class)
        {
            Function f = Class.Find_fun("Main");
            o.Add("");
            o.Add(sp(8) + "static void Main(string[] args)");
            o.Add(sp(8) + "{");
            o.Add(sp(8) + "for (int i = 0; i < args.Length; i++)");
            o.Add(sp(8) + "		AL4_system.System_parameters.Add(args[i]);");
            generate_init_classes();
            o.Add("");
            o.Add(sp(8) + "    try {");
            if (Comp.Test())
            {
                o.Add(sp(16) + "Do_tests();");
                foreach (Type c in Comp.All_classes)
                {
                    if (c == Class) continue;
                    if (c.Test.Count == 0) continue;
                    o.Add(sp(16) + c.Final_name + ".Do_tests();");
                }
            }
            else o.Add(sp(16) + f.Final_name + "();");
            o.Add(sp(8) + "    } catch (Stop S) {");
            o.Add(sp(8) + "       AL4_system.Any_exception(S);");
            o.Add(sp(8) + "       Console.WriteLine(\"STOP: \" +");
            o.Add(sp(8) + "           S.Stop_message);");
            o.Add(sp(8) + "       Console.ReadLine();");
            o.Add(sp(8) + "    }");
            o.Add(sp(8) + "}");
            o.Add("");
        }

        /*
        
        METHOD generate_init_classes|_for_main_or_tests :
            o[] << sp(8) "    // init classes"
            o[] << sp(12) "AL4_object.init_class_AL4_object();"
            {Type} list_obj|ect_types_to_init[]
            FOR c IN Comp.All_classes[] :
                //CASE c.Is_translation ? CONTINUE c ;
                CASE skip_class(c) ? CONTINUE c ;
                FOR struc IN c.Structures_[] :
                    list_obj[] << struc ; 
                STR n|ame_of_class = c.Final_name
                o[] << sp(12) n ".init_class_" n "();" ;
            FOR x IN [0 TO list_obj[].Count-1] :
                CASE list_obj[x] == NONE ? CONTINUE x ;
                do_init_obj(list_obj[], x) ;
            FOR c IN Comp.All_classes[] :
                //CASE c.Is_translation ? CONTINUE c ;
                CASE skip_class(c) ? CONTINUE c ;
                n = c.Final_name
                
                o[] << sp(12) n ".Do_init_fields_not_simple(" n 
                	".NoneObj_" n ");"
                	     
                o[] << sp(12) n ".Do_init_fields_not_simple(" n 
                	".DummyObj_" n ");"
                	     
            	FOR st IN c.Structures_[] :
	                n = c.Final_name "." st.Final_name
	                
	                o[] << sp(12) n ".Do_init_fields_not_simple(" n 
	                	".NoneObj_" st.Final_name ");"
	                	 
	                o[] << sp(12) n ".Do_init_fields_not_simple(" n 
	                	".DummyObj_" st.Final_name ");"
            	;
            ; .
            
        METHOD do_init_obj(
        	{Type} Obj|ects_to_init[], 
        	INT Index|_of_object_to_init INDEXING {Type}),
        	RECURSIVE
        	:
			FOR f IN Obj[Index].Field[] :
			    CASE f.Type_.Kind == 'STRUCTURE' 
			    	 && f.Type_ != Obj[Index] && f.Type_ IN Obj[]
			    	 ?
			    	 INT x|_position INDEXING {Type} = Obj[].Find(f.Type_) 
			         do_init_obj(Obj[], x) ;
			;
        	STR obj_n|ame = Obj[Index].Final_name
        	
        	o[] << sp(12) Obj[Index].In_class_.Final_name "." obj_n 
                	   ".init_class_" obj_n "();"
                	   
        	Obj[Index] = NONE . 


        */
        private void generate_init_classes()
        {
            o.Add(sp(8) + "    // init classes");
            foreach (Type c in Comp.All_classes)
            {
                string n = c.Final_name;
                o.Add(sp(12) + n + ".init_class_" + n + "();");
            }
            o.Add(sp(8) + "    // init none objects fields");
            foreach (Type c in Comp.All_classes)
            {
                string n = c.Final_name;
                o.Add(sp(12) + n + ".NoneObj_" + n + ".Init_none();");
                o.Add(sp(12) + "((Noneclass_" + n + ")" + n +
                    ".DummyObj_" + n + ").Init_none();");
            }
        }

        /*
        
        METHOD generate_enum({Type} E|numeration) :
            o[] << sp(8) "public static string[] Names_" E.Final_name
                   " = new string[]{"
            FOR it IN E.Items[] :
                o[] << sp(12) #QU it.Names[0] #QU "," ;
            o[*] = o[*].[0 TO *-1] "};"
            o[] << "" .
        */
        private void generate_enum(Type E)
        {
            o.Add(sp(8) + "public static string[] Names_" + E.Final_name +
                " = new string[]" + obr);
            foreach (Variable it in E.Items)
                o.Add(sp(12) + "\"" + it.Names[0] + "\",");
            o[o.Count-1] = o[o.Count-1].Substring(0, o[o.Count-1].Length-1) + 
                cbr + ";";
            o.Add("");
        }

        /*
        INT total_gen_field

        METHOD generate_field({Var} V|ariable) :
            o[] << sp(8) "// declare: " total_gen_field.Str
            total_gen_field += 1
            o[] << sp(8) "public "
            CASE V.Final_name == "DATA" ?
                 o[*] = o[*] "static "
                 CASE Comp.Current_class.Base_ != NONE ?
                      o[*] = o[*] "new " ;
            ;
            o[*] = o[*] var_type_gen(V) " " V.Final_name
            CASE V.Is_array ?
                 CASE V.Final_name == "DATA" ?
                      o[*] = o[*] " = new FixAStr(new string[]{"
                      FOR d IN Comp.Current_class.Ending_lines[] :
                          o[] << d.as_str "," ;
                      o[] << #QU #QU "})" ;
                 o[*] = o[*] ";" ==> ;
                 
            CASE V.Type_.Kind ?
                ['STR']: o[*] = o[*] " = " #QU #QU ";"
                
                ['BOOL', 'INT', 'REAL', 'ENUM', 'CLASS', 'STRUCTURE']:
                         o[*] = o[*] ";" ; .

        METHOD var_type_gen({Var} V|ariable) ==> STR :
            RESULT = type_gen(V.Type_, A_if(V.Is_array) F_if(V.Is_fixed)
                    "" W_if(V.Is_weak))
            CASE !Comp.Int32 && RESULT == "long" && V.Is_stored_param ? 
                 RESULT = "int" ;
            RESULT = RESULT " " .
                    
        METHOD generate_constant_array(
        {Var} C|onstant_array_to_generate)
        	:
			o[] << "" << sp(8) "public static " type_gen(C.Type_, "") 
				   "[] " C.Final_name " = {"
				   
			o[] << sp(12) 
				   
			FOR it IN C.Items_[] :
			    STR v_gen|erated = gen_const_value(it)
			    CASE o[*].Len >= 50 && o[*].Len + v_gen.Len >= 79 ?
			         o[] << sp(12) ;
			    o[*] = o[*] v_gen ", " ;
				   
			o[*] = Remove_trailing(o[*].TrimR, ",") "};" .
                    
        */
        private int TOTAL_gen_field;

        private void generate_field(Variable v)
        {
            if (TOTAL_gen_field == 179)
            { }
            o.Add(sp(8) + "// declare: " + (TOTAL_gen_field++).ToString());
            if (v.Type_ == null)
            {
            	o.Add(sp(8) + "//no type for foeld " + v.Final_name);
            	return;
            }

            o.Add(sp(8) + "public ");
            if (v.Final_name == "DATA")
            {
                o[o.Count - 1] += "static ";
                if (Comp.Current_class.Base_ != null)
                    o[o.Count - 1] += "new ";
            }
            o[o.Count-1] += type_gen(v.Type_, v.Is_array, v.Is_fixed) + " " + v.Final_name;
            if (v.Is_array)
            {
                if (v.Final_name == "DATA")
                {
                    o[o.Count - 1] += " = new FixAStr(new string[]{";
                    for (int i = 0; i < Comp.Current_class.Ending_lines.Count; i++)
                        o.Add(as_str(Comp.Current_class.Ending_lines[i]) + ",");
                    o.Add("" + (Char)34 + (Char)34 + (Char)0x7D + ")" );
                }
                o[o.Count - 1] += ";";
                return;
            }
            switch (v.Type_.Kind)
            {
                case Type.Kind_type.STR: o[o.Count-1] += " = \"\";"; break;
                default: o[o.Count - 1] += ";"; break;
            }
        }

        /*
        
        FUN A_if|_flag_passed_is_true( BOOL A|rray_flag ) ==> STR :
            CASE A ? RESULT = "A" ; .
            
        FUN F_if|_flag_passed_is_true( BOOL F|ixed_flag ) ==> STR :
            CASE F ? RESULT = "F" ; .
            
        FUN W_if|_flag_passed_is_true( BOOL W|eak_flag ) ==> STR :
            CASE W ? RESULT = "W" ; .
        
        METHOD type_gen_A|rray_replace({Type} T|ype_of_var,
            STR Op|tions_type) ==> STR
            :
            ----------------------------------------------------- ''
            CASE "A" !IN Op ?   RESULT = type_gen(T, Op) ==> ;
            CASE T.Kind ?
            ['BOOL']:           RESULT = "ArrayBool"
            ['ENUM']:   RESULT = "ArrayByte"
            ['INT']:            RESULT = "ArrayInt"
            ['REAL']:           RESULT = "ArrayReal"
            ['STR']:            RESULT = "ArrayStr"
            ['CLASS', 'STRUCTURE']:RESULT = "ArrayObj"
                       CASE "W" IN Op ? RESULT = RESULT "Weak"
                       ELSE             RESULT = RESULT "Hard" ;
            ; .
            
        

        METHOD type_gen|erate({Type} T|ype_of_var,
            STR Op|tions_type) ==> STR
            :
            --------------------------------- 'scalar'
            CASE T.Kind ?
                 ['BOOL']: RESULT = "bool"
                 ['ENUM']: RESULT = "byte"
                 ['INT']:
                     CASE Comp.Int32 ? 
                          RESULT = "int"
                     ELSE RESULT = "long" ;
                 ['REAL']: RESULT = "double"
                 ['STR']: RESULT = "string"
                 ['CLASS', 'STRUCTURE']: RESULT = "Ref_obj" ;
            --------------------------------- 'or array'
            CASE "A" !IN Op ? ==> ;
            CASE "F" !IN Op ?
                 CASE T.Kind ?
                      ['BOOL']: RESULT = "DynABool"
                      ['ENUM']: RESULT = "DynAByte"
                      ['INT']: RESULT = "DynAInt"
                      ['REAL']: RESULT = "DynAReal"
                      ['STR']: RESULT = "DynAStr"
                      ['CLASS', 'STRUCTURE']: RESULT = "DynAObj" 
                                 CASE "W" IN Op ? RESULT = RESULT "Weak"
                                 ELSE RESULT = RESULT "Hard" ;
                 ;
            ELSE 
                 CASE T.Kind ?
                      ['BOOL']: RESULT = "FixABool"
                      ['ENUM']: RESULT = "FixAByte"
                      ['INT']: RESULT = "FixAInt"
                      ['REAL']: RESULT = "FixAReal"
                      ['STR']: RESULT = "FixAStr"
                      ['CLASS', 'STRUCTURE']: RESULT = "FixAObj" ;
            ; .

        */
        private string type_gen(Type T, bool A, bool Fixed)
        {
            string Result = "";
            switch (T.Kind)
            {
                case Type.Kind_type.BOOL: Result = "bool"; break;
                case Type.Kind_type.INT: 
                case Type.Kind_type.ENUM: Result = "int"; break;
                case Type.Kind_type.REAL: Result = "double"; break;
                case Type.Kind_type.STR: Result = "string"; break;
                case Type.Kind_type.CLASS: Result = "Ref_obj"; break;
            }
            if (A)
            {
                if (!Fixed)
                {
                    switch (T.Kind)
                    {
                        case Type.Kind_type.BOOL: Result = "DynABool"; break;
                        case Type.Kind_type.INT: 
                        case Type.Kind_type.ENUM: Result = "DynAInt"; break;
                        case Type.Kind_type.REAL: Result = "DynAReal"; break;
                        case Type.Kind_type.STR: Result = "DynAStr"; break;
                        case Type.Kind_type.CLASS: Result = "DynAObj"; break;
                    }
                }
                else
                {
                    switch (T.Kind)
                    {
                        case Type.Kind_type.BOOL: Result = "FixABool"; break;
                        case Type.Kind_type.INT:
                        case Type.Kind_type.ENUM: Result = "FixAInt"; break;
                        case Type.Kind_type.REAL: Result = "FixAReal"; break;
                        case Type.Kind_type.STR: Result = "FixAStr"; break;
                        case Type.Kind_type.CLASS: Result = "FixAObj"; break;
                    }
                }
            }
            return Result;
        }

        /*
        BOOL FINAL_CODE
        {Fun} All_methods|_to_generate_debug_info[] 

		CONST BOOL:
			USE_STACK_OF_VAR|IABLES = FALSE
			USE_STACK_OF_FUN|CTIONS = TRUE .
			
		{Var} do_not_release|_vars[]
		{Fun} current_generated_fun

        METHOD generate_method({Fun} F|unction) :
	        used_brk[].Clear
			CASE F == NONE ? ==> ;
	        PUSH current_generated_fun = F :
				new_init = NONE
				INT start|_line_in_output = o[].Count
				do_generate_method(F)
				BOOL now_present|_List_temps = list_temps_present(F)
				FOR i IN [F.Local_var[].Count-1 DOWNTO 0]:
				    CASE F.Local_var[i].Line == -2 ?
				         F.Local_var[].Delete(i) ;
				;
				---------------------------- 'provide try - finally'
				INT r|eplacements_count = 0
				FOR io IN [o[].Count-1 DOWNTO start+1] :
				    CASE r >= 2 ? BREAK io ;
				    STR s|tring_line_i = o[io].Trim
				    CASE s IN ["//try", "//finally"] ?
				         CASE now_present ?
				              o[io] = Replace(o[io], "//", "")
				              r += 1
				              CONTINUE io ;
				         o[].Delete(io)
				         r += 1
				         CASE s == "//finally" && (
				         	  o[io+1].Trim == "} //end of finally") && (
				         	  o[io].Trim == "{ //begin finally2")
				         	  ?
				         	  o[].Delete(io+1)
				         	  o[].Delete(io) ;
				    ;
				;
	        ; .
		
		INT line_with_cnt
	
        METHOD do_generate_method({Fun} F|unction) :
            ------------------------------------------ 'skip native directives'
            CASE F.Final_name == "-" ? o[] << F.Native_code ==> ;
            All_methods[] << F
            do_not_release[].Clear
            ------------------------------------------ 'insert comment / / fun:'
            Comp.Current_fun = F
            Comp.Current_class.Parse.Line = F.Line_start
            o[] << ""
            o[] << "// fun: " F.Total_fn.Str " " F.Names[0]
            //DEBUG:
            //	CASE F.Overloaded_[].Count > 0 ?
            //	     o[] << "// overloaded versions: "
            //	     FOR ov IN F.Overloaded_[] :
            //	         o[*] << " " ov.Total_fn.Str ;
            //	;
            //;
            spaces = ""
            ---------------------------- 'header'
            CASE F.Ancestor_ != NONE || (
                 F == F.Class.Destruct || F == F.Class.Construct)
                 ? 
                 STR new|_qualifier = "new " ;
            CASE !FINAL_CODE ?
            	 line_with_cnt = o[].Count
            	 CASE use_profiler=="" || use_profiler.[0] IN "AF" ? 
            	      o[] << "public static " new "long CNT_" F.Final_name ";" ;
                 o[] << "public static " new "long CNT1_" F.Final_name ";"
                 o[] << "" ;
            o[] << "public "

            CASE F.Ancestor_ != NONE || (
                 F == F.Class.Destruct || F == F.Class.Construct)
                 ? 
                 CASE F.Modifiers['STATIC'] ?
                      Comp.Error("Internal error: static function can "
                      "not be override"._Einternal )
                 ELSE o[*] = o[*] "override " ;
            ELSE 
                 CASE F.Modifiers['STATIC'] ? o[*] = o[*] "static "
                 ELSE o[*] = o[*] "virtual " ;
            ;
            o[] << ""
            ---------------------------- 'type'
            CASE F.Result == NONE ? o[*] = o[*] "void "
            ELSE o[*] = o[*] type_gen(F.Result.Type_, "") " " ;

            o[*] = o[*] F.Final_name "(" sp(1)
            ---------------------------- 'parameters'
            FOR p IN F.Param[] :
                o[] << sp(8) type_gen_A(p.Type_, A_if(p.Is_array) 
                       "" F_if(p.Is_fixed) W_if(p.Is_weak))
                       " " p.Final_name ","
            ;
            CASE F.Modifiers['STORE'] ?
                 o[] << sp(8) "ref int " F.Stored_param.Final_name "," ;
            o[*] = o[*].[0 TO *-1] ")"
            o[] << "{"
            ---------------------------- 'increase CNT_<name> static counter'
            spaces = sp(4)
            CASE !FINAL_CODE ?
			     CASE LOGGING_METHODS ?
			          CASE ?
			          [F.Names[*] == LOGGING_RESET] ?
			          	   o[] << "AL4_log_methods.reset_logging();"     
			          
			          [F.Class.Names[0] !IN do_not_log_classes[]
			           && F.Class.Names[0] 
			           "." F.Names[0] !IN do_not_log_methods[]] ?
				           o[] << "AL4_log_methods.log_method("
				           		  #QU F.Class.Names[0] "." F.Names[0] #QU");"
				         		  
			          [F.Modifiers['NATIVE_FUN']] ? NONE
				           
			          ELSE o[] << "AL4_log_methods.disable_log(1);"
			          	   BOOL disabled_logging = TRUE
			          ;
			     ;
                 CASE use_profiler=="" || use_profiler.[0] IN "FA" ? 
	                  o[] << "    if (AL4_system.inc_cnt(ref CNT_" F.Final_name 
	                 		 ", ref CNT1_" F.Final_name ") == 0 )" #NL
	                 		 "    { }"
                        
	                  o[] << "	 long local_CNT_" F.Final_name 
	                  		 " = CNT_" F.Final_name ";"
	                 		 
	                  o[] << "	 if (local_CNT_" F.Final_name " == 0)"#NL
	                 		 "	 { }"
                 ;
	             ---------------------------- 'functions stack needed ?'
	             CASE Comp.Debugging && USE_STACK_OF_FUN ?
	                  BOOL stack_of_fun|ctions = TRUE
	                  o[] << "	try"
	                  o[]<< "	{"
	                  
	                  o[]<< "		AL4_system.Stack_functions["
	                  		"AL4_system.SP_fun++] = " F.Global_n.Str ";"
	                  		
	                  CASE use_profiler==""||use_profiler.[0] IN "FA" ? 
		                   o[]<< "		AL4_system.Stack_functions["
		             			 "AL4_system.SP_fun++] = CNT_" F.Final_name ";"
	                  ELSE o[]<< "      AL4_system.SP_fun++;" ;
	             			
	                  spaces = spaces sp(4)
	             ;
            ;
            ---------------------------- 'CONSTRUCT ?'
            CASE F == Comp.Current_class.Construct ?
                 o[] << spaces sp(4) "base.CONSTRUCT();" ;
            ---------------------------- 'recursive ?'
            BOOL recur|sion = F.Modifiers['RECURSIVE_FUN']
            	|| F.Ancestor_ != NONE
            	
            CASE recur ?
                 o[] << spaces "if (AL4_system.Recursion_counter"
                        " > AL4_system.Max_recursion_deep)" #NL
                        "" spaces sp(4) "throw new "
                        "TooDeepRecursionException();"
                 o[] << spaces "AL4_system.Recursion_counter++;" ;
            ---------------------------- 'local variables'
            object_var = FALSE
            dynamic_arr = FALSE
            fixed_arr = FALSE
            list_temps_released = FALSE
            init_local_vars(F, NONE)
            ------------------------------------ 'LIMIT FUN present'
            CASE Comp.Has_LIMIT_FUNC ? 
                 o[] << spaces sp(4) "AL4_system.total_func += 1;"
            ;
            ---------------------------- 'need try ?'
            BOOL inc_ref_THIS = FALSE
            //CASE !F.Modifiers['STATIC'] && F.Is_deleting_obj
            //     && F.Class.Destruct != F
            //     ?
            //     inc_ref_THIS = TRUE
            //     o[] << spaces "THIS.hard_link.Count += 2;" ;
            CASE F.Has_add || recur || object_var || dynamic_arr || (
            	 fixed_arr) || F == Comp.Current_class.Destruct
            	 || disabled_logging || inc_ref_THIS
                 || !FINAL_CODE
                 ?
                 o[] << spaces "try {//start try"
                 BOOL try_started = TRUE
                 spaces = spaces sp(4) 
            ELSE o[] << spaces "//try"
            	 o[] << spaces "{//start try" 
            ;
            ---------------------------- 'statements'
            FOR st IN F.Block[] : statement_gen(st) ;
                 
            ---------------------------- 'native ?'
            CASE F.Modifiers['NATIVE_FUN'] ?
                 CASE Comp.TEST_value && (
                      Comp.Current_class.Modifiers['TESTED'])
                      ?
                      FOR i|dummy IN [tcl[].Count TO F.Line_native] :
                          tcl[] << -1 ;
                      CASE !(Comp.Current_fun.Is_trivial && (
                           Comp.Current_class.Modifiers['NATIVE']))
                           ?
                           INT i_tcl INDEXING INT = F.Line_native
                           tcl[i_tcl] = 0 ;
                      CASE !Comp.Current_fun.Modifiers['STATIC'] ? 
                           STR pref|ix_class_name = (
                               Comp.Current_class.Final_name ".") ;
                      
                      STR ref_test|_lines = pref "test_lines"
                      "_" Comp.Current_class.Final_name 
                      "[" F.Line_native.Str "]"
                      
                      o[] << spaces "if (" ref_test " <= 0) " 
                      "" ref_test " = AL4_system.Test_caller;" 
                      
                 ;                      
                 o[] << "//native code added:"
                 o[] << F.Native_code ;
                 
            CASE F.Block[*].Is_jump ?
                 o[] << spaces "// last block was ended with a jump" ;
            CASE F.Result != NONE && !F.Block[*].Is_jump ?
                 o[] << spaces "return RESULT;" ;
            ----------------------------- 'catch OutOfMemory'
            o[] << spaces.[0 TO *] "}//end of try"
            CASE F.Has_add ?
                 o[] << spaces @"catch (OutOfMemoryException E) {"
                     "" spaces "  AL4_system.Any_exception(E);"
                     "" spaces "  if (AL4_system.Recursion_counter > 1)"
                     "" spaces "     throw;"
                     "" spaces "  return"
                 CASE F.Result != NONE ?
                      o[*] = o[*] " " gen_none_val(F.Result.Type_) ;
                 o[*] = o[*] ";"
                 o[] << spaces "}"
            ;
            ---------------------------- 'catch recursion too deep'
            CASE recur ?
                 o[] << spaces.[0 TO *-4] "catch (TooDeepRecursionException E)"
                        " {"
                        
                 o[] << @
                     "" spaces "  AL4_system.Any_exception(E);"
                     "" spaces "  if (AL4_system.Recursion_counter > 1)"
                     "" spaces "     throw;"
                     "" spaces "  return"
                     
                 CASE F.Result != NONE ?
                      o[*] = o[*] " " gen_none_val(F.Result.Type_) ;
                 o[*] = o[*] ";"
                 o[] << spaces "}" 
            ;
            ---------------------------- 'finally...' 
			CASE try_started ?
                 spaces = spaces.[0 TO * - 4]
                 o[] << spaces "finally {"
                 CASE !FINAL_CODE 
                      && (use_profiler==""||use_profiler.[0]IN"AF") 
                      ?
                      o[] << spaces "  AL4_system.inc_cnt(ref CNT_" F.Final_name
                      ", ref CNT1_" F.Final_name ");" 
                 ;
                 spaces = spaces sp(4)
                 CASE inc_ref_THIS ?
                      o[] << spaces "THIS.hard_link.Ref_dec_hard();" ;
                 CASE recur ?
                      o[] << spaces "  AL4_system.Recursion_counter--;" ;
                 PUSH spaces = spaces sp(4) :
                      dispose_local_vars(F, NONE)
                 ;
                 -------------------------------------- 'DESTRUCTOR ?'
                 CASE F == Comp.Current_class.Destruct ?
                      gen_unref_class_field_objects(Comp.Current_class)
                      o[] << spaces sp(4) "base." F.Final_name "();" ;
                 CASE disabled_logging ?
                 	  o[] << "AL4_log_methods.disable_log(-1);" ;
                 spaces = spaces.[0 TO * - 4]
            ELSE o[] << spaces "//finally"
            	 o[] << spaces "{ //begin finally2"
            ;
            CASE !list_temps_released && list_temps_present(F) ?
			 	 o[] << spaces "ArrayAny.release_temp_lists(List_temps);"
			 	 list_temps_released = TRUE
		 		 o[] << spaces "} //end of finally"
            ELSE
		 		 o[] << spaces "} //end of finally"
		 	;
            -------------------------- 'if tests are called from ancestor ?'
            CASE Comp.TEST_value && Comp.Generating_test && (
                 !Comp.Current_class.Modifiers['ABSTRACT'])
                 ?
                 o[] << spaces "if (AL4_system.Test_caller / 1000000L == 0) "
                 "AL4_system.Test_caller = 0;" ;
            ----------------- 'end of finally block'
            CASE !FINAL_CODE && stack_of_fun ?
                 spaces = spaces.[0 TO * - 4]
                 o[]<< "	} finally "
                 o[]<< "	{"
                 o[]<< "		AL4_system.SP_fun -= 2;"
                 o[]<< "	}" ; 
            o[] << "}" .

		FUN list_temps_present|_in_variables(
			{Fun} F|unction) ==> BOOL
			:
		    FOR v IN F.Local_var[] :
		        CASE v.Final_name == "List_temps" ?
		             RESULT = TRUE ==> ;
		    ; .
		    
BOOL object_var|iables_present	
BOOL dynamic_arr|ays_present
BOOL fixed_arr|ays_present	
BOOL list_temps_released
		    
METHOD init_local_vars(
{Fun} F|unction_generating,
{Local} Loc|al_block) 
    :
    FOR v IN F.Local_var[] :
        CASE v.In_local_ != Loc ? CONTINUE v ;
        CASE v.Is_fixed || v.Final_name == "List_temps" ?
	 		 fixed_arr = TRUE ;
	 	CASE v.Replaced ? CONTINUE v ;
        CASE v.Names[0] != "RESULT" ?
             CASE v.Is_param || v.Names[*] == "THIS" ?
                  CONTINUE v ;
        ;
        //o[] << spaces "// init var: " total_init_var++.Str
        o[] << spaces type_gen(v.Type_, A_if(v.Is_array) 
               "" F_if(v.Is_fixed) W_if(v.Is_weak)) " "
               
        CASE v.Final_name != "" ? o[*] = o[*] v.Final_name " = "
        ELSE o[*] = o[*] v.Names[*] " = " ;
        CASE v.Type_.Kind ?
        ['BOOL']: STR iv|_initial = "false"
        ['INT', 'ENUM', 'REAL']: iv = "0"
        ['STR']: iv = #QU #QU
        
        ['STRUCTURE']:
            iv = v.Type_.In_class_.Final_name
            				  "." v.Type_.Final_name
                			  ".New()"
                			       
        	object_var = TRUE
            			 
        ['CLASS']: iv = v.Type_.Final_name
            iv = iv ".NoneObj_" iv ".hard_link"
            object_var = TRUE ;
        CASE v.Is_array ?
             iv = "new " type_gen(v.Type_, 
                "A" F_if(v.Is_fixed) W_if(v.Is_weak)) "("
             STR t|ype_name = v.Type_.Final_name
             CASE ?
             [v.Type_.Kind == 'CLASS'] ?
                  iv = iv t ".NoneObj_" t ".hard_link"
                   
             [v.Type_.Kind == 'STRUCTURE'] ?
                  iv = iv v.Type_.In_class_.Final_name 
                  		"." t ".NoneObj_" t ".hard_link" 
             ;
             CASE ?
             [v.Is_fixed && v.Size_type_.Kind == 'ENUM'] ?
             	  iv = iv v.Size_type_.Items[].Count.Str
             	  
             [v.Is_fixed && v.Type_.Kind !IN ['CLASS', 'STRUCTURE']] ?
                  iv = iv "0"
             ;
             iv = iv ")"
             CASE !v.Is_fixed ?
                  dynamic_arr = TRUE ;
        ;
        o[*] = o[*] iv ";"
    ;
	.    
	
METHOD dispose_local_vars(
{Fun} F|unction, {Local} Loc|al_block) 
    :
    FOR v IN F.Local_var[] :
        CASE ?
        [v.In_local_ != Loc] ? CONTINUE v
        [v.Replaced] ?
             CONTINUE v
        [v IN F.Param[] || v.Names[0] IN [
             "THIS", "RESULT"]] ?
             CONTINUE v
        [v.Final_name == "List_temps"] ?
             list_temps_released = TRUE
             
             o[] << spaces "ArrayAny."
               		"release_temp_lists(List_temps);"
               		
             CONTINUE v
        [v IN do_not_release[]] ?
             CONTINUE v
        [Starting(v.Names[0], "temp_inline")] ?
             CONTINUE v
        ;
        gen_dispose_var(v) ; .
		    
METHOD provide_list_temps :
	list_temps_used = TRUE
	CASE list_temps_present(Comp.Current_fun) ? ==> ;
	
	v|ariable_list_temps = {Var}(Line = -2, In_fun_ = Comp.Current_fun,
		Is_array = TRUE),
		>> Comp.Current_fun.Local_var[]
		
	v.Set_final_name("List_temps")
	------------------------------------ 'declare & init'
	FOR i IN [o[].Count-1 DOWNTO 0] :
		CASE ?
		[o[i] == "{"] ? 
		     STR init|ialization_of_List_temps = "var List_temps = "
							"ArrayAny.allocate_list_temps();"
		     o[].Insert(i+1, spaces init) ==>
		;
	; .	

METHOD gen_unref_class_field_objects(
{Type} Class|_type)
    :
    FOR fld IN Class.Field[] :
        CASE fld.Is_array && ! fld.Is_fixed ?
             o[] << spaces "    THIS." fld.Final_name ".Clear();"
             CONTINUE fld ;
        CASE fld.Is_array
        	 && fld.Type_.Kind IN ['CLASS', 'STRUCTURE']
        	 ?
             o[] << spaces "    THIS." fld.Final_name ".Clear();"
             CONTINUE fld ;
        CASE fld.Type_.Kind IN ['CLASS', 'STRUCTURE']
        	 && fld.Is_weak
        	 ?
             o[] << spaces "    AL4_object.Object_assign_weak("
             "ref THIS." fld.Final_name ", " fld.Type_.Final_name 
             ".NoneObj_" fld.Type_.Final_name ");"
             CONTINUE fld ;
        CASE ?
        [fld.Type_.Kind == 'CLASS'] ?
             o[] << spaces "    AL4_object.Object_assign_hard("
             "ref THIS." fld.Final_name ", " fld.Type_.Final_name 
             ".NoneObj_" fld.Type_.Final_name ");" 
        [fld.Type_.Kind == 'STRUCTURE'] ?
             o[] << spaces "    (THIS." fld.Final_name ").Discard_struct();"
             //o[] << spaces "    AL4_object.Object_assign_hard("
             //"ref THIS." fld.Final_name
             //", " fld.Type_.In_class_.Final_name
             //"." fld.Type_.Final_name
             //".NoneObj_" fld.Type_.Final_name ");"
        ;
    ; .
    

	*/

        const bool FINAL_CODE = true;
        int total_init_var;

        private void generate_method(Function F)
        {
            if (F.Final_name == "-")
            {
                o.Add(F.Native_code);
                return;
            }
            Comp.Current_fun = F;
            Comp.Current_class.Parse.Line = F.Line_start;
            o.Add("");
            spaces_prefix = "";
            o.Add(spaces_prefix + "// fun: " + F.Total_fn.ToString() + " " +
                F.Names[0]);
            if (F.Total_fn == 393)
            { }

            if (FINAL_CODE)
            {
                o.Add("private static int CNT_" + F.Final_name + ";");
                o.Add("");
            }

            o.Add("public ");
            if (F.Modifiers[(int)Function.Fun_mod.STATIC])
                o.Add("static ");
            else o[o.Count - 1] += "virtual ";
            if (F.Result == null) o[o.Count - 1] += "void ";
            else o[o.Count - 1] += type_gen(F.Result.Type_, false, false) + " ";
            o[o.Count - 1] += F.Final_name + "(" + sp(1);
            //-------------------------- 'parameters'
            foreach (Variable p in F.Param)
                o.Add(sp(8) + type_gen(p.Type_, p.Is_array, p.Is_fixed) +
                    " " + p.Final_name + ",");
            o[o.Count - 1] = o[o.Count - 1].Substring(0, o[o.Count - 1].Length - 1) + ")";
            o.Add("{");
            if (FINAL_CODE)
            {
                o.Add("    if (++CNT_" + F.Final_name + " == 0 )\r\n" +
                      "    { }");
            }
            //-------------------------- 'CONSTRUCT ?'
            if (F == Comp.Current_class.Construct_method)
            {
                string call = gen_call_construct(Comp.Current_class.Base_, "this");
                if (call != "")
                    o.Add(spaces_prefix + sp(4) + call);
            }
            //-------------------------- 'native ?'
            if (F.Modifiers[(int)Function.Fun_mod.NATIVE])
            {
                o.Add(F.Native_code);
                o.Add("}");
                return;
            }
            //-------------------------- 'recursive ?'
            spaces_prefix = sp(4);
            bool recur = F.Modifiers[(int)Function.Fun_mod.RECURSIVE];
            if (recur)
            {
                o.Add(spaces_prefix + "if (AL4_system.Recursion_counter" +
                        " > AL4_system.Max_recursion_deep)\r\n" +
                      spaces_prefix + sp(4) + "throw new " +
                      "TooDeepRecursionException();");
                o.Add(spaces_prefix + "AL4_system.Recursion_counter++;");
            }
            //-------------------------- 'local variables'
            bool object_var = false;
            bool dynamic_arr = false;
            foreach (Variable v in F.Local_var)
            {
                if (F.Param.Contains(v) || v.Names[v.Names.Count-1] == "THIS") continue;
                o.Add(spaces_prefix + "// init var: " + (total_init_var++).ToString());
                if (total_init_var == 341)
                { }

                o.Add(spaces_prefix + type_gen(v.Type_, v.Is_array, false) +
                    " " + v.Final_name + " = ");
                string iv = "";
                switch (v.Type_.Kind)
                {
                    case Type.Kind_type.BOOL: iv = "false"; break;
                    case Type.Kind_type.INT:
                    case Type.Kind_type.ENUM:
                    case Type.Kind_type.REAL: iv = "0"; break;
                    case Type.Kind_type.STR: iv = "\"\""; break;
                    case Type.Kind_type.CLASS:
                    	if (v.Type_.Final_name == "obj") {
                    		iv = "AL4_object.NoneObj_AL4_object.hard_link";
                    	}
                    	else iv = v.Type_.Final_name +
                        	 ".NoneObj_" + v.Type_.Final_name + ".hard_link"; 
                        object_var = true; break;
                }
                if (v.Is_array)
                {
                    iv = "new " + type_gen(v.Type_, true, false) + "(";
                    if (v.Type_.Kind == Type.Kind_type.CLASS)
                        iv += v.Type_.Final_name + 
                            ".NoneObj_" + v.Type_.Final_name + ".hard_link";
                    iv += ")";
                    if (!v.Is_fixed) dynamic_arr = true;
                }
                o[o.Count-1] += iv + ";";
            }
            //-------------------------- 'need try ?"
            if (F.Has_add || recur || object_var || dynamic_arr)
            {
                o.Add(spaces_prefix + "try {");
                spaces_prefix += sp(4);
            }
            //--------------------------- 'statements'
            foreach (Statement st in F.Block)
                statement_gen(st);
            if (F.Result != null && !(F.Block.Count > 0 && F.Block[F.Block.Count-1].Is_jump()))
                o.Add(spaces_prefix + "return RESULT;");
            //------------------------------ 'catch OutOfMemory'
            if (F.Has_add)
            {
                o.Add(spaces_prefix + "} catch (OutOfMemoryException E) {");
                o.Add(spaces_prefix + "  AL4_system.Any_exception(E);");
                o.Add(spaces_prefix + "  if (AL4_system.Recursion_counter > 1)");
                o.Add(spaces_prefix + "     throw;");
                o.Add(spaces_prefix + "  return");
                if (F.Result != null)
                    o[o.Count - 1] += " " + gen_none_val(F.Result.Type_);
                o[o.Count - 1] += ";";
            }
            //--------------------------- 'catch recursion too deep'
            if (recur)
            {
                o.Add(spaces_prefix.Substring(0, spaces_prefix.Length-4) + 
                "} catch (TooDeepRecursionException E) {");
                o.Add(spaces_prefix + "  AL4_system.Any_exception(E);");
                o.Add(spaces_prefix + "  if (AL4_system.Recursion_counter > 1)");
                o.Add(spaces_prefix + "     throw;");
                o.Add(spaces_prefix + "  return");
                if (F.Result != null)
                    o[o.Count - 1] += " " + gen_none_val(F.Result.Type_);
                o[o.Count - 1] += ";";
            }
            //--------------------------- 'finally...'
            if (recur || object_var || dynamic_arr || F.Has_add)
            {
                spaces_prefix = spaces_prefix.Substring(0, spaces_prefix.Length - 4);
                o.Add(spaces_prefix + "} finally {");
                if (F.Modifiers[(int)Function.Fun_mod.RECURSIVE])
                    o.Add(spaces_prefix + "  AL4_system.Recursion_counter--;");
                string save = spaces_prefix;
                spaces_prefix += sp(4);
                {
                    foreach (Variable v in F.Local_var)
                    {
                        if (F.Param.Contains(v) || v.Names[0] == "THIS" || v.Names[0] == "RESULT") continue;
                        gen_dispose_var(v);
                    }
                }
                spaces_prefix = save;
                o.Add(spaces_prefix + "}");
                spaces_prefix = spaces_prefix.Substring(0, spaces_prefix.Length - 4);
            }
            o.Add("}");
        }

        /*
        
        METHOD gen_dispose_var({Var} V|ariable_local) :
            CASE V.Is_array ?
                 CASE V.Final_name == "" ? V.Set_final_name(V.Names[*]) ;
                 o[] << spaces V.Final_name ".Clear();"
                 ==> ;
            CASE ?
            [V.Type_.Kind == 'CLASS'] ? 
                o[] << spaces V.Final_name ".Ref_dec_hard();"
            [V.Type_.Kind == 'STRUCTURE'] ?
                o[] << spaces "(" V.Final_name ").Discard_struct();"
            ; .
        */
        private void gen_dispose_var(Variable V)
        {
            if (V.Is_array)
            {
                if (V.Type_.Kind == Type.Kind_type.CLASS)
                    o.Add(spaces_prefix + V.Final_name + ".Release_objects_hard();");
                else o.Add(spaces_prefix + V.Final_name + ".Dispose();");
            }
            else if (V.Type_.Kind == Type.Kind_type.CLASS)
                o.Add(spaces_prefix + V.Final_name + ".Ref_dec_hard();");
        }

        /*
        INT level_expr|ession
        BOOL is_left_side
        BOOL close_br|acket_right_side
        INT line_current_statement|_will_be_placed

        METHOD statement_gen|erate({Statement} St|atement) :
            -------------------------------------- 'single statement generation'
            close_br = FALSE
            
            o[] << spaces "// stmt: " St.Total_stmt.Str 
                    " (Line:" (St.Line+1).Str ")"

            CASE St.Inline_index != "" ?
                 o[*] = o[*] " INLINE: " St.Inline_index 
                         " (" St.Total_stmt.Str ")"
            ;            
            CASE Comp.TEST_value && Comp.Generating_test && St.Line > 0 ?
                 o[] << spaces "AL4_system.Test_caller = "
                 CASE Comp.Current_class.Modifiers['ABSTRACT'] ?
                      -------------- 'all tests of abstract class are secondary'
                      o[*] = o[*] "AL4_system.Test_caller % 1000000L + " 
                      "" St.Line.Str " * 1000000L;"
                      
                 ELSE o[*] = o[*] St.Line.Str ";" ;
            ;
            CASE Comp.TEST_value && !Comp.Generating_test && St.Line > 0 && (
                 St.Work != 'CASE') && St.Work != 'COMMENT'
                 ?
                 FOR i|dummy IN [tcl[].Count TO St.Line] : tcl[] << -1 ;
                 CASE !(Comp.Current_fun.Is_trivial && (
                      Comp.Current_class.Modifiers['NATIVE']))
                      ?
                      //o[] << "// set tcl[" St.Line.Str "] = 0"
                      INT i_tcl INDEXING (INT, STR) = St.Line
                      tcl[i_tcl] = 0 ;
                 CASE !Comp.Current_fun.Modifiers['STATIC'] ? 
                      STR p|refix_test_lin = Comp.Current_class.Final_name "."
                 ;
                 STR r|ef_test_lines = p "test_lines"
                 "_" Comp.Current_class.Final_name 
                 "[" St.Line.Str "]"
                 
                 o[] << spaces "if (" r " == 0) " r 
                 " = AL4_system.Test_caller;"
            ;
            line_current_statement = o[].Count
            --------------------------------------- 'stmt'
            SILENT:
	            DEBUG:
		            CASE St.Total_stmt == 9999 ? NONE ;
		            //CASE St.Line+1 == 50 
		            //	 && Comp.Current_class.Final_name == "C_Compiler" 
		            //	 ? 
		            //     NONE ;
	            ;
            ;
            CASE St.Work ?
            ['ASSIGN']: STR assign|_what = generate_assign(St.{Assign})  
                     	CASE St.{Assign}.Dest.Var_arg.Final_name=="RESULT"
                     	     && Ending(assign,"RESULT = 0;")
                     	     && Starting(o[*].Trim,"//")
                     	     && Ending(o[*-1],"RESULT = 0;") 
                     	     ?
                     	     o[].Delete(o[].Count-1)
                     	ELSE o[] << assign ;
            ['APPEND']: STR append|_what = generate_append(St.{Assign})  
                     	o[] << append
            ['OUTPUT']: generate_output(St.{Assign})
            ['INPUT']:  generate_input(St.{Assign})
            ['BREAK']:  generate_break(St.{For})
            ['CONTINUE', 'NEXT']: generate_cont(St.{For})
            ['RETURN']: generate_return(St.{Case})
            ['CASE', 'ELSE']: gen_case(St.{Case})
            ['LIMIT']: gen_limit(St.{Limit})
            ['LOCAL']: gen_local(St.{Local})
            ['FOR']: generate_for(St.{For})
            ['PUSH']:   generate_push(St.{Assign})
            ['STOP']:   generate_stop(St.{Case})
            ['ASSERT']: generate_assert(St.{Case})
            ['DEBUG']:
                       CASE !Comp.Final && !St.{Assign}.Ignore ?
                            generate_block(St.Block_[]) ;
            ['COMMENT']: gen_comment_block(St.{Assign})
            ['CALL_NATIVE']: NONE ; .
        */
        int total_stmt_output_index;

        private int level_expr = 0;
        private bool is_left_side;
        private bool close_bracket_right_side;

        private void statement_gen(Statement St)
        {
            if (total_stmt_output_index == 557)
            { }
            o.Add(spaces_prefix + "// stmt: " + (total_stmt_output_index++).ToString());
            if (Comp.Test() && !Comp.Generating_test() && St.Work != Statement.Workflow.CASE)
            {
                int line = St.Line;
                if (line >= 0)
                {
                    while (tcl.Count <= line) tcl.Add(-1);
                    tcl[line] = 0;
                    o.Add(spaces_prefix + "test_lines[" + St.Line.ToString() +
                 "] = (test_lines[" + St.Line.ToString() + "] + 2) & 0xFFFFFF | 1;");
                }
            }

            switch (St.Work)
            {
                case Statement.Workflow.ASSIGNMENT: generate_assign((Assignment)St); break;
                case Statement.Workflow.APPEND: generate_append((Assignment)St); break;
                case Statement.Workflow.OUTPUT: generate_output((Assignment)St); break;
                case Statement.Workflow.INPUT: generate_input((Assignment)St); break;
                case Statement.Workflow.BREAK: generate_break((For)St); break;
                case Statement.Workflow.CONTINUE: generate_cont((For)St); break;
                case Statement.Workflow.RETURN: generate_return((Case)St); break;
                case Statement.Workflow.CASE:
                case Statement.Workflow.ELSE: gen_case((Case)St); break;
                case Statement.Workflow.FOR:
                case Statement.Workflow.FOREVER: generate_for((For)St); break;
                case Statement.Workflow.PUSH: generate_push((Assignment)St); break;
                case Statement.Workflow.STOP: generate_stop((Case)St); break;
                case Statement.Workflow.ASSERT: generate_assert((Case)St); break;
                case Statement.Workflow.COMMENT_BLOCK: gen_comment_block((Assignment)St); break;
            }
        }

        /*
        
		FUN Min|imum_of_two_integers(
			INT A|_value_1,
			INT B|_value_2) ==> INT
			:
   			CASE A < B ? RESULT = A
   			ELSE RESULT = B ; .
        
	
        METHOD generate_assign({Assign} A|ssignment) ==> STR,
        	RECURSIVE
        	:
			//DEBUG:
			//      CASE A.Total_stmt == 40132 ? NONE ;
			//;
            ---------------------------------------------------- 'ignore?'
            CASE A.Ignore ? ==> ;
            ---------------- 'exclude trap_add_ functions if debugging is off'
			CASE !Comp.TEST_value && !Comp.Debugging 
				 && A.Source.Fun_.Modifiers['TRAP_FUN']
				 && A.Source.Fun_.Trap_field.Trap_add_ == A.Source.Fun_
				 ?
			     ==> ;
            ---------------------------------------------------- 'left side'
            CASE A.Dest != NONE && A.Dest.Var_arg != Comp.NONE_c ?
                 ------------------------------ 'to an item of an objects array'
                 CASE A.Dest.Type_expr.Kind IN ['CLASS', 'STRUCTURE']
                 	  && A.Dest.Operation == 'INDEX'
                      ?
                      PUSH is_left_side = TRUE :
                           RESULT = RESULT spaces gen_expr(A.Dest.Arg1_)
                           ".set_obj(" ;
                           
                      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
                      RESULT = RESULT "(" gen_expr(A.Dest.Arg2_) "), "
                      STR a|ssigning_value 
                      	  a = gen_obj_expr(A.Source, A.Dest.Type_expr) 
                      CASE A.Dest.Type_expr.Kind == 'STRUCTURE' ? 
                           a = "((Structure_any)" a ".Obj).Clone()" ;
                      RESULT = RESULT a ");"
                             
                      CASE A.Source.Operation == 'FUN' && ! A.Dest.Is_weak
                      	   ?
                           RESULT = RESULT #NL spaces 
                           RESULT = RESULT gen_expr(A.Dest) ".Ref_dec_hard();"
                      ;
                      CASE A.Source.Operation == 'FUN' && A.Dest.Is_weak
                      	   ?
                           RESULT = RESULT #NL spaces 
                           RESULT = RESULT gen_expr(A.Dest) ".Ref_dec_weak();"
                      ;
                      RESULT = RESULT finish_assign_object(A) ==> ;
                 --------------------------------- 'to a scalar object variable'
                 BOOL scalar_obj = ! A.Dest.Is_array
                 {Type} type_dest = A.Dest.Type_expr 
                 scalar_obj &&= type_dest.Kind IN ['CLASS', 'STRUCTURE']
                 CASE ?
                 //[type_dest.Kind == 'CLASS' && A.Source.Operation IN [
                 //'FUN', 'BASE_FUN', 'SYSTEM_FUN']] ?
                 //     PUSH is_left_side = TRUE :
                 //          RESULT << spaces gen_expr(A.Dest) " = " ;
                 //     RESULT << gen_obj_expr(A.Source, type_dest) ";"
                 //     RESULT << finish_assign_object(A) ==>
                 [scalar_obj] ?
                      RESULT = RESULT spaces "AL4_object.Object_assign_"
                      CASE A.Dest.Is_weak ? RESULT = RESULT "weak"
                      ELSE RESULT = RESULT "hard" ;
                      //CASE A.Source.Operation == 'FUN'
                      //	   && A.Source.Fun_.Modifiers['NEW']
                      //	   ?
                      //     RESULT << "_noincref"
                      //;
                      PUSH is_left_side = TRUE :
                           RESULT = RESULT "(ref " gen_expr(A.Dest) ;
                      RESULT = RESULT ", " gen_obj_expr(A.Source, type_dest) 
                      RESULT = RESULT ".Obj);" finish_assign_object(A)
                      ------------------------------------------ 'need dec ref?'
                      CASE A.Source.Operation IN [
                           'FUN', 'BASE_FUN', 'SYSTEM_FUN']
                           ?
                           RESULT = RESULT #NL spaces gen_expr(A.Dest) 
                           ".Ref_dec_"
                                
                           CASE A.Dest.Is_weak ? RESULT = RESULT "weak" 
                           ELSE ..= RESULT "hard" ;
                           RESULT = RESULT "();" ;
                      ==>
                 ;
                 ---------- 'to a single symbol of a string in array of strings'
                 CASE A.Dest.Operation == 'INDEX' && (
                      A.Dest.Arg1_.Operation == 'INDEX')
                      ?
                      PUSH is_left_side = TRUE :
                           RESULT = RESULT spaces gen_expr(A.Dest.Arg1_.Arg1_) 
                           RESULT = RESULT ".set_str("
                           CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
                                
                           RESULT = RESULT "(" gen_expr(A.Dest.Arg1_.Arg2_) ")"
                           ", AL4_system.Change_single_symbol("
                      ;
                      RESULT = RESULT gen_expr(A.Dest.Arg1_.Arg1_) 
                      RESULT = RESULT ".get_str("
                      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
                      RESULT = RESULT "(" gen_expr(A.Dest.Arg1_.Arg2_) ")), "
                      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
                      RESULT = RESULT "(" gen_expr(A.Dest.Arg2_) ")"
                      
                      RESULT = RESULT ", " gen_expr(A.Source) "));" ==> ;
                 -------------------------- 'to a single symbol of a string'
                 CASE A.Dest.Operation == 'INDEX' && ! A.Dest.Arg1_.Is_array &&(
                      type_dest.Kind == 'STR')
                      ?
                      PUSH is_left_side = TRUE :
                           RESULT = RESULT spaces gen_expr(A.Dest.Arg1_)
                           RESULT = RESULT " = AL4_system.Change_single_symbol("
                      ;
                      RESULT = RESULT gen_expr(A.Dest.Arg1_) ", "
                      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
                      RESULT = RESULT "(" gen_expr(A.Dest.Arg2_) "), "
                      RESULT = RESULT gen_expr(A.Source) ");" ==> ;
                 ------------------------------ 'to an item of a strings array'
                 CASE A.Dest.Operation == 'INDEX' && (
                      type_dest.Kind == 'STR') && A.Dest.Arg1_.Is_array
                      ?
                      PUSH is_left_side = TRUE :
                           RESULT = RESULT spaces gen_expr(A.Dest) ;
                      CASE !close_br ?
                      	   RESULT = RESULT " = " gen_expr(A.Source) ";"
                      ELSE RESULT = RESULT gen_expr(A.Source) ");"
                      	   close_br = FALSE ; 
                      ==> ;
                 ------------------------------ 'to an object which can be NONE'
                 {Type} type_arg1 = A.Dest.Arg1_.Type_expr 
                 CASE A.Dest.Operation == 'FIELD' && (
                      type_dest.Kind IN ['CLASS', 'STRUCTURE'])
                      && type_arg1.Kind == 'CLASS' && (
                      type_arg1.Has_destructors)
                      ?
                      RESULT = RESULT spaces "if (!(" 
                      RESULT = RESULT gen_expr(A.Dest.Arg1_) ")"
                      CASE ! Ending(RESULT, "(Result)") && (
                           ! Ending(RESULT, "Result"))
                           ?
                           RESULT = RESULT ".Obj" ;
                      RESULT = RESULT ".Is_NONE_object)" #NL ;
                 ----------------------------------- 'all other cases'
                 PUSH is_left_side = TRUE :
                      CASE A.Dest.Is_fixed && A.Source.Operation == 'INDEX' && (
                           A.Source.Arg3_ != NONE)
                           ?
                           ------ 'special assign A[x TO y] to temp fixed array'
                           RESULT = RESULT spaces gen_expr(A.Dest) 
                           ".Dispose();" #NL
                           
                           RESULT = RESULT spaces gen_expr(A.Dest) " = "
                           PUSH is_left_side = FALSE :
	                            RESULT = RESULT "new " type_gen(type_dest, "AF")
	                            RESULT = RESULT "(" gen_expr(A.Source.Arg1_) ", "
	                            CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
	                            RESULT = RESULT "("gen_expr(A.Source.Arg2_) "), "
	                            CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
	                            RESULT = RESULT "(" gen_expr(A.Source.Arg3_) "));" 
	                            ==> ;
                      ;
                      CASE ?
                      [A.Dest.Is_array && (A.Source == NONE || (
                      	A.Source.Var_arg.Constant_value == "NONE"))] ?
                           --------------- 'an array is just declared, clear it'
                           do_not_release[] << A.Dest.Var_arg
                           CASE A.Dest.Is_fixed ?
                           		RESULT = RESULT spaces gen_expr(A.Dest) 
                           			".Nullify();"
                           ELSE RESULT = RESULT spaces gen_expr(A.Dest) 
                           			".Clear();" 
                           ;
                           ==>
                      [A.Dest.Is_array] ?
                           RESULT = RESULT spaces gen_expr(A.Dest) " = ("
                           BOOL fixed|_dest = A.Dest.Is_fixed 
                           PUSH is_left_side = FALSE :
	                            RESULT = RESULT type_gen(
	                            	type_dest, "A" F_if(fixed) )
	                            	
	                            RESULT = RESULT ")" gen_expr(A.Source) ";" 
	                            ==> ;
                      ;
                      RESULT = RESULT spaces gen_expr(A.Dest) ;
                 CASE !close_br && A.Source != NONE ? RESULT = RESULT " = " ;
                 CASE A.Dest.Var_arg.Is_stored_param ?
                      RESULT  = RESULT "(int)" ;
            ELSE RESULT = RESULT spaces ;
            ------------------------ 'assign right side'
            CASE A.Source != NONE ?
                 PUSH A.Dest :
	            	  CASE RESULT.Trim == "" && A.Source.Operation !IN [
	            	 	   'FUN', 'BASE_FUN', 'SYSTEM_FUN']
	            	 	   ?
	            	       dummy_var += 1 
	            	       RESULT = "var dummy" dummy_var.Str " = " 
	            	       
	            	       A.Dest = {Expr}(Operation = 'VAR',
	            	       	Var_arg = {Var}(Line = 0,
	            	       	Type_ = A.Source.Type_expr))
	            	       	
	            	       A.Dest.Var_arg.Set_final_name("dummy" dummy_var.Str) 
	            	  ; 
	                  CASE A.Source.Var_arg == Comp.NONE_c ?
	                       RESULT = RESULT gen_none_val(type_dest)
	                  ELSE STR r|ight_side = gen_expr(A.Source).remove_br
	                       CASE type_dest.Kind IN ['ENUM']
	                       		&& TRUE // A.Source.Type_expr.Kind !IN ['BYTE', 'ENUM']
	                       		?
	                            r = "(byte)(" r ")" ;
	                       RESULT = RESULT r ;
	                  CASE close_br ? RESULT = RESULT ")" ;
	                  close_br = FALSE     
	                  RESULT = RESULT ";" finish_assign_object(A) ==>      
                 ;     
            ;
            RESULT = RESULT ";"
            close_br = FALSE .
            
   		INT dummy_var|iable_to_assign_inplace_none
            
        METHOD gen_obj_expr(
            {Expr} E|xpression,
            {Type} T|ype_of_object) ==> STR 
            :
            ------------------------------------ 'NONE / not NONE'
            CASE E.Var_arg == Comp.NONE_c ?
                 RESULT = gen_none_val(T)
            ELSE RESULT = gen_expr(E) ; 
            ------------------------------------ '{new object}(), OWNED BY'
            CASE E.Owned_ != NONE ?
                 RESULT = RESULT ".Owned_by(" gen_expr(E.Owned_) ")" ; .
            
            
            
        METHOD finish_assign_object({Assign} A|ssignment) ==> STR :
           ------------------------ 'assign of new obj, init its fields'
           CASE new_init != NONE ?
                {Type} t|ype_object = A.Source.Type_expr
                CASE t.Kind IN ['BOOL', 'ENUM'] ? ==> ;
                RESULT = RESULT #NL gen_init_new_obj(A)
                CASE A.Dest != NONE && A.Source.Operation != 'FUN' ?
                	 STR call|_construct = gen_call_construct(
                	 	t, gen_expr(A.Dest))
                ;
                CASE call != "" ? RESULT = RESULT #NL spaces call ;
           		//new_init = NONE // very temporary decision 
           ;
           ------------------------ ', >> array[]'
           CASE A.Source.Array_ != NONE ?
                RESULT = RESULT #NL spaces 
                RESULT = RESULT gen_expr(A.Source.Array_) 
                RESULT = RESULT ".Add(" gen_expr(A.Dest) ");" ; .

        */
        private void generate_assign(Assignment A)
        {
            bool ra = false;
            if (A.Ignore) return;
            if (A.Dest != null && A.Dest.Var_arg != Comp.NONE_c)
            {
                bool was_left_side = is_left_side;
                is_left_side = true;
                try
                {
                    if (A.Dest.Is_array())
                    {
                        o.Add(spaces_prefix + gen_expr(A.Dest) + ".Clear();");
                        return;
                    }
                    add_lines(o, spaces_prefix + gen_expr(A.Dest));
                }
                finally { is_left_side = was_left_side; }
                if (A.Dest.Type_expr().Kind == Type.Kind_type.CLASS)
                {
                    string n = A.Dest.Type_expr().Final_name;
                    string hw = "";
                    if (A.Dest.Is_weak()) 
                        hw = "Obj.Assign_weak";
                    else hw = "Obj.Assign_hard";
                    string source = "";
                    if (A.Source.Var_arg == Comp.NONE_c) source = gen_none_val(A.Dest.Type_expr());
                    else source = gen_expr(A.Source);
                    o[o.Count - 1] = spaces_prefix + o[o.Count - 1].TrimStart() +
                        " = " + source +
                        "." + hw + "(" + o[o.Count - 1].TrimStart() + ");";
                    if (A.Source.Owned_ != null)
                        o.Add(spaces_prefix + gen_expr(A.Dest) + ".Obj.Owned_by(" +
                            gen_expr(A.Source.Owned_) + ");");
                    else if (A.Source.Operation == Expression.Operation_kind.NEW)
                        o.Add(spaces_prefix + gen_expr(A.Dest) + ".Ref_dec_hard();");
                    ra = true;
                }
                else if (!close_bracket_right_side) o[o.Count - 1] += " = ";
            }
            else o.Add(spaces_prefix);
            if (!ra)
            {
                if (A.Source.Var_arg == Comp.NONE_c)
                    o[o.Count - 1] += gen_none_val(A.Dest.Type_expr());
                else
                {
                    string r = remove_brackets(gen_expr(A.Source));
                    o[o.Count - 1] += r;
                }
                if (close_bracket_right_side)
                    o[o.Count - 1] += ")";
                o[o.Count - 1] += ";";
            }
            close_bracket_right_side = false;
            //------------------------- 'assign of new obj, init its fields'
            if (new_init != null)
            {
                Type t_init = new_init.Type_expr();
                gen_init_new_obj(A);
                string call = gen_call_construct(t_init, gen_expr(A.Dest));
                if (call != "") o.Add(spaces_prefix + call);
            }
            //------------------------ ', >> array[]'
            if (A.Source.Array_ != null)
            {
                o.Add(spaces_prefix + gen_expr(A.Source.Array_) + ".Add");
                if (A.Source.Array_.Is_weak())
                    o[o.Count - 1] += "_obj_weak";
                else o[o.Count - 1] += "_obj_hard";
                o[o.Count - 1] += "(" + gen_expr(A.Dest) + ");";
            }
        }

        /*
        
        FUN gen_call_construct({Type} C|lass_constructing_obj,
            STR Th|is_obj) ==> STR
            :
            ------------- 'call constructor from the nearest ancestor having it'
            {Type} cf|un_class = C
            FOR i|dummy IN [0 TO MAX_INT-1] :
                CASE cf == NONE ? BREAK i ;
                CASE cf.Construct != NONE ?
                    RESULT = "((" cf.Final_name ")(" Th
                    CASE Th != "this" ? RESULT = RESULT ".Obj" ;
                    RESULT = RESULT ")).Do." cf.Construct.Final_name "();" ==> ;
                cf = cf.Base_
            ; .
        */
        private string gen_call_construct(Type C, string Th)
        {
            Type cf = C;
            for (int i = 0; i < int.MaxValue; i++)
            {
                if (cf == null) break;
                if (cf.Construct_method != null)
                {
                    string R = "((" + cf.Final_name + ")(" + Th;
                    if (Th != "this") R += ".Obj";
                    R += "))." + cf.Construct_method.Final_name + "();";
                    return R;
                }
                cf = cf.Base_;
            }
            return "";
        }

        /*
        INT CNT_init_expr
        
        METHOD gen_init_new_obj({Assign} A|ssignment) ==> STR :
            {Expr} init_expr = new_init
            new_init = NONE
            FOR a IN init_expr.Assignments_[] :
                {Assign} aa|ssign_a = a.{Assign}
                CASE aa.Dest.Operation ?
                ['FIELD']:
                    PUSH aa.Dest.Arg1_ = A.Dest :
                         RESULT = RESULT #NL generate_assign_or_append(aa)
                    ;
                ['UNKNOWN']:
                	CASE aa.Source.Operation == 'FUN' ?
                	     PUSH aa.Source.This_ = A.Dest :
                		  	  RESULT = RESULT #NL generate_assign(aa) ;
                	ELSE RESULT = RESULT #NL generate_assign(aa) ;
                ['INDEX']:
                    CASE aa.Dest.Arg1_.Operation == 'FIELD' ?
                         PUSH aa.Dest.Arg1_.Arg1_ = A.Dest :
                              RESULT = RESULT #NL generate_assign_or_append(aa)
                         ;
                    ELSE Comp.Error("Init indexed"._Einit
                         " " aa.Dest.Arg1_.Operation.Name "?")
                    ;
                ['VAR']:
                    PUSH init_expr = NONE :
                         RESULT = RESULT #NL generate_assign_or_append(aa)
                    ;
                         
                ['BINARY', 'FUN', 'BASE_FUN', 'SYSTEM_FUN', 'NEW_OBJ', 
                 'ARRAY', 'AS', 'CONSTANT', 'INT2REAL', 'NOT_B', 'NOT', 'NEG']:
                    Comp.Error("Unknown init of"._Eunk " "
                    "" aa.Dest.Operation.Name) ;
            ; .
        */
        static int CNT_gen_init_new_obj;

        private void gen_init_new_obj(Assignment A)
        {
            if (++CNT_gen_init_new_obj == 97)
            { }
            
            Expression init_expr = new_init;
            new_init = null;
            foreach (Statement a in init_expr.Assignments_)
            {
                Assignment aa = (Assignment)a;
                switch (aa.Dest.Operation)
                {
                    case Expression.Operation_kind.FIELD:
                        Expression save_arg1 = aa.Dest.Arg1_;
                        aa.Dest.Arg1_ = A.Dest;
                        generate_assign_or_append(aa);
                        aa.Dest.Arg1_ = save_arg1;
                        break;
                    case Expression.Operation_kind.INDEX:
                        if (aa.Dest.Arg1_.Operation == Expression.Operation_kind.FIELD)
                        {
                            save_arg1 = aa.Dest.Arg1_.Arg1_;
                            aa.Dest.Arg1_.Arg1_ = A.Dest;
                            generate_assign_or_append(aa);
                            aa.Dest.Arg1_.Arg1_ = save_arg1;
                        }
                        else Comp.Error("Init indexed " +
                            Expression.Operation_kind_names[(int)aa.Dest.Operation] +
                            "?");
                        break;
                    case Expression.Operation_kind.VAR:
                        Expression save = init_expr;
                        init_expr = null;
                        generate_assign_or_append(aa);
                        init_expr = save;
                        break;
                    default: Comp.Error("Unknown init of " + Expression.Operation_kind_names[
                        (int)aa.Dest.Operation]);
                        break;
                }
            }
        }

        /*
        
        METHOD generate_assign_or_append(
        	{Assign} A|ssign_or_append) ==> STR
        	:
            CASE A.Work ?
                ['ASSIGN']: RESULT = RESULT generate_assign(A)
                ['APPEND']: RESULT = RESULT generate_append(A)
                
                ['OUTPUT', 'INPUT', 'BREAK', 'NEXT', 'CONTINUE', 'RETURN',
                 'CASE', 'ELSE', 'FOR', 'PUSH', 'STOP', 'ASSERT',
                 'COMMENT', 'DEBUG', 'CALL_NATIVE', 'LIMIT', 'LOCAL']:
                   Comp.Error("Invalid field initialization "
                   "operation"._Einvalid ) ; .
        */
        private void generate_assign_or_append(Assignment A)
        {
            switch (A.Work)
            {
                case Statement.Workflow.ASSIGNMENT:  generate_assign(A); break;
                case Statement.Workflow.APPEND: generate_append(A); break;
                default: Comp.Error("Invalid init field opoeration");
                    break;
            }
        }

        private void add_lines(List<string> A, string L)
        {
            int Len = L.Length;
            for (int i = 0; i < Len; i++)
            {
                if (L == "") return;
                int p = L.IndexOf("\r\n");
                if (p < 0)
                {
                    A.Add(L);
                    return;
                }
                A.Add(L.Substring(0, p));
                L = L.Substring(p + 2);
            }
        }

        /*
        
        METHOD generate_append({Assign} A|ppend_stmt) ==> STR :
            PUSH is_left_side = TRUE : RESULT = RESULT spaces gen_expr(A.Dest) ;
            CASE A.Dest.Is_array ?
                 STR app|ending = ".Add"
                 CASE A.Source.Var_arg == Comp.NONE_c ?
                      STR a|ppending_value_str = gen_none_val(A.Dest.Type_expr)
                 ELSE a = gen_expr(A.Source).remove_br ;
                 
                 CASE ?
                 [A.Source.Type_expr.Kind == 'STRUCTURE' 
                  && A.Source.Type_expr.Final_name[0] == "S"] ?
                      a = "((Structure_any)" a ".Obj).Clone()" ;
                 app = app "(" a ");"
                 RESULT = RESULT app ==> ;
            CASE close_br ?
	             app = " " gen_expr(A.Dest).remove_br
	             app = app " + " gen_expr(A.Source).remove_br ");"
	             close_br = FALSE
            ELSE app = " += " gen_expr(A.Source).remove_br ";" ;
            RESULT = RESULT app .
        */
        private void generate_append(Assignment A)
        {
            bool was_left_side = is_left_side;
            is_left_side = true;
            try
            {
                o.Add(spaces_prefix + gen_expr(A.Dest));
            }
            finally { is_left_side = was_left_side; }
            if (A.Dest.Is_array())
            {
                string adding = ".Add";
                if (A.Dest.Type_expr().Kind == Type.Kind_type.CLASS && !A.Source.Is_new())
                {
                    if (A.Dest.Is_weak()) adding += "_obj_weak";
                    else adding += "_obj_hard";
                }
                if ((A.Source.Var_arg != null) && (A.Source.Var_arg == Comp.NONE_c))
                    adding += "(" + gen_none_val(A.Dest.Type_expr()) + ");";
                else
                    adding += "(" + remove_brackets(gen_expr(A.Source)) + ");";
                o[o.Count-1] += adding;
                return;
            }
            string append = " += " + remove_brackets(gen_expr(A.Source)) + ";";
            o[o.Count-1] += append;
        }

        /*
        METHOD generate_output({Assign} A|_output) :
			STR out|_what = gen_expr(A.Source).remove_brackets 
            o[] << spaces "AL4_system.Write(" out ");" .
        */
        private void generate_output(Assignment A)
        {
            o.Add(spaces_prefix + "Console.Write(" + remove_brackets(gen_expr(A.Source)) + ");");
        }

        /*
        METHOD generate_input({Assign} A|_input_stmt) :
            CASE A.Dest == NONE ? 
                 //CASE Comp.TEST_value ? ==> ;
                 o[] << spaces "Console.ReadLine();" ==> ;
            CASE A.Dest.Type_expr.Kind == 'STR' ?
                o[] << spaces 
                o[*] = o[*] gen_expr(A.Dest) 
                o[*] = o[*] " = AL4_system.Null_to_EOF(Console.ReadLine());" ==>
            ;
            STR temp|_name = "tmp" A.Line.Str
            o[] << spaces "string " temp ";"
            
            o[] << spaces "AL4_system.Null_to_EOF(Console.ReadLine(" 
            	   "" temp "));"
            	   
            PUSH is_left_side = TRUE : o[] << spaces gen_expr(A.Dest) ;
            o[*] = o[*] " = Safe_convert(" temp ");" .
        */
        private void generate_input(Assignment A)
        {
            if (A.Dest == null)
            {
                if (Comp.Test()) return;
                o.Add(spaces_prefix + "Console.ReadLine();");
                return;
            }
            if (A.Dest.Type_expr().Kind == Type.Kind_type.STR)
            {
                o.Add(spaces_prefix + gen_expr(A.Dest) + " = Console.ReadLine();");
                return;
            }
            string temp = "tmp" + o.Count.ToString();
            o.Add(spaces_prefix + "string " + temp + ";");
            o.Add(spaces_prefix + "Console.ReadLine(" + temp + ");");
            bool was_left_side = is_left_side;
            is_left_side = true;
            try
            {
                o.Add(spaces_prefix + gen_expr(A.Dest));
            }
            finally { is_left_side = was_left_side; }
            o[o.Count-1] += " = Safe_convert(" + temp + ");";
        }

        /*
        
        STR used_brk|_labels[]
        
        METHOD generate_break({For} Br|eak_stmt) :
	        used_brk[] << "Brk_" Br.Loop_.Total_stmt.Str
            o[] << spaces "goto Brk_" Br.Loop_.Total_stmt.Str ";" .
        */
        private void generate_break(For Br)
        {
            o.Add(spaces_prefix + "goto Brk" + Br.Loop_.Line.ToString() + ";");
        }

        /*
        
        METHOD generate_cont({For} Cont|inue_stmt) :
	        CASE Cont.Work == 'NEXT' ? 
	             STR i|ndex_var = Cont.Loop_.Index_var
	             o[] << spaces i " = " i
	             CASE Cont.Loop_.Downto ? 
	                  o[*] = o[*] " - "
	             ELSE o[*] = o[*] " + " ;
	             o[*] = o[*] "Math.Max(0, " gen_expr(Cont.By) "-1);"
	        ;
            o[] << spaces "goto " Cont.Loop_.Continue_label ";" .
        */
        private void generate_cont(For Cont)
        {
            o.Add(spaces_prefix + "goto Cont" + Cont.Loop_.Line.ToString() + ";");
        }

        /*
        
        METHOD generate_return({Case} Ret|urn_dummy) :
            CASE Comp.Current_fun.Result == NONE ?
                o[] << spaces "return;" ==> ;
            o[] << spaces "return RESULT;" .
            
        */
        private void generate_return(Case Ret)
        {
            if (Comp.Current_fun.Result == null)
            {
                o.Add(spaces_prefix + "return;");
                return;
            }
            o.Add(spaces_prefix + "return RESULT;");
        }

        /*
        
 		METHOD gen_sequential_case(
 			{Case} Sw|itch_stmt,
 			INT Index|_in_block INDEXING {Statement}), RECURSIVE
 			:
			CASE Sw.Block_[Index].Work != 'ELSE' ?
			     STR cond|ition_if = gen_expr(Sw.Block_[Index].{Case}.Condition) 
	 			 o[] << spaces "if (" cond.remove_br ") {"
	 			 BOOL close_if = TRUE 
			;
			CASE use_profiler.[0] IN "BA" && !Comp.Final ? 
                 STR n|ame_cnt = make_cnt(Sw.Block_[Index].Line) ;
 			generate_block(Sw.Block_[Index].{Case}.Block_[])
 			CASE n != "" ? 
 			     o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
 			     o[*] = o[*] ", ref CNT1_" n ");" ;
 			CASE close_if ?
 				 o[] << spaces "}" ;
 			CASE Index >= Sw.Block_[].Count-1 ? ==> ;
 			o[] << spaces "else {"
 			PUSH line_current_statement = o[].Count :
	 			 PUSH spaces = spaces sp(4) :
	 			      gen_sequential_case(Sw, Index+1) ;
 			;
 			o[] << spaces "}" .
 			
 		METHOD make_cnt(INT line|_number_from0) ==> STR :
 			cnt_int += 1
 			
 			STR name|_cnt = Comp.Current_fun.Final_name 
 				"_Line" (line+1).Str "__" cnt_int.Str
 				
            o[].Insert(line_with_cnt,  "public static long CNT1_" name ";") 
            o[].Insert(line_with_cnt,  "public static long CNT_" name ";") 
			-------------------- 'increment counter, check if it is equal to...'
            o[] << spaces "if (AL4_system.inc_cnt(ref CNT_" name 
            o[*] = o[*] ", ref CNT1_" name ") == 0)"
            o[] << spaces "{ }"
            RESULT = name .
 			
 		INT case_count|er_tmp
	
        METHOD gen_case({Case} Sw|itch_stmt) :
            ------------------------------------- 'sequential ?'
            CASE Sw.Condition == NONE ?
                 gen_sequential_case(Sw, 0) ==> ;
            ------------------------------------- 'by type of expression'
            CASE Sw.Condition.Type_expr.Kind ?
                ['BOOL']:
                    STR cond|ition_expression = gen_expr(Sw.Condition).remove_br 
                    o[] << spaces "if (" cond ") {"
                    CASE Sw.Block_[0].Work != 'ELSE' ?
                         CASE use_profiler.[0] IN "BA" && !Comp.Final ?
                              PUSH spaces = spaces "  /" "**" "/" :
                              	   STR n|ame_cnt = make_cnt(Sw.Block_[0].Line) ;
                         ;
                         generate_block(Sw.Block_[0].Block_[])
                         CASE n != "" ? 
                              o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
                              		 ", ref CNT1_" n ");" 
                         ;
                    ;
                    CASE Sw.Block_[*].Work == 'ELSE' ?
                         o[] << spaces "} else {"
                         n = ""
                         CASE use_profiler.[0] IN "BA" && !Comp.Final ?
                              PUSH spaces = spaces "  /" "**" "/" :
                              	   n = make_cnt(Sw.Block_[*].Line) ;
                         ;
                         generate_block(Sw.Block_[*].Block_[])
                         CASE n != "" ? 
                              o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
                              		 ", ref CNT1_" n ");" 
                         ;
                    ;
                ['STR']:
                    STR t|emp_index = Sw.Line.Str "_" case_count.Str
                    case_count += 1
                    CASE Sw.Inline_index.has_digits ?
                         t = t "_" Sw.Inline_index ;
                    o[] << spaces "int tmp" t " = -1;"
                    
                    o[] << spaces "string str" t "=" 
                    o[*] = o[*] gen_expr(Sw.Condition) ";"
                            
                    gen_calc_str_index(Sw, t)
                    o[] << spaces "switch (tmp" t ") {"
                    FOR cas IN Sw.Block_[] :
                        CASE cas.Work != 'ELSE' ?
                             o[] << spaces sp(4) "case " cas.Index.Str ":"
                        ELSE o[] << spaces sp(4) "default:" ;
                        PUSH spaces = spaces sp(8) :
                             n = ""
                        	 CASE use_profiler.[0] IN "BA" && !Comp.Final ? 
                        	      PUSH spaces = spaces "  /" "**" "/" :
                              	  	   n = make_cnt(cas.Line) ;
                        	 ;
                             generate_block(cas.Block_[])
	                         CASE n != "" ? 
	                              o[] << spaces "  AL4_system.inc_cnt(ref CNT_" 
	                              o[*] = o[*] n ", ref CNT1_" n ");" ;
                             CASE !cas.Block_[*].Is_jump ?
                                  o[] << spaces "break;" ;
                        ;
                    ;
                ['ENUM', 'INT']:
                    o[] << spaces "switch (" 
                    o[*] = o[*] gen_expr(Sw.Condition) ") {"
                    gen_switch_int_enum_cases(Sw)
                ['REAL', 'CLASS', 'STRUCTURE']: 
                    NONE ;
            o[] << spaces "}" .
            
        FUN has_digits(STR S|tring_char_test) ==> BOOL :
        	FOR i IN [0 TO S.Len-1] :
        	    CASE S.[i] IN "0123456789" ? RESULT = TRUE ==> ;
        	; .
        	
        INT total_lim|it_statements
        	
        METHOD gen_limit({Limit} Lim|it_statement) :
	        total_lim += 1
        	STR tl|_variable = "limit_st" total_lim.Str
	        o[] << spaces "int " tl " = AL4_system.limit_by_"
	        CASE Lim.By_what ? 
	        ['TIME']: o[*] = o[*] "time"
	        ['FUNC']: o[*] = o[*] "func"
	        ['LOOPS']: o[*] = o[*] "loop" ;
        	o[*] = o[*] "(" gen_expr(Lim.Condition)
        	CASE Lim.By_what == 'TIME' ? 
        	     o[*] = o[*] ", " 
        	     CASE Lim.Units ? 
        	     ['MILLISEC']: o[*] = o[*] "0"
        	     ['SEC']: o[*] = o[*] "1"
        	     ['MIN']: o[*] = o[*] "2"
        	     ['HOUR']: o[*] = o[*] "3"
        	     ['DAYS']: o[*] = o[*] "4" ;
        	;
        	o[*] = o[*] ");"
        	--------------------- 'body of LIMIT'
        	o[] << spaces "try {"
        	PUSH spaces = spaces #TAB :
        	     o[] << spaces "try {"
        	     PUSH spaces = spaces #TAB :
        	          generate_block(Lim.Block_[]) ;
        	     o[] << spaces "}" 
        	     o[] << spaces "catch(E_Limit_exceeded eL) { "
        	     o[] << spaces #TAB "if (eL.id != " tl ")"
        	     o[] << spaces #TAB#TAB"throw;"
        	     o[] << spaces "}"
        	;
        	o[] << spaces "}"
        	o[] << spaces "finally {"
        	o[] << spaces #TAB "AL4_system.dismiss_limit(" tl ");"
        	o[] << spaces "}" .
        	
        METHOD gen_local({Local} Loc|al_statement) :
        	--------------------- 'body of LIMIT'
        	object_var = FALSE
            dynamic_arr = FALSE
            fixed_arr = FALSE
            list_temps_released = FALSE
            INT o_pos|ition = o[].Count
            init_local_vars(Comp.Current_fun, Loc)
            BOOL need_try = o_pos < o[].Count
            CASE need_try ? 
        		 o[] << spaces "try {"
            ;
        	PUSH spaces = spaces #TAB :
        	     generate_block(Loc.Block_[])
        	;
        	CASE need_try ? 
	        	 o[] << spaces "}"
	        	 o[] << spaces "finally {"
	        	 dispose_local_vars(Comp.Current_fun, Loc)
	        	 o[] << spaces "}" 
        	; .
        	
        */
        private void gen_case(Case Sw)
        {
            if (Sw.Condition == null)
            {
                o.Add(spaces_prefix + "if (" + remove_brackets(gen_expr((((Case)Sw.Block_[0]).Condition))) + ") {");
                generate_block(Sw.Block_[0].Block_);
                for (int i = 1; i < Sw.Block_.Count; i++)
                {
                    if (Sw.Block_[i].Work == Statement.Workflow.ELSE)
                        o.Add(spaces_prefix + "} else {");
                    else o.Add(spaces_prefix + "} else if (" + remove_brackets( 
                        gen_expr( ((Case) Sw.Block_[i]).Condition)) + ") {");
                    generate_block(((Case)Sw.Block_[i]).Block_);
                }
                o.Add(spaces_prefix + "}");
                return;
            }
            switch (Sw.Condition.Type_expr().Kind)
            {
                case Type.Kind_type.BOOL:
                    o.Add(spaces_prefix + "if (" + remove_brackets(gen_expr(Sw.Condition)) + ") {");
                    if (Sw.Block_[0].Work != Statement.Workflow.ELSE)
                        generate_block(Sw.Block_[0].Block_);
                    if (Sw.Block_[Sw.Block_.Count - 1].Work == Statement.Workflow.ELSE)
                    {
                        o.Add(spaces_prefix + "} else {");
                        generate_block(Sw.Block_[Sw.Block_.Count - 1].Block_);
                    }
                    break;
                case Type.Kind_type.STR:
                    string t = Sw.Line.ToString();
                    o.Add(spaces_prefix + "int tmp" + t + " = -1;");
                    o.Add(spaces_prefix + "string str" + t + " = " + 
                        gen_expr(Sw.Condition) + ";");
                    gen_calc_str_index(Sw, t);
                    o.Add(spaces_prefix + "switch (tmp" + t + ") {");
                    for (int icas = 0; icas < Sw.Block_.Count; icas++)
                    {
                        Statement cas = Sw.Block_[icas];
                        if (((Case)cas).Work != Statement.Workflow.ELSE)
                            o.Add(spaces_prefix + sp(4) + "case " + icas.ToString() + ":");
                        else o.Add(spaces_prefix + sp(4) + "default:");
                        string save_sp = spaces_prefix;
                        spaces_prefix += sp(8);
                        try
                        {
                            generate_block(cas.Block_);
                            if (cas.Block_.Count == 0 || !cas.Block_[cas.Block_.Count-1].Is_jump())
                                o.Add(spaces_prefix + "break;");
                        }
                        finally { spaces_prefix = save_sp; }
                    }
                    break;
                case Type.Kind_type.ENUM:
                case Type.Kind_type.INT:
                    o.Add(spaces_prefix + "switch (" + gen_expr(Sw.Condition) + ") {");
                    gen_switch_int_enum_cases(Sw);
                    break;
            }
            o.Add(spaces_prefix + "}");
        }

        /*
        INT total_case|_count

        METHOD gen_calc_str_index(
        {Case} Sw|itch_by_str, STR T|emp_index)
            :
            o[] << spaces "switch ((str" T " + (char)0)[0]) {"
            STR all_s|trings[]
            INT all_i|ndexes[]
            
            FOR cas IN Sw.Block_[] :
                FOR val IN cas.{Case}.Values[] :
                    all_s[] << val.Str_c
                    all_i[] << cas.Index ;
            ;
            FOR s IN all_s[] :
                CASE all_i[s.Index] < 0 ? CONTINUE s ;
                o[] << spaces "case " s.as_char ": // case " total_case.Str
                total_case += 1
                CASE s != #0 ?
	                 o[] << spaces sp(4) "if (str" T " == " s.as_str.remove_br 
	                     ") tmp" T " = " all_i[s.Index].Str ";"
                ELSE
                	 o[] << spaces sp(4) "if (str" T " == " #QU "\0" #QU 
	                     " || str" T " == " #QU#QU 
	                     ") tmp" T " = " all_i[s.Index].Str ";"
                ;     
                    
                FOR i IN [s.Index+1 TO all_s[].Count-1] :
                    CASE s.[0] != all_s[i].[0] ? CONTINUE i ;
                    INT i_i|ndexing INDEXING (STR,INT) = i     
                    
                    o[] << spaces sp(4) "else if (str" T " == " all_s[i].as_str
                           ") tmp" T " = " all_i[i_i].Str ";"
                           
                    all_i[i_i] = -1 ;
                o[] << spaces sp(4) "break;" ;
            o[] << spaces "}" .
        */
        int CNT_case;

        private void gen_calc_str_index(Case Sw, string t)
        {
            o.Add(spaces_prefix + "switch ((str" + t + " + (char)0)[0]) {");
            List<string> all_s = new List<string>();
            List<int> all_i = new List<int>();
            for (int i = 0; i < Sw.Block_.Count; i++)
            {
                Case cas = (Case)Sw.Block_[i];
                foreach (Variable val in cas.Values)
                {
                    all_s.Add(val.Str_c);
                    all_i.Add(i);
                }
            }
            for (int i = 0; i < all_s.Count; i++)
            {
                string s = all_s[i];
                if (all_i[i] < 0) continue;
                if (s == "-")
                { }

                if (CNT_case == 317)
                { }

                o.Add(spaces_prefix + "case " + as_char(s) + ":" + " // case " + (CNT_case++).ToString());
                if (CNT_case == 150)
                { }

                o.Add(spaces_prefix + sp(4) + "if (str" + t + " == " +
                    remove_brackets(as_str(s)) + ") tmp" + t + " = " + all_i[i].ToString() + ";");
                for (int j = i + 1; j < all_s.Count; j++)
                {
                    if ((s + (char)0)[0] != (all_s[j] + (char)0)[0]) continue;
                    o.Add(spaces_prefix + sp(4) + "else if (str" + t + " == " +
                        as_str(all_s[j]) + ") tmp" + t + " = " + all_i[j].ToString() +
                        ";");
                    all_i[j] = -1;
                }
                o.Add(spaces_prefix + sp(4) + "break;");
            }
            o.Add(spaces_prefix + "}");
        }

        /*
        
        METHOD gen_switch_int_enum_cases({Case} Sw|itch_stmt) :
            FOR cas IN Sw.Block_[] :
                {Case} c|ase_of_switch = cas.{Case}
                CASE c.Work == 'CASE' && c.Values[].Count > 0 ?
                     FOR v IN cas.{Case}.Values[] :
                         o[] << spaces sp(4) "case " v.Int_c.Str ":" ;
                ;
                CASE c.Work == 'CASE' && c.Values[].Count == 0 ?
                     FOR r IN [c.Range1.Var_arg.Int_c TO (
                               c.Range2.Var_arg.Int_c)] :
                         o[] << spaces sp(4) "case " r.Str ":" ;
                ;
                CASE cas.Work == 'ELSE' ?
                     o[] << spaces sp(4) "default:" ;
                PUSH spaces = spaces sp(8) :
                     CASE use_profiler.[0] IN "BA" && !Comp.Final ?
                          PUSH spaces = spaces "  /" "**" "/" :
                          	   STR n|ame_cnt = make_cnt(cas.Line) ;
                     ;
                     generate_block(cas.Block_[])
                     CASE n != "" ? 
                          o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
                          		 ", ref CNT1_" n ");" 
                     ;
                     CASE cas.Block_[].Count == 0 || !cas.Block_[*].Is_jump ?
                          o[] << spaces "break;" ;
                ;
            ; .
        */
        private void gen_switch_int_enum_cases(Case Sw)
        {
            for (int i = 0; i < Sw.Block_.Count; i++)
            {
                Case cas = (Case)Sw.Block_[i];
                if (cas.Work != Statement.Workflow.ELSE)
                {
                    if (cas.Values.Count > 0)
                        foreach (Variable v in cas.Values)
                            o.Add(spaces_prefix + sp(4) + "case " + v.Int_c.ToString() + ":");
                    else
                        for (int v = cas.Range1.Var_arg.Int_c; v <= cas.Range2.Var_arg.Int_c;
                            v++)
                            o.Add(spaces_prefix + sp(4) + "case " + v.ToString() + ":");
                }
                else o.Add(spaces_prefix + sp(4) + "default:");
                string save = spaces_prefix;
                spaces_prefix += sp(8);
                try
                {
                    generate_block(cas.Block_);
                    if (cas.Block_.Count == 0 || !cas.Block_[cas.Block_.Count - 1].Is_jump())
                        o.Add(spaces_prefix + "break;");
                }
                finally { spaces_prefix = save; }
            }
        }

        /*
        
        FUNCTION as_char|acter(STR S|tr_where_from) ==> STR :
            CASE S == "" ? RESULT = "(char)0" ==> ;
            CASE S.[0].Ord < " ".Ord || S.[0].Ord == #QU.Ord || (
                 S.[0].Ord == "'".Ord || S.[0].Ord=="\".Ord || S.[0].Ord > 255)
                 ?
                 RESULT = "(char)" ((S (0).Char).[0].Ord.Str) ==> ;
            RESULT = "'" S.[0] "'" .
        */
        private string as_char(string S)
        {
            if (S == "") return "(char)0";
            if ((int)(S[0]) < (int)(' ') || S[0] == '\"' || S[0] == '\'' || (
               S[0] == '\\'))
               return "(char)" + ((int)(S + (char)0)[0]).ToString();
            return "'" + S[0] + "'";
        }

        /*
        
        FUNCTION as_str|ing(STR S|tr_where_from) ==> STR :
            BOOL in_str|ing = TRUE
            RESULT = #QU
            FOR i IN [0 TO S.Len-1] :
                CASE S.[i].Ord < " ".Ord || S.[i] == #QU || S.[i].Ord > 255 ?
                     CASE in_str ?
                          in_str = FALSE
                          RESULT = RESULT #QU ;
                     INT o|rdinal_char = S.[i].Ord
                     RESULT = RESULT " + (char)" o.Str
                ELSE 
                     CASE !in_str ?
                          in_str = TRUE
                          RESULT = RESULT " + " #QU ;
                     RESULT = RESULT S.[i] 
                     CASE S.[i] == "\" ? RESULT = RESULT "\" ;
                ;
            ;
            CASE in_str ? RESULT = RESULT #QU ;
            CASE "+" IN RESULT ? RESULT = "(" RESULT ")" ; .
        */
        private string as_str(string S)
        {
            bool in_str = true;
            string Result = "" + (Char)34;
            for (int i = 0; i < S.Length; i++)
            {
                if (S[i] < ' ' || S[i] == (Char)34)
                {
                    if (in_str)
                    {
                        in_str = false;
                        Result += (Char)34;
                    }
                    Result += " + (char)" + ((int)S[i]).ToString();
                }
                else 
                {
                    if (!in_str)
                    {
                        in_str = true;
                        Result += " + " + (Char)34;
                    }
                    Result += "" + S[i];
                    if (S[i] == '\\') Result += "" + '\\';
                }
            }
            if (in_str) Result += (Char)34;
            if (Result.Contains('+')) Result = "(" + Result + ")";
            //if (Result.IndexOf('\\') >= 0) Result = "@" + Result;
            return Result;
        }

        /*
        {For} nesting_for|_statements[]
        INT total_for|_counter
        BOOL list_temps_used

        METHOD generate_for({For} F|or_loop) :
		PUSH list_temps_used = FALSE :
            nesting_for[] << F
			CASE F.Unroll && F.Unroll_factor >= 0 && "U" IN Comp.Optimizations ?
			     unroll_for(F)
			     nesting_for[].Remove(F) ==> ;
			----------------------------------------- 'prepare for header'
			STR v|ar_loop = F.Var.Final_name
         	CASE F.Var.Type_.Kind IN ['ENUM'] ?
         	  	 STR to_b|yte_if_need = "(byte)" ;
        	CASE F.Var.Replaced ? v = F.Var.Replace_to_.Final_name ;
        	//DEBUG: v << "/" "*" F.Var.Total_i.Str "*" "/" ;
        	total_for += 1
            STR t|mp_indx = "_" F.Total_stmt.Str "_" total_for.Str
            CASE F.Array != NONE ? 
                 STR i|ndex_var = "idx" t "_" total_for.Str
                 STR i_type|_prefix = "int "
            ELSE i = F.Var.Final_name ;
            F.Index_var = i
            CASE ?
            [F.Infinite] ?
                 BOOL inf|initive = TRUE
                 o[] << spaces "while (true) {"
            [F.Range1 != NONE] ?
                 BOOL from_to_int = Comp.Int32 || F.Array != NONE
                 CASE from_to_int ? STR assign_from = "int"
                 ELSE assign_from = "long" ;
                 assign_from = assign_from " from" t " = "
                 -------------------------------- 'from'
                 CASE ?
                 [F.Array.Operation == 'CONSTANT'] ?
                     CASE !Comp.Int32 ? assign_from = assign_from "(int)" ;
                          
                     assign_from = assign_from "(" gen_expr(
                         F.Range1).remove_br ");"
                         
                 [F.Array != NONE && F.Downto] ?
                     CASE from_to_int ? assign_from = assign_from "(int)" ;
                          
                     assign_from = assign_from min_max("imin",
                       		 gen_expr(F.Range1).remove_br,
                       		 gen_expr(F.Array) ".Count-1") ";"
                       		 
                 [F.Array != NONE] ?
                     CASE from_to_int ? assign_from = assign_from "(int)" ;
                          
                      assign_from = assign_from min_max("imax", 
                       		 gen_expr(F.Range1).remove_br, "0") ";"
                       		 
                 ELSE
                     CASE from_to_int ? assign_from = assign_from "(int)" ;
                  	    
                     assign_from = assign_from "(" 
                  	   "" gen_expr(F.Range1).remove_br ");"
                 ;
                 o[] << spaces assign_from
             	 -------------------------------- 'to'
             	 CASE from_to_int ? 
             	      STR assign_to = "int"
             	 ELSE assign_to = "long" ;
             	 assign_to = assign_to " to" t " = "
             	  	    
                 CASE ?
                 [F.Array.Operation == 'CONSTANT' && !F.Has_next] ?
                     CASE from_to_int ? assign_to = assign_to "(int)" ;
                          
                  	 assign_to = assign_to "(" gen_expr(F.Range2).remove_br 
                  	  	   ");"
                  	  		    
                  	 o[] << spaces assign_to
                    
                     o[] << spaces "for (" i_type i " = from" t "; " i " "
                     CASE F.Downto ? o[*] = o[*] ">="
                     ELSE o[*] = o[*] "<=" ;
                     o[*] = o[*] " to" t "; " i
                     CASE F.Downto ? o[*] = o[*] "--"
                     ELSE o[*] = o[*] "++" ;     
                     o[*] = o[*] ") {"
                 [F.Array != NONE || F.Has_next] ?
                     CASE from_to_int ? assign_to = assign_to "(int)" ;
                          
                     CASE F.Downto ?
                          assign_to = assign_to min_max("imax",
                           		  gen_expr(F.Range2).remove_br, "0")
                           		  "; to" t "--;" 
                     ELSE assign_to = assign_to 
                       			  "(" gen_expr(F.Range2).remove_br 
                       			  "); to" t "++;"    
                     ;     
                       		 
                     o[] << spaces assign_to
                     
                     CASE F.Has_next ?
                          o[] << spaces "for (" i_type i " = from" t
                          CASE F.Downto ? 
                               o[*] = o[*] "+1"
                          ELSE o[*] = o[*] "-1";
                          o[*] = o[*] "; ;) {"
                          F.Continue_label = "Cont" t
                          o[] << spaces F.Continue_label ": "
                          CASE F.Downto ? o[*] = o[*] i "--;"
                          ELSE o[*] = o[*] i "++;" ;
                          o[] << spaces "if (" i
                          CASE F.Downto ? o[*] = o[*] " <= " 
                          ELSE o[*] = o[*] " >= " ;
                          o[*] = o[*] " to" t ") goto Brk_" F.Total_stmt.Str ";" 
                     ELSE
	                      o[] << spaces "for (" i_type
	                      o[*] = o[*] i " = from" t "; " i 

	                      CASE F.Downto ? 
	                           o[*] = o[*] ">"
	                      ELSE o[*] = o[*] "<" ;
	                      o[*] = o[*] " to" t "; " i 
	                      CASE F.Downto ? 
	                           o[*] = o[*] "--"
	                      ELSE o[*] = o[*] "++" ;
	                      o[*] = o[*] ") {"
                     ;
                      
                 [F.Downto] ?
                      CASE from_to_int ? assign_to = assign_to "(int)" ;
                           
                      assign_to = assign_to "(" 
                       	   "" gen_expr(F.Range2).remove_br ")"
                       	   "; to" t "--;"
                       		 
                      o[] << spaces assign_to
                      
                      o[] << spaces "for (" v " = from" t "; " v 
                       		 " > to" t "; " v "--) {"
                       		 
                 //[F.Array != NONE] ?
                 //     CASE from_to_int ? assign_to = assign_to "(int)" ;

                 //     assign_to = assign_to
                 //      "(" gen_expr(F.Range2).remove_br "); to" t "++;"

                 //     o[] << spaces assign_to
                      
                 //     o[] << spaces "for (int " i " = from" t "; " i
                 //     " < to" t "; " i "++) {"
                 ELSE 
                  	  CASE from_to_int ? assign_to = assign_to "(int)" ;
                  	       
                      assign_to = assign_to "(" 
                       	   "" gen_expr(F.Range2).remove_br ")" 
                       	   "; to" t "++;"
                       		      
                      o[] << spaces assign_to
                      
                  	  o[] << spaces "for (" v " = " to_b " from" t 
                  	   		 "; " v " < " to_b "to" t "; " v "++) {"
                 ;
            ELSE 
                 CASE F.Array.Operation == 'CONSTANT' ? 
                      o[] << spaces "int count" t 
                       		 " = " F.Array.Var_arg.Items_[].Count.Str ";"
                 ELSE
                      o[] << spaces "int count" t " = " gen_expr(F.Array)
	                     ".Count;"
                 ;
                 
                 CASE F.Has_next ?
                      o[] << spaces "for (" i_type i " = -1; ;) {"
                      F.Continue_label = "Cont" t
                      o[] << spaces F.Continue_label ": " i "++;" 
                      o[] << spaces "if (" i " >=  count" t ") "
                      		 "goto Brk_" F.Total_stmt.Str ";" 
                 ELSE
	                  o[] << spaces "for (" i_type i " = 0; " i 
	                  " < count" t "; " i "++) {"
                 ;
            ;
            CASE ?
            [F.Array.Operation == 'CONSTANT'] ?
             	 o[] << spaces sp(4) v "= (uint)" i 
             	  	 " < " F.Array.Var_arg.Items_[].Count.Str " ? new " 
             	 o[*] = o[*] type_gen(F.Array.Type_expr, "") "[]{"
             	 PUSH spaces = spaces sp(8) :
                      FOR ii IN [0 TO F.Array.Var_arg.Items_[].Count-1] :
                          o[] << spaces gen_const_value(
                           		   F.Array.Var_arg.Items_[ii])
                           		   
                          CASE ii < F.Array.Var_arg.Items_[].Count-1 ? 
                               o[*] = o[*] "," ;
                      ;
                 ;
                 o[] << spaces sp(4) "}[" i "] : "
                 CASE F.Array.Type_expr.Kind ?
                 ['BOOL']: o[*] = o[*] "false;"
                 ['ENUM', 'INT', 'REAL']: o[*] = o[*] "0;"
                 ['STR']: o[*] = o[*] #QU#QU";"
                 ['CLASS', 'STRUCTURE']: NONE ;
            [F.Array != NONE] ?
                 CASE F.Array.Type_expr.Kind ?
                 ['CLASS', 'STRUCTURE']:
                      o[] << spaces sp(4) 
                      "AL4_object.Object_assign_hard(" 
                      "ref " v ", " gen_expr(F.Array) ".get_obj(" i 
                      ").Obj);"
                 ['ENUM']:
	     			  o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      ".get_byte(" i ");"
                 ['BOOL']:
	     			  o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      ".get_bool(" i ");"
                 ['INT']:
	     			  o[] << spaces sp(4) v " = "
	     			  o[*] = o[*] gen_expr(F.Array) ".get_int(" i ");"
                 ['REAL']:
	     			  o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      ".get_real(" i ");"
                 ['STR']:
	     			  o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      ".get_str(" i ");"
                 ;
            ;
            ------------------------------------ 'LIMIT LOOPS present'
            CASE Comp.Has_LIMIT_LOOPS ? 
                 o[] << spaces sp(4) "AL4_system.total_loops += 1;"
            ;
            ------------------------------------ 'do not stop response'
			CASE "$NOLONGOP" !IN Comp.Defined_name[] ?
		         CASE !warning_nolongop ?
		              warning_nolongop = TRUE
		              
		              << "Option $NOLONGOP is not set: checking for long "
		              	 "operations is provided"._MOptionNolongop #NL
		         ;
		              	 
	             o[] << spaces sp(4) 
	             		"if (--AL4_system.global_activity_counter < 0)"
	             		
	             o[] << spaces sp(8) "AL4_system.check_long_operation();"
			;
            CASE use_profiler.[0] IN "LA" && !Comp.Final ?
                 PUSH spaces = spaces "  /" "**" "/" :
                 	  STR n|ame_cnt = make_cnt(F.Line) ;
            ;
            ------------------------------------ 'generate block'
            INT first_line|_of_for_block_code INDEXING STR = o[].Count
            o[] << "//***"
            F.Continue_label = "Cont" t
            generate_block(F.Block_[])
            CASE n != "" ? 
                 o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
                 		", ref CNT1_" n ");" 
                 ;
            -------------- 'call clear_list_temps if necessary, on each pass'
		    FOR j IN [first_line TO o[].Count-1] :
		        CASE o[j] == "//***" ? first_line = j
		        						BREAK j ;
		    ;
		    CASE list_temps_used ?
		    	 o[].Insert(first_line, 
		    	 	spaces "ArrayAny.clear_list_temps(List_temps);")
		    	 	
		    	 first_line += 1
		    ;
		    CASE o[first_line] == "//***" ? o[].Delete(first_line) ;
    		----------------------- 'ending FOR block'
            CASE !inf && F.Continued && !F.Has_next ?
                 o[] << spaces sp(4) F.Continue_label ": ;" ;
            o[] << spaces "}"
            CASE !inf && F.Breaked || F.Infinite || F.Has_next ?
                 CASE "Brk_" F.Total_stmt.Str IN used_brk[] || F.Has_next ? 
                      o[] << spaces "Brk" "_" F.Total_stmt.Str ": ;" ;
            ;
            nesting_for[].Remove(F)
		; .
		
		BOOL warning_nolongop
		
		FUNCTION min_max|_may_be_not_call(
		STR F|un_min_max, STR A|_operand1, STR B|_operand2) ==> STR
			:
			CASE A == B ? RESULT = A ==> ;
			RESULT = "AL4_system." F "(" A ", " B ")" .
		

            
   		METHOD unroll_for|_statement(
   			{For} F|or_to_unroll)
   			:
			{Expr} r1|_start = F.Range1
			{Expr} r2|_finish = F.Range2
			CASE r1.Operation == 'CONST' && r2.Operation == 'CONST' ?
			     CASE F.Downto ?
			          INT count|_pass = r1.Var_arg.Int_c - r2.Var_arg.Int_c + 1
			     ELSE count = r2.Var_arg.Int_c - r1.Var_arg.Int_c + 1 ;
			     CASE count == F.Unroll_factor && F.Unroll_factor <= 1024 || (
			     	  F.Unroll_factor == 0 && count <= 1024)
			     	  ?
			          unroll_all(F, count) ==> ;
			;
			STR v|ar_loop = F.Var.Final_name
        	CASE F.Var.Replaced ? v = F.Var.Replace_to_.Final_name ;
        	//DEBUG: v << "/" "*" F.Var.Total_i.Str "*" "/" ;
        	total_for += 1
        	STR t|mp_indx = "_" F.Total_stmt.Str "_" total_for.Str
            CASE F.Range1 != NONE ?
                 STR right|_side = gen_expr(F.Range1).remove_br
                 o[] << spaces "int from" t " = (int)" right ";"
                 CASE F.Downto ?
                      right = gen_expr(F.Range2).remove_br 
                      o[] << spaces "int to" t " = (int)" right
                      o[*] = o[*] " + " F.Unroll_factor.Str " - 1;"
                      o[] << spaces "for (" v " = from" t "; " v 
                      o[*] = o[*] " > to" t ";) {"
                 ELSE 
                 	  right = gen_expr(F.Range2).remove_br  
                      o[] << spaces "int to" t " = (int)" right
                      o[*] = o[*] " - " F.Unroll_factor.Str " + 1;"
                  	  o[] << spaces "for (" v " = from" t "; " v 
                      o[*] = o[*] " < to" t ";) {"
                 ;
            ELSE STR i|ndex_var = "idx" t "_" total_for.Str
            	 F.Index_var = i
            	 o[] << spaces "int last_idx" t " = 0;"
            	 right = gen_expr(F.Array)
                 o[] << spaces "int count" t " = " right ".Count;"
                 
                 o[] << spaces "for (int " i " = 0; " i 
                 " < count" t " - " F.Unroll_factor.Str ";) {"
                 
                 o[] << spaces sp(4) "last_idx" t " = " i ";"
            ;
            ------------------------------------ 'do not stop response'
            o[] << spaces sp(4) "if (--AL4_system.global_activity_counter < 0)"
            o[] << spaces sp(8) "AL4_system.check_long_operation();"
            ------------------------------------ 'generate block'
            INT first_line INDEXING STR
   		PUSH list_temps_used = FALSE :
            F.Continue_label = "Cont" t
            FOR j IN [0 TO F.Unroll_factor-1] :
                o[] << "// step #" (j+1).Str " from " F.Unroll_factor.Str
                CASE F.Array != NONE ?
                     CASE F.Array.Type_expr.Kind IN ['CLASS', 'STRUCTURE'] ?
                      o[] << spaces "AL4_object.Object_assign_hard(" 
                      "ref " v ", " gen_expr(F.Array) "[" i " + " j.Str 
                      "].Obj);"
                      
                 	 ELSE o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      "[" i " + " j.Str "];" ;
                ;
                F.Continue_label = "Cont_" F.Total_stmt.Str "_" j.Str
                CASE use_profiler IN "BA" && !Comp.Final ?
                     PUSH spaces = spaces "/" "**" "/" :
                     	  STR n|ame_cnt = make_cnt(F.Line) ; 
                ELSE n = "" ;
                generate_block(F.Block_[])
	            CASE n != "" ? 
	                 o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
	                 o[*] = o[*] ", ref CNT1_" n ");" ;
			    CASE F.Continued ?
			         o[] << spaces F.Continue_label ": ;" ;
			    CASE F.Range1 != NONE ?
			         CASE F.Downto ? o[] << spaces v "--;"
			         ELSE o[] << spaces v "++;" ;
			    ELSE o[] << spaces i "++;" ; 
            ;
   		;
            o[] << spaces "}"
            ---------------------- 'finish by a usual loop portion'
   		PUSH list_temps_used = FALSE :
            CASE F.Range1 != NONE ?
                 CASE F.Downto ?
                      o[] << spaces "to" t " -= " F.Unroll_factor.Str ";"
                      o[] << spaces "for (; " v " > to" t "; " v "--) {"
                 ELSE 
                 	  o[] << spaces "to" t " += " F.Unroll_factor.Str ";"
                  	  o[] << spaces "for (; " v " < to" t "; " v "++) {"
                 ;
            ELSE 
            	 o[] << spaces "for (int " i " = last_idx" t "; " i 
            			" < count" t "; " i "++) {"
                 CASE F.Array.Type_expr.Kind IN ['CLASS', 'STRUCTURE'] ?
                      o[] << spaces sp(4) "AL4_object.Object_assign_hard(" 
                      "ref " v ", " gen_expr(F.Array) "[" i "].Obj);"
                      
                 ELSE o[] << spaces sp(4) v " = " gen_expr(F.Array)
                      "[" i "];" ;
            ;
            ------------------------------------ 'do not stop response'
            o[] << spaces sp(4) "if (--AL4_system.global_activity_counter < 0)"
            o[] << spaces sp(8) "AL4_system.check_long_operation();"
            ------------------------------------ 'generate block'
            F.Continue_label = "Cont" t
            o[] << "//***"
	        first_line = o[].Count
	        generate_block(F.Block_[])
		    FOR k IN [first_line TO o[].Count-1] :
		        CASE o[k] == "//***" ? first_line = k
		        						BREAK k ;
		    ;
		    CASE list_temps_used ?
		    	 o[].Insert(first_line, spaces "ArrayAny."
		    	 	 "clear_list_temps(List_temps);")
		    	 	 
		    	 first_line += 1
		    ;
		    CASE o[first_line] == "//***" ? o[].Delete(first_line) ;
	    
            CASE F.Continued ?
                 o[] << spaces sp(4) F.Continue_label ": ;" ;
            o[] << spaces "}"
            CASE F.Breaked && "Brk_" F.Total_stmt.Str IN used_brk[] ?
                 o[] << spaces "Brk" "_" F.Total_stmt.Str ": ;" ;
   		;
			.
			
		METHOD unroll_all(
			{For} F|or_statement, INT Count_unroll)
			:
			BOOL dumm|_y_for_variable = "dummy" IN F.Var.Names[*]
			INT curr|ent_var_value = F.Range1.Var_arg.Int_c
			STR v|ar_loop = F.Var.Final_name
			CASE F.Var.Replaced ? v = F.Var.Replace_to_.Final_name ;
			//DEBUG: v << "/" "*" F.Var.Total_i.Str "*" "/" ;
			FOR pass|dummy IN [0 TO Count_unroll-1] :
			    CASE !dumm ?
			         o[] << spaces v " = " curr.Str ";" ;
			    PUSH F.Var.Is_const = TRUE :
			         F.Var.Int_c = curr
			         F.Continue_label = "Cont_" F.Total_stmt.Str "_" curr.Str
                     CASE use_profiler IN "BA" && !Comp.Final ?
                          PUSH spaces = spaces "  /" "**" "/" :
                          	   STR n|ame_cnt = make_cnt(F.Line) ; 
                     ELSE n = "" ;
			         generate_block(F.Block_[]) 
                     CASE n != "" ? 
                          o[] << spaces "  AL4_system.inc_cnt(ref CNT_" n 
                          o[*] = o[*] ", ref CNT1_" n ");" ;
			    ;
			    CASE F.Continued ?
			         o[] << spaces F.Continue_label ": ;" ;
			    CASE F.Downto ? curr -= 1
			    ELSE curr += 1 ;
			;
			CASE F.Breaked && "Brk_" F.Total_stmt.Str IN used_brk[] ?
				 o[] << spaces "Brk_" F.Total_stmt.Str ": ;" ;
			.   
	
        */
        private List<For> nesting_for = new List<For>();

        private void generate_for(For F)
        {
            nesting_for.Add(F);
            bool inf = false;
            if (F.Work == Statement.Workflow.FOREVER)
            {
                inf = true;
                o.Add(spaces_prefix + "while (true) {");
            }
            else
            {
                string v = F.Var.Final_name;
                string t = F.Line.ToString();
                if (F.Range1 != null)
                {
                    o.Add(spaces_prefix + "int from" + t + " = " + remove_brackets(gen_expr(F.Range1)) + ";");
                    o.Add(spaces_prefix + "int to" + t + " = " + remove_brackets(gen_expr(F.Range2)) + ";");
                    if (F.Downto)
                        o.Add(spaces_prefix + "for (" + v + " = from" + t +
                            "; " + v + " >= to" + t + "; " + v + "--) {");
                    else
                        o.Add(spaces_prefix + "for (" + v + " = from" + t +
                            "; " + v + " <= to" + t + "; " + v + "++) {");
                }
                else
                {
                    string i = "idx" + F.Var.Line.ToString();
                    o.Add(spaces_prefix + "int count" + t + " = " + gen_expr(F.Array) + ".Count;");
                    o.Add(spaces_prefix + "for (int " + i + " = 0; " + i +
                        " < count" + t + "; " + i + "++) {");
                    o.Add(spaces_prefix + sp(4) + v + " = " + gen_expr(F.Array) +
                        "[" + i + "]");
                    if (F.Array.Type_expr().Kind == Type.Kind_type.CLASS)
                        o[o.Count - 1] += ".Obj.Assign_hard(" + v + ")";
                    o[o.Count - 1] += ";";
                }
            }
            generate_block(F.Block_);
            if (!inf && F.Continued) 
                o.Add(spaces_prefix + sp(4) + "Cont" + F.Line.ToString() + ": ;");
            o.Add(spaces_prefix + "}");
            if (!inf && F.Breaked) 
                o.Add(spaces_prefix + "Brk" + F.Line.ToString() + ": ;");
            nesting_for.Remove(F);
        }

        /*
 		INT save_total|_index       

		METHOD generate_save_variable(
		{Assign} A|_push_stmt,
		{Expr} S|ource_assign_from,
		STR Temp|orary_variable_name)
			:
			STR typ|e_temp = type_gen(S.Type_expr, "")
			CASE A.Dest.Type_expr.Kind IN ['CLASS', 'STRUCTURE'] ?
			  o[] << spaces typ " " Temp 
			  		 " = " gen_none_val(A.Dest.Type_expr) ";"
			  		 
			ELSE o[] << spaces typ " " Temp ";" ;
			{Type} t|ype_of_destination = A.Dest.Type_expr
			
			sav|e_statement_temp = {Assign}(Line = 0,
					Function_ = Comp.Current_fun,
			        Level = A.Level,
			        Dest = {Expr}(Operation = 'VAR', 
			           Var_arg = {Var}(Line = 0, Type_ = t)), 
			        Source = S)
			        
			sav.Dest.Var_arg.Set_final_name(Temp)
			STR save|_assignment = generate_assign(sav) 
			o[] << save .
		
	
        METHOD generate_push({Assign} A|_push_stmt) :
            STR tmp|_save_var = "save" A.Line.Str "_" save_total.Str
            save_total += 1
            CASE A.Dest.Operation == 'FUN' ? 
                 CASE A.Dest.Fun_.Pop_method_ == NONE ?
                      CASE ?
		              [A.Dest.Fun_.Getter_field_ != NONE] ?
		                   ge|xpression_source_getter_temp = {Expr}(
		                   		Operation = 'FIELD',
		                   		Var_arg = A.Dest.Fun_.Getter_field_,
		                   		Arg1_ = A.Dest.This_)
		                   generate_save_variable(A, ge, tmp)
		              [A.Dest.Fun_.Getter_method_ != NONE] ?
		                   ge = {Expr}(Operation = 'FUN',
		                   		Fun_= A.Dest.Fun_.Getter_method_,
		                   		This_ = A.Dest.This_)
		                   generate_save_variable(A, ge, tmp) ;
		         ;
                 ------------------------------------- 'call method'
                 {Fun} pop|_method = A.Dest.Fun_.Pop_method_
                 STR text_call|_function = gen_fun_call(A.Dest) 
                 o[] << spaces text_call ";"
            ELSE generate_save_variable(A, A.Dest, tmp) ;
            ---------------------------------------- 'PUSH block in try-finally'
            o[] << spaces "try {"
            PUSH spaces = spaces sp(4) :
                 CASE A.Source != NONE ? o[] << generate_assign(A) ;
                 generate_block(A.Block_[]) ;
            o[] << spaces "} finally { "
            CASE ?
            [pop != NONE] ?
                 ------------------------------------- 'pop method'
                 {Expr} call|_pop_method_TEMP = {Expr}(Operation = 'FUN',
                        Fun_ = pop, This_ = A.Dest.This_),
                 		>> Comp.Current_fun.All_expr[]
                 
                 CASE pop !IN Comp.Current_fun.Call_functions_[] ?
                      Comp.Current_fun.Call_functions_[] << pop ;
                      
                 text_call = gen_fun_call(call) 
                 o[] << spaces sp(4) text_call ";"
                 
            [A.Dest.Fun_ != NONE] ?
		         res|tore_source_temp = {Expr}(Operation = 'VAR',
		                    Var_arg = {Var}(Line = 0,
		                    Type_ = A.Dest.Type_expr))
		         res.Var_arg.Set_final_name(tmp)
		         PUSH A.Dest.Items_[0] = res :
		         	  o[] << spaces gen_fun_call(A.Dest) ";" ;	
            ELSE
                 ------------------------------------- 'restore variable'
                 b|ack_assign_temp = {Assign}(Dest = A.Dest, Line = 0,
		                Function_ = A.Function_, Level = A.Level,
		                Source = {Expr}(Operation = 'VAR', 
		                    Var_arg = {Var}(Line = 0,
		                    Type_ = A.Dest.Type_expr)) )
		                    
		         b.Source.Var_arg.Set_final_name(tmp)
                 PUSH spaces = spaces sp(4) :
                      o[] << generate_assign(b) ;
            ;
            o[] << spaces "}" .
        */
        private void generate_push(Assignment A)
        {
            string tmp = "save" + A.Line.ToString();
            o.Add(spaces_prefix + type_gen(A.Dest.Type_expr(), false, false) + 
                  " " + tmp + " = " + gen_expr(A.Dest) + ";");
            o.Add(spaces_prefix + "try {");
            string save_sp = spaces_prefix;
            try
            {
                spaces_prefix += sp(4);
                if (A.Source != null)
                    generate_assign(A);
                generate_block(A.Block_);
            }
            finally { spaces_prefix = save_sp; }
            bool save_inc = A.Dest.Inc;
            bool save_dec = A.Dest.Dec;
            A.Dest.Inc = false;
            A.Dest.Dec = false;
            o.Add(spaces_prefix + "} finally {");
            o.Add("");
            bool was_left_side = is_left_side;
            is_left_side = true;
            try {
                o.Add(spaces_prefix + sp(4) + gen_expr(A.Dest));
            }
            finally { is_left_side = was_left_side; }
            o[o.Count - 1] += " = " + tmp;
            if (A.Dest.Type_expr().Kind == Type.Kind_type.CLASS)
            {
                string hard_w = "hard";
                if (A.Dest.Is_weak()) hard_w = "weak";
                o[o.Count - 1] += ".Obj.Assign_" + hard_w + "(" + gen_expr(A.Dest) + ")";
            }
            o[o.Count - 1] += "; }";
            A.Dest.Inc = save_inc;
            A.Dest.Dec = save_dec;
        }

        /*
        
        METHOD generate_stop({Case} Stop|_message) :
			STR text|_print = gen_expr(Stop.Condition) 
            o[] << spaces "AL4_system.STOP(" text ");" .
        */
        private void generate_stop(Case A)
        {
            o.Add(spaces_prefix + "AL4_system.STOP(" + gen_expr(A.Condition) + ");");
        }

        /*
        
        METHOD generate_assert({Case} A|ssert_stmt) :
			STR text|_condition = gen_expr(A.Condition) 
            o[] << spaces "if (!" text ") {"

            CASE A.Formatted != NONE ?
                 STR format|ted_text_if_failed = gen_expr(A.Formatted)
            ELSE format = #QU#QU ;
            
            o[] << spaces "   AL4_system.Assertion_failed(" A.Line.Str
                ", ref test_assert_" Comp.Current_class.Final_name 
                ", ref test_assert_failed_text_" Comp.Current_class.Final_name
                ", " format "); }" .
        */
        private void generate_assert(Case A)
        {
            o.Add(spaces_prefix + "if (!" + gen_expr(A.Condition) + ")");
            o.Add(spaces_prefix + "   AL4_system.Assertion_failed(" + A.Line.ToString() +
                ", ref test_assert);");
        }

        /*
        INT cnt_int|ernal_number
        
        METHOD gen_comment_block({Assign} A|_comment_block) :
            o[] << spaces "//----------------------- " A.Source.Var_arg.Str_c 
            CASE !FINAL_CODE ?
                 CASE use_profiler==""||use_profiler.[0]IN"AC" ?
                      //DEBUG:
                      		//o[] << "// use_profiler=" use_profiler 
                      		//;
	                  {Fun} f|unction_currently_generated = current_generated_fun
	                  cnt_int += 1
	                  STR suff|ix_cnt = "_Line" (A.Line+1).Str "__" cnt_int.Str
	                  ------------------------ 'declare CNT1_ and CNT_ variables'
	                  o[].Insert(line_with_cnt, 
	                 	 "public static long CNT1_" f.Final_name suff ";")
	                 	  
	                  o[].Insert(line_with_cnt, 
	                 	 "public static long CNT_" f.Final_name suff ";") 
	 
	                  //o[] << spaces "if (++CNT_" f.Final_name suff " == 0 )" #NL
	                  o[] << spaces "CNT1_" f.Final_name suff " = 0;" 
	                  o[] << spaces "if (AL4_system.inc_cnt(ref CNT_" 
	                  o[*] = o[*] f.Final_name suff ", ref CNT1_" f.Final_name suff 
	                  o[*] = o[*] ") == 0 )" #NL "" spaces "{ }" 
                 ;
                 ------------------------- 'if trace blocks on ...'
                 o[] << spaces "if (AL4_system.Level_trace_blocks > 0"
                 o[*] = o[*] " && AL4_system.Stack_functions.Length < "
                 o[*] = o[*] "AL4_system.Level_trace_blocks)"
                 o[] << spaces "   AL4_system.WriteLine(@" #QU
                 ------------------------- '... then output comment text'     
                 STR t|ext_to_out = f.Class.Names[0] "." f.Names[0]
                 INT len|gth_rest = 80 - t.Len - A.Source.Var_arg.Str_c.Len - 2
                 CASE len < 3 ? len = 3 ;
                 o[*] = o[*] t " " Repeat("-", len) " " 
                 o[*] = o[*] Replace_all( A.Source.Var_arg.Str_c, #QU, "")  
                 o[*] = o[*] #QU ");" 
            ; .
        */
        private void gen_comment_block(Assignment A)
        {
            o.Add(spaces_prefix + "//----------------------- " + A.Source.Var_arg.Str_c);
        }

        /*
        METHOD generate_block|_of_statements({Statement} Block|_of_stmt[]) :
            PUSH spaces = spaces sp(4) :
                FOR s IN Block[] : statement_gen(s) ;
            ; .
        */
        private void generate_block(List<Statement> Block)
        {
            string save_sp = spaces_prefix;
            spaces_prefix += sp(4);
            try
            {
                foreach (Statement s in Block)
                    statement_gen(s);
            }
            finally { spaces_prefix = save_sp; }
        }

        public static bool generating_localized_strings = false;
        /*
        BOOL generating_localized_strings
        
        METHOD gen_expr|ession(
        {Expr} E|xpression) ==> STR, RECURSIVE
        	:
            ----------------------------------- 'generate Before_assign_[] ?'
            CASE E.Before_assign_[].Count > 0 ?
                 PUSH close_br = FALSE :
	                  STR save_lines|_already_added[]
	                  FOR i IN [line_current_statement TO o[].Count-1] :
	                      save_lines[] << o[i] ;
	                  FOR i IN [o[].Count-1 DOWNTO line_current_statement] :
	                      o[].Delete(i) ;
	                  {Assign} a|ssignments[]
	                  FOR x IN E.Before_assign_[] : a[] << x.{Assign} ;
	                  E.Before_assign_[].Clear
	                  FOR y IN a[] : o[] << generate_assign(y) ;
	                  ------------------------------------- 'restore o[]'
	                  line_current_statement = o[].Count
	                  FOR s IN save_lines[] : o[] << s ;
	                  FOR y IN a[] : E.Before_assign_[] << y ;
                 ;
            ;
            --------------------------------------- 'localized string constant?'
            CASE E.Localize_n != "" && !generating_localized_strings ?
                 RESULT = "AL4_system.Localize_str["
                 "" E.Localize_i.Str 
                 " + " Comp.Current_class.Final_name
                 ".First_localize_item_" Comp.Current_class.Final_name "]" ==> ;
            --------------------------------------- 'generate expression'
            CASE E.Replace_index != ""  ?
                 RESULT = "/" "*R:" E.Replace_index "*" "/" ;

            PUSH level_expr = level_expr + 1 :
                CASE E.Operation ?
                ['BINARY']: RESULT = RESULT gen_binary(E)
                ['FUN', 'BASE_FUN', 'SYSTEM_FUN']: 
                    		RESULT = RESULT gen_fun_call(E)
                ['VAR']:    STR v|ariable_result = gen_variable(E)
                            CASE v == "this" ? v = "THIS.hard_link" ;
                            RESULT = RESULT v
                ['INDEX']:  RESULT = RESULT gen_index(E)
                ['FIELD']:  RESULT = RESULT gen_field(E)
                ['NEW_OBJ']:RESULT = RESULT gen_new_obj(E)
                ['ARRAY']:  RESULT = RESULT gen_array(E)
                ['AS']:     RESULT = RESULT gen_as_obj(E)
                ['CONST']:  RESULT = RESULT gen_const(E)
                            CASE E.Calculated ?
                                 RESULT = RESULT "/" "*CALC:" E.Total_const.Str 
                                 "*" "/"
                            ;
                ['INT2REAL']: RESULT = gen_expr(E.Arg1_)
                ['NOT_B']: 	RESULT = "~" gen_expr(E.Arg1_)
                ['NOT']: 	RESULT = "!" gen_expr(E.Arg1_)
                ['NEG']: 	RESULT = "-" gen_expr(E.Arg1_)
                ['UNKNOWN']:
                    Comp.Error("Generating unknown operation"._Egen ) ;
                CASE RESULT == "" ?
                     {Parser} p|arser_of_cur_class = Comp.Current_class.Parse
                     PUSH p.Line = E.At_line :
                          PUSH p.Pos = E.At_pos :
                               Comp.Error("Error generating expression"._Egen2 
                               " (" operation_descr(E) "):" p.Next20) ;
                     ;
                ;
            ; .
			
		FUN operation_descr(
		{Expr} E|xpression_to_desribe) ==> STR, RECURSIVE
			:
			RESULT = "Operation=" E.Operation.Name
			CASE E == NONE ? RESULT = RESULT ", NONE" ==> ;
			CASE E.Operation ?
			['BINARY']: RESULT = RESULT ", Sign=" E.Sign.Name
			['FUN', 'BASE_FUN', 'SYSTEM_FUN']:
					   RESULT = RESULT ", Fun_=" E.Fun_.Whole_name
			['CONST']: RESULT = RESULT ", Var_arg=CONST, Value:"
					  CASE E.Var_arg.Type_.Kind ?
					  ['BOOL']: RESULT = RESULT bool_to_str(E.Var_arg.Int_c != 0)
					  ['INT', 'ENUM']: RESULT = RESULT E.Var_arg.Int_c.Str
					  ['REAL']: RESULT = RESULT E.Var_arg.Real_c.Str
					  ['STR']: RESULT = RESULT #QU E.Var_arg.Str_c #QU
					  ['CLASS', 'STRUCTURE']: NONE ;
			['VAR']: RESULT = RESULT ", Var_arg=" E.Var_arg.Whole_name
					 RESULT = RESULT ", Type_.Kind=" E.Var_arg.Type_.Kind.Name
			['INT2REAL']: RESULT = RESULT "Int2Real(" operation_descr(E.Arg1_) ")"
			['NOT_B']: RESULT = RESULT "~(" operation_descr(E.Arg1_) ")"
			['NOT']: RESULT = RESULT "!(" operation_descr(E.Arg1_) ")"
			['NEG']: RESULT = RESULT "-(" operation_descr(E.Arg1_) ")"
			['UNKNOWN', 'INDEX', 'FIELD', 'NEW_OBJ', 'ARRAY', 'AS']: NONE ; .
					 
		FUN bool_to_str( BOOL V|alue_true_false ) ==> STR:
			CASE V ? RESULT = "TRUE" ==> ;
			RESULT = "FALSE" .

        */
        static int CNT_gen_expr;

        private string gen_expr(Expression E)
        {
            if (E == null)
            {
                Comp.Error("Internal error: can not generate null expression");
                return "?";
            }
            if (CNT_gen_expr++ == 8443)
            { }

            level_expr++;
            try
            {
                string Result = "";
                switch (E.Operation)
                {
                    case Expression.Operation_kind.BINARY:
                        Result = gen_binary(E);
                        break;
                    case Expression.Operation_kind.FUN:
                        Result = gen_fun_call(E);
                        break;
                    case Expression.Operation_kind.VAR:
                        Result = gen_variable(E);
                        if (Result == "this")
                            Result += ".hard_link";
                        break;
                    case Expression.Operation_kind.INDEX:
                        Result = gen_index(E);
                        break;
                    case Expression.Operation_kind.FIELD:
                        Result = gen_field(E);
                        break;
                    case Expression.Operation_kind.NEW:
                        Result = gen_new_obj(E);
                        break;
                    case Expression.Operation_kind.ARRAY:
                        Result = gen_array(E);
                        break;
                    case Expression.Operation_kind.AS:
                        Result = gen_as_obj(E);
                        break;
                    case Expression.Operation_kind.CONST:
                        Result = gen_const(E);
                        break;
                    default:
                        Comp.Error("Generating unknown operation");
                        break;
                }
                if (E.Inc) Result += "++";
                if (E.Dec) Result += "--";
                if (E.Neg) Result = "-" + Result;
                if (E.Not) Result = "!" + Result;
                if (Result == "")
                {
                    Parser p = Comp.Current_class.Parse;
                    int save_line = p.Line;
                    int save_pos = p.Pos;
                    p.Line = E.At_line;
                    p.Pos = E.At_pos;
                    {
                        Comp.Error("Error generating expression: " + p.Next20());
                    }
                    p.Line = save_line;
                    p.Pos = save_pos;
                }
                return Result;
            }
            finally { level_expr--; }
        }

        /*
        METHOD gen_binary({Expr} E|xpression) ==> STR :
		PUSH is_left_side = FALSE :
			--------------------------------- 'special case: long concatenation'
			CASE E.Sign == 'CONCAT' && E.Items_[].Count > 0 ?
				 RESULT = "("
				 FOR i IN E.Items_[] : RESULT = RESULT gen_expr(i) " + " ;
				 RESULT = RESULT.[0 TO *-3] ")" ==> ;
			--------------------------------- 'depending on operation:'
            CASE E.Sign ?
                 ['UNDEFINED']: 
                     {Parser} p|arser_of_cur_class = Comp.Current_class.Parse
                     PUSH p.Line = E.At_line :
                     PUSH p.Pos = E.At_pos :
                          Comp.Error("Attempt to compile undefined operation")
                     ;
                     ;
                 ['PLUS', 'CONCAT']: STR s|ign_operation = "+"
                 ['MINUS']:  s = "-"
                 ['MULT']:   s = "*"
                 ['DIV']:    RESULT = "AL4_system.Safe_div"
                             CASE E.Arg1_.Type_expr.Kind == 'INT' && (
                                  E.Arg2_.Type_expr.Kind == 'INT')
                                  ?
                                  RESULT = RESULT "_int" ;
                                  
                             RESULT = RESULT "(" gen_expr(E.Arg1_)
                             ", " gen_expr(E.Arg2_) ")" ==>
                             
                 ['REST']:   RESULT = "AL4_system.Safe_rest(" gen_expr(E.Arg1_)
                             ", " gen_expr(E.Arg2_) ")" ==>
                             
                 ['AND_B']:  s = "&"
                 ['OR_B']:   s = "|"
                 ['XOR_B']:  s = "^"
                 ['AND']:    s = "&&"
                 ['OR']:     s = "||"
                 ['IN', 'NOT_IN']: 
                             CASE E.Sign == 'NOT_IN' ? RESULT = "!" ;
                             CASE ?
                             [E.Arg2_.Operation == 'ARRAY' && (
                                  E.Arg2_.Type_expr.Kind IN ['INT', 
                                  'STR', 'ENUM'])]
                                  ?
                                  RESULT = RESULT "AL4_system.ArrayContains"
                                  "(" gen_const_array(E.Arg2_) 
                                  ", " gen_expr(E.Arg1_) ")" ==>
                                  
                             [E.Arg1_.Type_expr.Kind == 'STR' 
                              && !E.Arg2_.Is_array && !E.Arg1_.Is_const] ?
                              	  RESULT = RESULT "(" gen_expr(E.Arg1_) 
                              	  ".Length>0 && " gen_expr(E.Arg2_) 
                                  ".IndexOf(" gen_expr(E.Arg1_) ")>=0)" ==>
                                  
                             ELSE RESULT = RESULT "(" gen_expr(E.Arg2_)
                                  ".IndexOf(" gen_expr(E.Arg1_) ")>=0)" ==>
                             ;
                 ['LIKE', 'UNLIKE']:
                     	RESULT = "AL4_system.like_str"
                     	CASE E.Sign == 'UNLIKE' ? RESULT = "!" RESULT ;
                     	RESULT = RESULT "(" gen_expr(E.Arg1_) 
                     	RESULT = RESULT ", " gen_expr(E.Arg2_) ")" ==>
                 ['EQUAL']:  RESULT = gen_compare(E, "==") ==>
                 ['NOT_EQ']: RESULT = gen_compare(E, "!=") ==> 
                 ['LESS']:   RESULT = gen_compare(E, "<") ==>
                 ['LESS_OR_EQ']: RESULT = gen_compare(E, "<=") ==>
                 ['GREATER']:RESULT = gen_compare(E, ">") ==>
                 ['GREATER_OR_EQ']:  RESULT = gen_compare(E, ">=") ==> ;
            STR x|operand = gen_expr(E.Arg1_)
            STR y|operand = gen_expr(E.Arg2_)
            CASE x == "" || y == "" ? RESULT = "" ==> ;
            RESULT = "(" x " " s " " y ")" ; .
        */
        private string gen_binary(Expression E)
        {
            string s = "";
            switch (E.Sign)
            {
                case Expression.Bin.PLUS:
                case Expression.Bin.CONCAT: s = "+"; break;
                case Expression.Bin.MINUS: s = "-"; break;
                case Expression.Bin.MULT: s = "*"; break;
                case Expression.Bin.DIV: s = "AL4_system.Safe_div";
                    if (E.Arg1_.Type_expr().Kind == Type.Kind_type.INT &&
                        E.Arg2_.Type_expr().Kind == Type.Kind_type.INT)
                        s += "_int";
                        return s + "(" + gen_expr(E.Arg1_) + ", " + gen_expr(E.Arg2_) + ")";
                case Expression.Bin.REST: return "AL4_system.Safe_rest(" + gen_expr(E.Arg1_) + ", " + gen_expr(E.Arg2_) + ")";
                case Expression.Bin.AND_B: s = "&"; break;
                case Expression.Bin.OR_B: s = "|"; break;
                case Expression.Bin.XOR_B: s = "^"; break;
                case Expression.Bin.AND: s = "&&"; break;
                case Expression.Bin.OR: s = "||"; break;
                case Expression.Bin.IN: return gen_expr(E.Arg2_) + ".Contains(" + gen_expr(E.Arg1_) + ")";
                case Expression.Bin.NOT_IN: return "!" + gen_expr(E.Arg2_) + ".Contains(" + gen_expr(E.Arg1_) + ")";
                case Expression.Bin.EQUAL: return gen_compare(E, "==");
                case Expression.Bin.NOT_EQ: return gen_compare(E, "!=");
                case Expression.Bin.LESS: return gen_compare(E, "<");
                case Expression.Bin.LESS_OR_EQ: return gen_compare(E, "<=");
                case Expression.Bin.GREATER: return gen_compare(E, ">");
                case Expression.Bin.GREATER_OR_EQ: return gen_compare(E, ">=");
            }
            string x = gen_expr(E.Arg1_);
            string y = gen_expr(E.Arg2_);
            
            if (x == "" || y == "") return "";
            return "(" + x + " " + s + " " + y + ")";
        }

        /*
        
        METHOD gen_compare(
        {Expr} E|xpression, STR S|ign_compare) ==> STR
        	:
            CASE E.Arg1_.Type_expr.Kind ?
                ['BOOL', 'INT', 'REAL', 'ENUM']: NONE
                
                ['STR']: 
                         CASE S ?
                              ["=="]: NONE
                              ["!="]: RESULT = "!"
                              
                         ELSE 
                         	RESULT = "(" gen_expr(E.Arg1_)
                         
                         	RESULT = RESULT 
                         		".CompareTo(" gen_expr(E.Arg2_).remove_br
                         		
                            RESULT = RESULT ")" S "0)" ==>
                         ;
                         RESULT = RESULT gen_expr(E.Arg2_)
                         
                         RESULT = RESULT ".Equals(" gen_expr(E.Arg1_).remove_br 
                         	")" ==>
                         
                ['CLASS', 'STRUCTURE']:
                    CASE E.Arg1_.Var_arg == Comp.NONE_c 
                         && E.Arg2_.Var_arg == Comp.NONE_c
                         ?
                         CASE S ?
                         ["=="]: RESULT = "true" ==>
                         		 
                         ["!="]: RESULT = "false" ==> ;
                         		 
                         RESULT = "?[unknown operation between to NONEs]?" ==>
                    ;
                    CASE E.Arg1_.Var_arg == Comp.NONE_c ?
                         CASE S ?
                         ["=="]: RESULT = "AL4_system.Is_none(" 
                         		 "" gen_expr(E.Arg2_) ")" ==>
                         		 
                         ["!="]: RESULT = "!AL4_system.Is_none(" 
                         		 "" gen_expr(E.Arg2_) ")" ==> ;
                         		 
                         RESULT = "(AL4_system.Is_none(" gen_expr(E.Arg2_) 
                         ") " S " true)" ==>
                    ;
                    CASE E.Arg2_.Var_arg == Comp.NONE_c ?
                         CASE S ?
                         ["=="]: RESULT = "AL4_system.Is_none(" 
                         		 "" gen_expr(E.Arg1_) ")" ==>
                         		 
                         ["!="]: RESULT = "!AL4_system.Is_none(" 
                         		 "" gen_expr(E.Arg1_) ")" ==>
                         ;
                         		 
                         RESULT = "(AL4_system.Is_none(" gen_expr(E.Arg1_)
                         		  ")" S " true)" ==>
                    ;
                    RESULT = "(" gen_expr(E.Arg1_)
                    RESULT = RESULT ".Obj" S gen_expr(E.Arg2_) ".Obj)" ==>
            ;
            RESULT = "(" gen_expr(E.Arg1_) S 
            RESULT = RESULT  gen_expr(E.Arg2_) ")" .
        */
        static int CNT_gen_compare;

        private string gen_compare(Expression E, string S)
        {
            if (CNT_gen_compare++ == 3)
            { }

            switch (E.Arg1_.Type_expr().Kind)
            {
                case Type.Kind_type.BOOL:
                case Type.Kind_type.INT:
                case Type.Kind_type.REAL:
                case Type.Kind_type.ENUM: break;
                case Type.Kind_type.STR:
                    if (S == "==")
                        return gen_expr(E.Arg1_) + ".Equals(" + remove_brackets(gen_expr(E.Arg2_)) + ")";
                    else if (S == "!=")
                        return "!" + gen_expr(E.Arg1_) + ".Equals(" + remove_brackets(gen_expr(E.Arg2_)) + ")";
                    return "(" + gen_expr(E.Arg1_) + 
                                        ".CompareTo(" + remove_brackets(gen_expr(E.Arg2_)) + ")" + S + "0)";
                case Type.Kind_type.CLASS:
                    if (E.Arg1_.Var_arg == Comp.NONE_c)
                        return "(AL4_system.Is_none(" + gen_expr(E.Arg2_) + ")" + S + " true)";
                    if (E.Arg2_.Var_arg == Comp.NONE_c)
                        return "(AL4_system.Is_none(" + gen_expr(E.Arg1_) + ")" + S + " true)";
                    break;
            }
            return "(" + gen_expr(E.Arg1_) + S + gen_expr(E.Arg2_) + ")";
        }

        /*
        
        METHOD gen_fun_call({Expr} E|xpr_calling_fun) ==> STR :
	        CASE E.Fun_.Overloaded_[].Count > 0 ?
	             << "generating AMBIGUOUS call to overloaded function" >> ;
            //CASE E.Fun_.Final_name == "" && E.Fun_.Is_system ?
            CASE E.Fun_.Is_system ?
                RESULT = gen_system_fun(E) ==> ;
            CASE E.Fun_.Modifiers['STATIC'] ?
                    CASE E.Fun_.Is_system ? 
                         RESULT = "AL4_system."
                    ELSE RESULT = RESULT E.Fun_.Class.Final_name "." ;
            ELSE 
                 CASE E.This_ != Comp.THIS_expr && E.This_ != NONE ?
                      CASE ?
                      [E.This_.Is_array] ?
                           RESULT = gen_expr(E.This_) "."
                           
                      [E.Operation == 'BASE_FUN'] ? NONE
                      
                      [E.This_.Var_arg.Names[0] == "THIS"] ?
                           RESULT = "THIS."
                           BOOL this_prefix|_is_set_already = TRUE
                           
                      ELSE RESULT = "((" E.This_.Type_expr.Final_name 
                           RESULT = RESULT ")(" gen_expr(E.This_) ".Obj))."
                           
                           this_prefix = TRUE
                      ;
                 ;
            ;
            CASE E.Operation == 'BASE_FUN' ? RESULT = RESULT "base."
            ELSE 
                 CASE !E.Fun_.Modifiers['STATIC'] ? 
                      CASE !Comp.Current_fun.Modifiers['STATIC'] && (
                           !this_prefix)
                           ?
                           RESULT = RESULT "THIS." ;
                      RESULT = RESULT "Do." ;
            ;
            //DEBUG: CASE E.Fun_.Final_name == "" ?
            //             RESULT << "[fun#" E.Fun_.Total_fn.Str 
            //             " -- no final name!]" ;
            //;
            --------------- 'for TRAP function replace it to caller of TRAP fun'
            CASE E.Fun_.Modifiers['TRAP_FUN'] ?
                 {Var} tf|eild_trapping = E.Fun_.Trap_field
		         CASE ?
		         [tf.Trap_read_ == E.Fun_] ?
		         	  RESULT = RESULT "Trap_read_" tf.Final_name "("
		         [tf.Trap_write_ == E.Fun_] ?
		         	  RESULT = RESULT "Trap_write_" tf.Final_name "("
		         ELSE RESULT = RESULT E.Fun_.Final_name "(" ;
            ELSE RESULT = RESULT E.Fun_.Final_name "(" ;
        	----------------------------------- 'parameters'
            CASE E.Fun_.Param[].Count > 0 ?
                 PUSH is_left_side = FALSE :
	                  FOR p IN E.Items_[] :
	                      CASE p.Pass_by_ref ?
	                           RESULT = RESULT "ref " ; // only for STORE parameter
	                      CASE ?
	                      [p.Var_arg == Comp.NONE_c] ?
	                           RESULT = RESULT gen_none_val(
	                           			E.Fun_.Param[p.Index].Type_) ","
	                      [p.Operation == 'INDEX' && p.Arg2_ != NONE] ?
	                           RESULT = RESULT gen_index(p) ","
	                      ELSE RESULT = RESULT gen_expr(p).remove_brackets "," 
	                      ;
	                  ;
                 ;
                 RESULT = RESULT.[0 TO *-1] ;
            RESULT = RESULT ")" .

        */
        private string gen_fun_call(Expression E)
        {
            string Result = "";
            if (E.Fun_.Final_name == "" && E.Fun_.Is_system)
            {
                Result = gen_system_fun(E);
                return Result;
            }
            if (E.Fun_.Modifiers[(int)Function.Fun_mod.STATIC])
            {
                if (E.Fun_.Is_system) Result = "AL4_system.";
                else Result += E.Fun_.Class().Final_name + ".";
            }
            else
            {
                if (E.This_ != Comp.THIS_expr)
                    Result = "((" + E.This_.Type_expr().Final_name + ")" + gen_expr(E.This_) + ".Obj).";
            }
            Result += E.Fun_.Final_name + "(";
            if (E.Fun_.Param.Count > 0)
            {
                for (int ip = 0; ip < E.Items_.Count; ip++)
                {
                    Expression p = E.Items_[ip];
                    if (p.Var_arg == Comp.NONE_c)
                        Result += gen_none_val(E.Fun_.Param[ip].Type_) + ",";
                    else Result += remove_brackets(gen_expr(p)) + ",";
                }
                Result = Result.Substring(0, Result.Length - 1);
            }
            Result += ")";
            return Result;
        }

        /*
        
        METHOD gen_system_fun|ction_special_call(
            {Expr} E|xpr_calling) ==> STR
            :
            ----------------------------------------- 'Len, Name, Clear, etc.'
            CASE E.Fun_.System_fun ?
            ['SYSFUN_Len']:
				RESULT = gen_expr(E.Items_[0]) ".Length"
				
            ['SYSFUN_Name']:
				RESULT = E.Items_[0].Type_expr.Base_.Final_name
				RESULT = RESULT ".Names_" E.Items_[0].Type_expr.Final_name 
				RESULT = RESULT "[" gen_expr(E.Items_[0]).remove_br
				CASE E.Items_[0].Type_expr.Kind=='BOOL' ? 
				     RESULT = RESULT "?1:0" ;
				RESULT = RESULT "]"
                        
            ['SYSFUN_Clear']:
				RESULT = gen_expr(E.Items_[0]) ".Clear()"
				
            ['SYSFUN_Count']:
                CASE E.Items_[0].Operation == 'CONSTANT' ? 
                     RESULT = E.Items_[0].Var_arg.Items_[].Count.Str
                ELSE RESULT = gen_expr(E.Items_[0]) ".Count" ;
				
            ['SYSFUN_Insert']:
				RESULT = gen_expr(E.Items_[0])
				RESULT = RESULT ".Insert("
				CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
				RESULT = RESULT "(" gen_expr(E.Items_[1]) "), "
				CASE E.Items_[2].Type_expr.Kind != 'STRUCTURE' 
				     || E.Items_[2].Fun_.System_fun == 'SYSFUN_Clone'
				     ?
				     RESULT = RESULT gen_expr(E.Items_[2]) ")"
				ELSE 
					 {Expr} e_clone|_before_insert = {Expr}(
					 	Operation= 'SYSTEM_FUN', Fun_= Comp.SYSFUN_Clone,
					 	Items_[] << E.Items_[2]),
					 	>> Comp.Current_fun.All_expr[]
					 	
					 RESULT = RESULT gen_expr(e_clone) ")"
				;
                        
            ['SYSFUN_Allocate']:
				RESULT = gen_expr(E.Items_[0]) ".Allocate("
				CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
				RESULT = RESULT gen_expr(E.Items_[1]) ")"
                        
            ['SYSFUN_Delete']:
				CASE E.Items_[].Count > 2 ?
					 RESULT = spaces 
					 RESULT = RESULT gen_expr(E.Items_[0])   
					 CASE E.Items_[0].Type_expr.Kind != 'STRUCTURE' ? 
					      RESULT = RESULT ".Delete_range("
					      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
					      RESULT = RESULT "(" gen_expr(E.Items_[1]) ")"
					 ELSE RESULT = RESULT ".Delete_range_struc("
					      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
					      RESULT = RESULT "(" gen_expr(E.Items_[1]) ")"
					 ;
					 RESULT = RESULT ", " 
					 //CASE !Comp.Int32 ? RESULT << "(int)" ;
					 RESULT = RESULT "(" gen_expr(E.Items_[2]) "))"
	                         
				ELSE RESULT = spaces 
					 RESULT = RESULT gen_expr(E.Items_[0])
					 CASE E.Items_[0].Type_expr.Kind != 'STRUCTURE' ? 
					      RESULT = RESULT ".Delete("
					      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
					      RESULT = RESULT "(" gen_expr(E.Items_[1]) "))"
					 ELSE 
					 	  RESULT = spaces "((DynAObjHard)(" RESULT "))"
					      RESULT = RESULT ".Del_struc("
					      CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
					      RESULT = RESULT "(" gen_expr(E.Items_[1]) "))"
					 ;
				;
            ['SYSFUN_Remove']:
				RESULT = gen_expr(E.Items_[0])
				CASE E.Items_[0].Type_expr.Kind != 'STRUCTURE' ? 
				     RESULT = RESULT ".Remove(" gen_expr(E.Items_[1]) ")"
				ELSE RESULT = RESULT ".Remove_struc(" gen_expr(E.Items_[1]) ")" ;
                        
            ['SYSFUN_Find_item']:
				RESULT = gen_expr(E.Items_[0])
				RESULT = RESULT ".IndexOf(" gen_expr(E.Items_[1]) ")"
                        
            ['SYSFUN_Index']:  
                FOR f IN nesting_for[] :
                    CASE E.Items_[0].Var_arg == f.Var ?
                         RESULT = f.Index_var ==> ;
                ;
                Comp.Error("Can not find Index of FOR loop"._Ecannot5
                	". " ("May be loop variable was used out of a loop."
                	""._EOutLoop) ": " E.Items_[0].Var_arg.Names[0] )
                
            ['SYSFUN_Swap']:
            	RESULT = gen_expr(E.Items_[0])
            	RESULT = RESULT ".Swap("
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ; 
            	RESULT = RESULT "(" gen_expr(E.Items_[1]) "), "
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[2]) "))"
            			
            ['SYSFUN_First']:
            	RESULT = "(byte)0"
            	
	        ['SYSFUN_Last']:
	        	RESULT = "(byte)" (E.Items_[0].Type_expr.Items[].Count-1).Str
	        			
	        ['SYSFUN_Previous']:
	        	RESULT = "(byte)Math.Max(0, " gen_expr(E.Items_[0]) "-1)"
	        		  
	        ['SYSFUN_Next']:
	        	RESULT = "(byte)Math.Min(" 
	        	RESULT = RESULT (E.Items_[0].Type_expr.Items[].Count-1).Str
	        	RESULT = RESULT ", " gen_expr(E.Items_[0]) "+1)"

            ['SYSFUN_Find_str']:
            	RESULT = gen_expr(E.Items_[0]) ".IndexOf(" 
            	RESULT = RESULT gen_expr(E.Items_[1]) ")"
            			
            ['SYSFUN_Str', 'SYSFUN_RealStr', 'SYSFUN_BoolStr']:
            	RESULT = "AL4_system.Str(" gen_expr(E.Items_[0]) ")"
            	
            ['SYSFUN_StrInt']:
            	RESULT = "AL4_system.Int(" gen_expr(E.Items_[0]) ")"
            	
            ['SYSFUN_Byte']:
                RESULT = "(byte)(" gen_expr(E.Items_[0]) ")"
            	
            ['SYSFUN_RealInt']:
                CASE !Comp.Int32 ? 
                     RESULT = "(long)"
                ELSE RESULT = "(int)" ;
                RESULT = RESULT "Math.Truncate((double)(" gen_expr(E.Items_[0])
                "))"
            	
            ['SYSFUN_EnumInt']:
            	RESULT = gen_expr(E.Items_[0])
            	
            ['SYSFUN_StrHex16']:
            	RESULT = "AL4_system.hex16(" gen_expr(E.Items_[0]) 
            	RESULT = RESULT ", " gen_expr(E.Items_[1]) ")"
            		
            ['SYSFUN_Shl']:
            	RESULT = "(" gen_expr(E.Items_[0]) 
            	RESULT = RESULT " << (int)" gen_expr(E.Items_[1]) ")"
            		
            ['SYSFUN_Shr']:
            	RESULT = "AL4_system.ShiftRight(" gen_expr(E.Items_[0]) 
            	RESULT = RESULT ", (int)" gen_expr(E.Items_[1]) ")"
            		
            ['SYSFUN_Rol']:
            	RESULT = "AL4_system.RotateLeft(" gen_expr(E.Items_[0]) 
            	RESULT = RESULT ", (int)" gen_expr(E.Items_[1]) ")"
            		
            ['SYSFUN_Ror']:
            	RESULT = "AL4_system.RotateRight(" gen_expr(E.Items_[0]) 
            	RESULT = RESULT ", (int)" gen_expr(E.Items_[1]) ")"
            		
            ['SYSFUN_Compare_substrings']:
            	RESULT = "AL4_system.CompareSubstrings(" gen_expr(E.Items_[0]) ", "
            	RESULT = RESULT gen_expr(E.Items_[1]) ", " 
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT gen_expr(E.Items_[2]) ", "
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[3]) "), " 
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[4]) "), "
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[5]) "))"
            		
            ['SYSFUN_Compare_substr1']:
            	RESULT = "AL4_system.CompareSubstrWithStr(" 
            	RESULT = RESULT gen_expr(E.Items_[0]) ", "
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[1]) "), "
            	CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	RESULT = RESULT "(" gen_expr(E.Items_[2]) "), "
            	RESULT = RESULT gen_expr(E.Items_[3]) ")"
            		
            ['SYSFUN_Clone']:
            	RESULT = "((Structure_any)" gen_expr(E.Items_[0]) 
            	RESULT = RESULT ".Obj).Clone()"
            	
            ['SYSFUN_Dismiss']:
            	CASE E.Items_[0].Operation == 'INDEX' ?
            	     RESULT = "Structure_any.Dismiss_array_item("
            	     RESULT = RESULT gen_expr(E.Items_[0].Arg1_) ", "
            	     CASE !Comp.Int32 ? RESULT = RESULT "(int)" ;
            	     RESULT = RESULT "(" gen_expr(E.Items_[0].Arg2_) "))"
            	     
            	ELSE RESULT = "Structure_any.Dismiss_structure("
            		 RESULT = RESULT "ref " gen_expr(E.Items_[0]) ")" ;
            		
            ['SYSFUN_UNDEFINED']:
            	Comp.Error("Don't know how to call system function"._Edont
                 ": " E.Fun_.Names[0]) ; .
        */
        private string gen_system_fun(Expression E)
        {
            if (E.Fun_ == Comp.SYSFUN_Len)
            {
                return gen_expr(E.Items_[0]) + ".Length";
            }
            if (E.Fun_ == Comp.SYSFUN_Name)
            {
                return E.Items_[0].Type_expr().Base_.Final_name +
                    ".Names_" + E.Items_[0].Type_expr().Final_name +
                    "[" + remove_brackets(gen_expr(E.Items_[0])) + "]";
            }
            //---------------------------------------- 'array ...'
            if (E.Fun_ == Comp.SYSFUN_Clear)
            {
                return gen_expr(E.Items_[0]) + ".Clear()";
            }
            if (E.Fun_ == Comp.SYSFUN_Count)
            {
                return gen_expr(E.Items_[0]) + ".Count";
            }
            if (E.Fun_ == Comp.SYSFUN_Insert)
            {
                return gen_expr(E.Items_[0]) + ".Insert(" + gen_expr(E.Items_[1]) + ", " +
                    gen_expr(E.Items_[2]) + ")";
            }
            if (E.Fun_ == Comp.SYSFUN_Delete)
            {
                string index = gen_expr(E.Items_[1]);
                return "if (" + index + ">=0 && " + index + "< " +
                    gen_expr(E.Items_[0]) + ".Count)\r\n" +
                    spaces_prefix + sp(4) + gen_expr(E.Items_[0]) + ".Delete(" +
                    index + ")";
            }
            if (E.Fun_ == Comp.SYSFUN_Remove)
            {
                return gen_expr(E.Items_[0]) + ".Remove(" + gen_expr(E.Items_[1]) + ")";
            }
            if (E.Fun_ == Comp.SYSFUN_Find_item || E.Fun_ == Comp.SYSFUN_Find_str)
            {
                return gen_expr(E.Items_[0]) + ".IndexOf(" + gen_expr(E.Items_[1]) + ")";
            }
            //------------------------------------- 'var of FOR'
            if (E.Fun_ == Comp.SYSFUN_Index)
            {
                foreach (For f in nesting_for)
                {
                    if (E.Items_[0].Var_arg == f.Var)
                        return "idx" + f.Var.Line.ToString();
                }
                Comp.Error("Can not find Index of FOR loop");
            }
            Comp.Error("Don't know how to call system function: " + E.Fun_.Names[0]);
            return "?";
        }

        /*
        
        METHOD gen_variable({Expr} E|_variable) ==> STR :
			{Var} v|ariable = E.Var_arg
			CASE v.Replaced ? v = v.Replace_to_ ;
            
            CASE ?
            [v.Names[0] == "DATA"] ?
                 RESULT = RESULT Comp.Current_class.Final_name "."
			[v.In_type_.Kind IN ['CLASS', 'STRUCTURE']] ?
			     RESULT = RESULT "THIS."
            ;
            RESULT = RESULT v.Final_name
            //DEBUG:
            //	CASE RESULT != "this" ?
            // 	 RESULT << "/" "*" E.Var_arg.Total_i.Str
            // 	 CASE E.Var_arg != v ? RESULT << "/" v.Total_i.Str ;
            // 	 RESULT << "*" "/" ;
            //;
            CASE RESULT != "" ? ==> ;
            
 			RESULT = v.Names[*] 
 			
			.
        */
        private string gen_variable(Expression E)
        {
            return E.Var_arg.Final_name;
        }

        /*
        //INT total_index

        METHOD gen_index({Expr} E|_index_operation) ==> STR :
            CASE E.Arg1_.Is_array ?
                 CASE (E.Arg1_.Is_fixed) && (
                      E.Arg3_ != NONE) && E.Arg2_.Operation == 'CONST' && (
                      E.Arg2_.Var_arg.Type_.Kind == 'INT') && (
                      E.Arg2_.Var_arg.Int_c == 0) && (
                      E.Arg3_.Is_star_operation)
                      ?
                      RESULT = RESULT gen_expr(E.Arg1_) ==> ;
                     
                CASE E.Arg3_ != NONE ?
                     CASE E.Arg3_.Is_star_operation && E.Arg1_.Is_fixed && (
                     	  E.Arg2_.Operation == 'CONST' && (
                     	  E.Arg2_.Var_arg.Int_c == 0))
                     	  ?
                          RESULT = gen_expr(E.Arg1_) ==> ;
                     provide_list_temps
                     STR tg|enerated = type_gen(E.Arg1_.Type_expr, "AF")
                     ------------------- '<type>.new_<type>(...)'
                     RESULT = tg ".new_"
                     RESULT = RESULT type_gen(E.Arg1_.Type_expr, "AFR")
                     ------------------------ 'args'
					 RESULT = RESULT "(List_temps, "
					 CASE E.Arg1_.Is_fixed ?
					      RESULT = RESULT "(" type_gen(E.Arg1_.Type_expr, "AFR") ")"
					 ELSE RESULT = RESULT "(" type_gen(E.Arg1_.Type_expr, "AR") ")"
					 ;
					 RESULT = RESULT gen_expr(E.Arg1_) ", " 
					 CASE !Comp.Int32 ? 
					      RESULT = RESULT "(int)(" gen_expr(E.Arg2_) ")"
					 ELSE RESULT = RESULT gen_expr(E.Arg2_) ;
					 CASE !Comp.Int32 ? 
					      RESULT = RESULT ", (int)(" gen_expr(E.Arg3_) "))"
					 ELSE RESULT = RESULT ", " gen_expr(E.Arg3_) ")" ;
					 ==>
                ;
						  
                CASE E.Arg1_.Var_arg.Is_const ?
                	 STR t|ype_name = type_gen(E.Arg1_.Var_arg.Type_, "")
                	 //CASE t == "long" ? t = "int" ;
                	   
                     RESULT = RESULT "AL4_system.Array_item_" t 
                     	"(" E.Arg1_.Var_arg.Final_name 
                     	", " E.Arg1_.Var_arg.Size_value.Str ", "
                     	     
                     CASE !Comp.Int32 ? 
                          RESULT = RESULT "(int)("  gen_expr(E.Arg2_) "))"
                     ELSE RESULT = RESULT gen_expr(E.Arg2_) ")" ;
                     ==>
                ;
                RESULT = RESULT gen_expr(E.Arg1_)
                CASE is_left_side ?
                     STR g|et_set_actually = ".set_"
                ELSE g = ".get_" ;
            	CASE E.Arg1_.Type_expr.Kind ?
            	['CLASS', 'STRUCTURE']: RESULT = RESULT g "obj("
            	['ENUM']: RESULT = RESULT g "byte("
            	['BOOL']: RESULT = RESULT g "bool("
            	['INT']: RESULT = RESULT g "int("
            	['REAL']: RESULT = RESULT g "real("
            	['STR']: RESULT = RESULT g "str("
            	;
            	PUSH is_left_side = FALSE :
            	     CASE !Comp.Int32 ? 
            	          RESULT = RESULT "(int)(" gen_expr(E.Arg2_) ")"
            	     ELSE RESULT = RESULT gen_expr(E.Arg2_) ;
            	;
            	CASE is_left_side ? RESULT = RESULT ", "
                	 close_br = TRUE
            	ELSE RESULT = RESULT ")" ;
                ==> 
            ;
                
            CASE E.Arg3_ != NONE ? 
                RESULT = "AL4_system.Substring(" 
                RESULT = RESULT gen_expr(E.Arg1_).remove_br ", "
                CASE !Comp.Int32 ? 
                     RESULT = RESULT "(int)(" gen_expr(E.Arg2_).remove_br "), "
                ELSE RESULT = RESULT gen_expr(E.Arg2_).remove_br ", " ;
                CASE !Comp.Int32 ? 
                     RESULT = RESULT "(int)(" gen_expr(E.Arg3_).remove_br "))"
                ELSE RESULT = RESULT gen_expr(E.Arg3_).remove_br ")" ;
                ==>
            ;
            RESULT = "AL4_system.Single_symbol(" 
            RESULT = RESULT gen_expr(E.Arg1_).remove_br ", "
            CASE !Comp.Int32 ? 
                 RESULT = RESULT "(int)(" gen_expr(E.Arg2_).remove_br "))"
            ELSE RESULT = RESULT gen_expr(E.Arg2_).remove_br ")" ; .
        */

        private string gen_index(Expression E)
        {
            if (E.Arg1_.Is_array())
            {
                if (E.Arg3_ != null)
                    return "new Fixed(" + gen_expr(E.Arg1_) +
                        ", " + gen_expr(E.Arg2_) + ", " + gen_expr(E.Arg3_) + ")";
                else
                {
                    return gen_expr(E.Arg1_) + "[" + gen_expr(E.Arg2_) + "]";
                }
            }
            else
            {
                if (E.Arg3_ != null)
                    return "AL4_system.Substring(" + remove_brackets(gen_expr(E.Arg1_)) + ", " + 
                        remove_brackets(gen_expr(E.Arg2_)) +
                        ", " + remove_brackets(gen_expr(E.Arg3_)) + ")";
                if (level_expr == 1 && is_left_side)
                {
                    close_bracket_right_side = true;
                    return remove_brackets(gen_expr(E.Arg1_)) + " = AL4_system.Replace_symbol(" + 
                        remove_brackets(gen_expr(E.Arg1_)) + ", " + 
                        remove_brackets(gen_expr(E.Arg2_)) + ", ";
                }
                return "AL4_system.Single_symbol(" + remove_brackets(gen_expr(E.Arg1_)) + ", " + 
                    remove_brackets(gen_expr(E.Arg2_)) + ")";
            }
        }

        /*
        
        FUNCTION gen_none_val({Type} T|ype_NONE) ==> STR :
            CASE T.Kind ?
                ['BOOL']: RESULT = "false"
                ['INT', 'REAL', 'ENUM']: RESULT = "0"
                ['STR']: RESULT = #QU #QU
                
                ['CLASS']: RESULT = T.Final_name
                        ".NoneObj_" T.Final_name ".hard_link"
                        
            	['STRUCTURE']: RESULT = T.In_class_.Final_name 
            			"." T.Final_name ".NoneObj_" T.Final_name ".hard_link"      
            ; .
        */
        private string gen_none_val(Type T)
        {
            switch (T.Kind)
            {
                case Type.Kind_type.BOOL: return "false";
                case Type.Kind_type.INT:
                case Type.Kind_type.REAL:
                case Type.Kind_type.ENUM: return "0";
                case Type.Kind_type.STR: return "\"\"";
                case Type.Kind_type.CLASS:
					if (T.Names[0] != "{}")
						return T.Final_name + ".NoneObj_" + T.Final_name + ".hard_link";
					else return "AL4_object.None_obj";
            }
            return "";
        }

        /*
        
		INT temp_rec|ord_index
        
        METHOD gen_field({Expr} E|_field_of_obj) ==> STR :
            CASE ?
            [E.Var_arg.Names[0] == "DATA"] ?
                 RESULT = E.Arg1_.Type_expr.Final_name "." E.Var_arg.Final_name
            [E.Arg1_.Type_expr.Kind == 'CLASS'] ?
                 PUSH is_left_side = FALSE :
	                  RESULT = "((" E.Arg1_.Type_expr.Final_name 
	                           ")" gen_expr(E.Arg1_)
                 ;
                 CASE Ending(RESULT, ", ") ?
                      STR ending|_comma = ", "
                      RESULT = RESULT.[0 TO *-2] ;
                 CASE ! Ending(RESULT, ")Result") ? RESULT = RESULT ".Obj" ;
                 CASE is_left_side ? RESULT = RESULT ".write" ;
                 RESULT = RESULT ")." E.Var_arg.Final_name ending
            [E.Arg1_.Type_expr.Kind == 'STRUCTURE'] ?
            	 PUSH is_left_side = FALSE :
	                  RESULT = "((" E.Arg1_.Type_expr.In_class_.Final_name "." 
	                 		   "" E.Arg1_.Type_expr.Final_name 
	                           ")" gen_expr(E.Arg1_)
            	 ;
                 CASE Ending(RESULT, ", ") ?
                      ending = ", "
                      RESULT = RESULT.[0 TO *-2] ;
                 CASE ! Ending(RESULT, ")Result") ? RESULT = RESULT ".Obj" ;
                 CASE is_left_side ? RESULT = RESULT ".write" ;
                 RESULT = RESULT ")." E.Var_arg.Final_name ending
            [E.Arg1_.Operation == 'INDEX'] ?
        	 	 STR t|emp_variable_name = "tmp" temp_rec.Str
        	 	 temp_rec += 1
        	 	 {Type} type_arg1 = E.Arg1_.Type_expr 
        	 	 o[] << spaces type_arg1.Base_.Final_name
        	 	 o[*] = o[*] "." type_arg1.Final_name " " t " = "
        	 	     
        	 	 PUSH is_left_side = FALSE :
        	 	  	  o[*] = o[*] gen_expr(E.Arg1_) ";" ;
        	 	 RESULT = t "." E.Var_arg.Final_name
            ELSE RESULT = gen_expr(E.Arg1_) "." E.Var_arg.Final_name
            ; .
            
        */
        private string gen_field(Expression E)
        {
            string Result = "((" + E.Arg1_.Type_expr().Final_name +
                ")" + gen_expr(E.Arg1_) + ".Obj";
            if (is_left_side)
                Result += ".write";
            Result += ")." + E.Var_arg.Final_name;
            return Result;
        }

        /*
        
        METHOD gen_const({Expr} E|_constant) ==> STR :
			RESULT = gen_const_value(E.Var_arg) .
			
        METHOD gen_const_value(
        {Var} V|alue_to_generate) ==> STR
        	:
            CASE V.Type_.Kind ?
            ['BOOL']: 
                      CASE V.Int_c != 0 ? RESULT = "true"
                      ELSE RESULT = "false" ;
            ['INT', 'ENUM']:
                CASE ?
                [Starting(V.Constant_value, "0x")] ?
                     RESULT = Replace_all(V.Constant_value, "_", "")
                     RESULT = Replace_all(RESULT, " ", "")
                     CASE Comp.Int32 ? RESULT = "unchecked((int)" RESULT ")" ;
                [V.Type_.Kind != 'ENUM' 
                 && V.Constant_value != "" && V.Int_c == 0] ?
                     RESULT = V.Constant_value
                ELSE RESULT = V.Int_c.Str ;
            ['REAL']: 
                RESULT = V.Real_c.Str
                CASE ?
                [V == Comp.INFINITY_c] ?
                     RESULT = "double.PositiveInfinity" ==>
                [V.Real_c.Is_INF] ?
                     CASE V.Real_c < 0 ?
                       	  RESULT = "double.NegativeInfinity"
                     ELSE RESULT = "double.PositiveInfinity" ;
                     ==>
                [V == Comp.NAN_c || V.Real_c.Is_NAN] ?
                     RESULT = "double.NaN" ==>
                [V.Real_c >= 0 && V.Real_c <= 0 && V.Constant_value != ""] ?
                     RESULT = V.Constant_value
                ;
                CASE "." !IN RESULT && "e" !IN RESULT.Lower && ")" !IN RESULT ?
                     RESULT = RESULT ".0" ;
            ['STR']: RESULT = V.Str_c.as_str
            ['CLASS', 'STRUCTURE']: 
				Comp.Current_class.Parse.Line = V.Line
            	CASE V == Comp.THIS_expr.Var_arg ?
            		 RESULT = "THIS"
            	ELSE Comp.Error("Generating class constant!"._Egen4 ) ;
            ; .
        */
        private string gen_const(Expression E)
        {
            switch (E.Var_arg.Type_.Kind)
            {
                case Type.Kind_type.BOOL:
                    if (E.Var_arg.Bool_c) return "true";
                    else return "false";
                case Type.Kind_type.INT:
                case Type.Kind_type.ENUM:
                    return E.Var_arg.Int_c.ToString();
                case Type.Kind_type.REAL:
					if (Double.IsNaN(E.Var_arg.Real_c)) return "Double.NaN";
                    return E.Var_arg.Real_c.ToString().Replace(',', '.');
                case Type.Kind_type.STR:
                    return as_str(E.Var_arg.Str_c);
                case Type.Kind_type.CLASS:
                    Comp.Current_class.Parse.Line = E.Var_arg.Line;
                    Comp.Error("Generating class constant");
                    return "";
            }
            return "";
        }

        /*
        METHOD gen_as_obj({Expr} E|_as_operation) ==> STR :
            STR t|ype_final_name = E.Type_expr.Final_name
            CASE E.Type_expr.Kind == 'STRUCTURE' ?
                 STR cp|refix_class = E.Type_expr.In_class_.Final_name "." ;
                 
            RESULT = "AL4_system.As_obj(" gen_expr(E.Arg1_)
            ", " cp t ".NoneObj_" t ".hard_link)" .
        */
        private string gen_as_obj(Expression E)
        {
            return "AL4_system.As_obj(" + gen_expr(E.Arg1_) + ", " +
                E.Type_expr().Final_name + ".NoneObj_" + 
                E.Type_expr().Final_name + ".hard_link)";
        }

        /*
        METHOD gen_array({Expr} E|_array_obj) ==> STR :
            CASE E.Type_expr.Kind ?
                ['BOOL']: STR n|ames_type[] << "Bool" << "bool"
                ['ENUM']: n[] << "Byte" << "byte"
                ['INT']: n[] << "Int" << "int"
                ['REAL']: n[] << "Real" << "double"
                ['STR']: n[] << "Str" << "string"
                ['CLASS', 'STRUCTURE']:
					Comp.Error("Constant array of objects?"._Econst2 )
            ;
            RESULT = "new FixA" n[0] "(new " n[1] "[]{"
            FOR it IN E.Items_[] :
                RESULT = RESULT gen_expr(it) ", " ;
            RESULT = RESULT.[0 TO *-2] "})" .
            
        METHOD gen_const_array({Expr} E|_array_of_items) ==> STR :
            CASE E.Type_expr.Kind ?
                ['BOOL']: STR n|ames_type[] << "Bool" << "bool"
                ['ENUM']: n[] << "Byte" << "byte"
                ['INT']:
                    CASE Comp.Int32 ? 
                    	 n[] << "Int" << "int"
                    ELSE n[] << "Int" << "long" ;
                ['REAL']: n[] << "Real" << "double"
                ['STR']: n[] << "Str" << "string"
                ['CLASS', 'STRUCTURE']:
					Comp.Error("Constant array of objects?"._Econst4 )
            ;
            RESULT = "new " n[1] "[]{"
            FOR it IN E.Items_[] :
                RESULT = RESULT gen_expr(it) ", " ;
            RESULT = RESULT.[0 TO *-2] "}" .
        */
        private string gen_array(Expression E)
        {
            string t = "";
            string n = "";
            switch (E.Type_expr().Kind)
            {
                case Type.Kind_type.BOOL: n = "Bool"; t = "bool"; break;
                case Type.Kind_type.INT: 
                case Type.Kind_type.ENUM: n = "Int"; t = "int"; break;
                case Type.Kind_type.REAL: n = "Real"; t = "double"; break;
                case Type.Kind_type.STR: n = "Str"; t = "string"; break;
                case Type.Kind_type.CLASS:
                    Comp.Error("Constant array of objects?"); break;
            }
            string Result = "new FixA" + n + "(new " + t + "[]{";
            foreach (Expression it in E.Items_)
                Result += gen_expr(it) + ", ";
            Result = Result.Substring(0, Result.Length - 2) + "})";
            return Result;
        }

        /*
        {Expr} new_init|_statement

        METHOD gen_new_obj({Expr} E|_new_obj) ==> STR :
            new_init = E
            RESULT = E.Type_obj_.Final_name ".New()"
            CASE E.Type_obj_.Kind == 'STRUCTURE' ?
                 RESULT = E.Type_obj_.In_class_.Final_name "." RESULT ;
            . 
        */
        Expression new_init = null;

        private string gen_new_obj(Expression E)
        {
            new_init = E;
            string result = E.Type_obj_.Final_name + ".New()";
            return result;
        }

        /*
        
        FUNCTION remove_br|ackets(STR S|tring_expression) ==> STR :
            CASE S.[0] != "(" || S.[*] != ")" ? RESULT = S ==> ;
            STR t|emp_str = S
            BOOL in_s|tring_constant = FALSE
            INT lev|el_brackets = 0
            FOR i IN [0 TO t.Len-1] :
                CASE in_s ?
                    CASE t.[i] == #QU ? in_s = FALSE ;
                    t.[i] = "*" ;
                CASE !in_s && t.[i] == #QU ? in_s = TRUE ;
                CASE t.[i] ?
                    ["("]: lev += 1
                    [")"]: lev -= 1
                           CASE lev != 0 ? CONTINUE i ;
                           CASE i == t.Len-1 ? RESULT = S.[1 TO *-1] ==> ;
                           RESULT = S ==>
                ;
            ;
            RESULT = S .
        */
        static int CNT_remove_brackets;

        private static string remove_brackets(string S)
        {
            if (CNT_remove_brackets++ == 34)
            { }

            if (S == "" || S == null || S[0] != '(')
                return S;
            string t = S;
            bool in_s = false;
            int lev = 0;
            for (int i = 0; i <= S.Length-1; i++)
            {
                if (in_s)
                {
                    if (t[i] == '\"') in_s = false;
                    t = t.Substring(0, i) + '*' + t.Substring(i+1);
                    //t[i] = '*';
                }
                if (!in_s && t[i] == '\"') in_s = true;
                switch (t[i])
                {
                    case '(': lev++; break;
                    case ')': if (lev-- != 1) continue; 
                        if (i == t.Length-1)
                            return S.Substring(1, S.Length-2);
                        return S;
                }
            }
            return S;
        }
        
    }

}
/*

END

--ASSEMBLY--(
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("ASSEMBLY-TITLE")]
[assembly: AssemblyDescription("ASSEMBLY-DESCRIPTION")]
[assembly: AssemblyConfiguration("ASSEMBLY-CONFIGURATION")]
[assembly: AssemblyCompany("ASSEMBLY-COMPANY")]
[assembly: AssemblyProduct("ASSEMBLY-PRODUCT")]
[assembly: AssemblyCopyright("ASSEMBLY-COPYRIGHT")]
[assembly: AssemblyTrademark("ASSEMBLY-TRADEMARK")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("ASSEMBLY-GUID")]
[assembly: AssemblyVersion("ASSEMBLY-VERSION")]
[assembly: AssemblyFileVersion("ASSEMBLY-FILE-VERSION")]
--ASSEMBLY--)
--CSPROJ--1
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="TOOLS-VERSION" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProjectGuid>{907A09F7-30EC-49DB-BACC-40881CEDD6AE}</ProjectGuid>
CONSOLE:    <OutputType>Exe</OutputType>
VISUAL:    <OutputType>WinExe</OutputType>
    <NoStandardLibraries>false</NoStandardLibraries>
    <AssemblyName>Program</AssemblyName>
	<TargetFrameworkVersion>vFRAMEWORK-VERSION</TargetFrameworkVersion>
    <TargetFrameworkProfile>
    </TargetFrameworkProfile>
    <FileAlignment>512</FileAlignment>
    <ApplicationRevision>1</ApplicationRevision>
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>.</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>x86</PlatformTarget>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin/Release/</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>x86</PlatformTarget>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup>
    <RootNamespace>Compiled</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
FRAMEWORK4.0:    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data" />
    <Reference Include="System.Data.DataSetExtensions" />
FRAMEWORK4.0:    <Reference Include="System.Deployment" />
FRAMEWORK4+:    <Reference Include="System.Drawing" />
FRAMEWORK3.5:    <Reference Include="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
FRAMEWORK4+:    <Reference Include="System.Windows.Forms" />
FRAMEWORK3.5:    <Reference Include="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Xml.Linq" />
  </ItemGroup>
  <ItemGroup>
--CSPROJ--2
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\\Microsoft.CSHARP.Targets" />
  <ProjectExtensions>
    <VisualStudio AllowExistingFolder="true" />
  </ProjectExtensions>
</Project>
--CSPROJ--3
--AL4.cs--(
//------------------------------- AL4.cs version 2020-02-25

//#define DIAGNOSTICS
//#define DIAGNOSTICS_LIGHT

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
//?{High_precision_time}
using System.Diagnostics; // only if debugging!!! (with Stopwatch, below)
//.

#if DIAGNOSTICS
	using System.Threading;
#else
//?{Thread}
using System.Threading;
//.
#endif

using System.Runtime.InteropServices;

using AL4_project;

namespace AL4
{

    public class AL4_system
    {
//#native_functions_table

//?{Thread}
        [ThreadStatic]
//.
        public static int Recursion_counter = 0;
        public static int Max_recursion_deep = 128;
        
//?{Thread}
        [ThreadStatic]
//.
        public static long[] stack_functions = new long[4096];
        public static long[] Stack_functions
        {
        	get {
	        	if (stack_functions == null)
	        		stack_functions = new long[4096];
	        	return stack_functions;
        	}
        }
        
//?{Thread}
        [ThreadStatic]
//.
        public static int SP_fun = 0;
        
        public static 
@int32:	int imin(int a, int b)
@int64:	long imin(long a, long b)
        {
        	if (a < b) return a;
        	else return b;
        }
	
        public static 
@int32:	int imax(int a, int b)
@int64:	long imax(long a, long b)
        {
        	if (a > b) return a;
        	else return b;
        }
        
        public static bool Array_item_bool(bool[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return false;
        	return A[Index];
        }
	
        public static byte Array_item_byte(byte[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return 0;
        	return A[Index];
        }
	
        public static int Array_item_int(int[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return 0;
        	return A[Index];
        }
	
        public static long Array_item_long(long[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return 0;
        	return A[Index];
        }
	
        public static double Array_item_double(double[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return 0;
        	return A[Index];
        }
	
        public static string Array_item_string(string[] A, int Size, int Index) {
        	if (Index < 0 || Index >= Size) return "";
        	return A[Index];
        }
	
        public static string[] Function_names = new string[] {
//#function_names
        };
        
		public static int Get_trace_levels()
		{
			return SP_fun / 2;
		}
		
		public static string Get_trace_fun(int level)
		{
			if (level >= 0 && level < SP_fun / 2)
				return Function_names[
						Stack_functions[SP_fun - 2 - level * 2]];
			else return "";
		}
		
		public static long Get_trace_counter(int level)
		{
			if (level >= 0 && level < SP_fun / 2)
				return Stack_functions[SP_fun - 1 - level * 2];
			else return 0;
		}
		
		[ThreadStatic]
		public static long prev_stopwatch;
		
		public static long inc_cnt(ref long counter, ref long stamp) {
			counter += 1;
//?{High_precision_time}
			if (prev_stopwatch == 0) {
				prev_stopwatch = Stopwatch.GetTimestamp();
				return counter;
			}
			if (Stopwatch.IsHighResolution) {
				long now_t = Stopwatch.GetTimestamp();
				if (stamp == 0) stamp = now_t;
				else {
					counter += (long)(
						(now_t - stamp) * 1000000.0 / Stopwatch.Frequency );
					stamp = 0;
				} 
			}
//.
			return counter;
		}
		
        public static long Test_caller;
                           // lower 6 decimal digits = #of source code line in test function
                           //    calling ordinary code and test functions of level 2
                           // next 6 decimal digits = #of source code line in secondary test
                           //    functions calling ordinary functions.
                           
        //public static bool Trace_blocks;
        public static int Level_trace_blocks;
        
		#if DIAGNOSTICS
        public static StringBuilder diag_sb;
        public static DateTime diag_flushed;
        public static string[] diag_except_classes = new string[] {
//#initialize diagnostics except classes list
        };
        
        public static List<string> diag_codes = new List<string>();
        
        public static void diag_report(string S)
        {
        	//- check if called not from excepting classes
        	for (int i = SP_fun-2; i >= SP_fun-6 && i >= 0; i-=2)
        	{
        		if (Array.IndexOf(diag_except_classes, Stack_functions[i]) >= 0)
        			return;
        	}
        	int k = S.IndexOf(':');
        	if (k >= 0)
        	{
        		string code = S.Substring(0, k);
        		if (Array.IndexOf(diag_except_classes, code) >= 0) return;
        		//- remove detailed description, if not the first time
        		int k2 = S.IndexOf(",");
        		if (k2 < 0) k2 = S.Length-1;
        		if (diag_codes.IndexOf(code) >= 0)
        		{
        			S = code + ":" + S.Substring(k2+1);
        		}
        		else
        		{
        			diag_codes.Add(code);
        		}
        	}
        	//- flush log each 10 seconds or too big collected log size
        	bool delete_log =false;
        	if (diag_sb==null) 
        	{
        		diag_sb = new StringBuilder();
        		diag_flushed = DateTime.Now;
        		delete_log = true;
        	}                         
        	bool need_flush = diag_sb.Length > 10000 || S == "#";
        	if (!need_flush)
        	{
        		TimeSpan ts = DateTime.Now.Subtract(diag_flushed);
        		if (ts.TotalSeconds >= 10) need_flush = true; 
        	}    
        	string log = "";
        	if (need_flush || delete_log) 
        	{
                //string arg0 = Environment.GetCommandLineArgs()[0];
                //string start_dir = Path.GetDirectoryName(arg0);
        		log = Start_dir() + "\\diagnostics.log";
        	}
    		if (delete_log)
    		{
    			File.Delete(log);
    		}        			
        	if (need_flush)
        	{
        		for (int j=1; j < 1000; j++)
        		{
        			bool success = false;
        			try {
        				File.AppendAllText(log, diag_sb.ToString());
        				success = true;
        			}
        			catch {}
        			if (success) break;
        			Thread.Sleep(10);
        		}
        		diag_sb.Clear();
        		diag_flushed = DateTime.Now;
        	}
        	//---------------------- 'add to log'
        	//if (S != "#") 
        	diag_sb.Append(S + " " + 
        	(SP_fun>=2? Function_names[Stack_functions[SP_fun-2]] : "") 
        	+ "\r\n");
        }
        #endif
                           
        public static List<string> System_parameters = new List<string>();
        
        //-------------------------------------
        // Safe operation S[i] (string S, int i)
        public static string Single_symbol(string S, int Pos)
        {
            if (Pos >= 0 && S.Length > Pos) return S[Pos] + "";
        #if DIAGNOSTICS
        	#if DIAGNOSTICS_LIGHT
        	if (Pos==0 && S.Length==0 || Pos==S.Length || Pos==-1) {}
        	else 
        	#endif
        		 diag_report("SSR: Single symbol out of string bounds, Pos=" +
        		 Pos.ToString() + " S.Len=" + S.Length.ToString());
        #endif
            return (char)0 + "";
        }

        //-------------------------------------
        // Change operation S[i] (string S, int i)
        public static string Change_single_symbol(string S, int Pos, string New_ch)
        {
            String Result = S;
            if (Pos >= 0 && S.Length > Pos) 
            {
            	Result = "";
            	if (Pos > 0) Result = Substring(S, 0, Pos-1);
            	Result += New_ch;
            	if (Pos < S.Length-1) 
            		Result += Substring(S, Pos+1, S.Length-1);
            }
        #if DIAGNOSTICS
        	else diag_report("CSS: String bounds violation, Pos=" + 
        	Pos.ToString() + " S.Len=" + S.Length.ToString());
        #endif
            return Result;
        }
        
        //---------------------------
        // Safe Substring() of string
        public static string Substring(string S, int from, int to)
        {
        #if DIAGNOSTICS
        	if (from < 0 || from > to || from > S.Length || to >= S.Length)
        	{
        		#if DIAGNOSTICS_LIGHT
        		if (from == to+1 || from == S.Length) {}
        		else
        		#endif
        		    diag_report("SS: Substring out of bounds of string, from=" +
        		    from.ToString() + " to=" + to.ToString() + " S.Len=" + 
        		    S.Length.ToString());
        	}
        #endif
            if (from < 0) from = 0;
            if (S.Length <= to) to = S.Length - 1;
            if (to - from + 1 <= 0 || S.Length <= from) return "";
            return S.Substring(from, to - from + 1);
        }
        
        //---------------------------
        // Optimized comparison of two sub-strings
        public static int CompareSubstrings(string S1, string S2, 
            int from1, int to1, int from2, int to2)
        {
        #if DIAGNOSTICS
        	if (from1 < 0 || from1 > to1 || from1 >= S1.Length || to1 >= S1.Length
        	|| from2 < 0 || from2 > to2 || from2 >= S2.Length || to2 >= S2.Length)
        	{
        		diag_report("SCS: Compare substrings bounds violation, from1=" +
        		from1.ToString() + " to1=" + to1.ToString() + " S1.Len=" +
        		S1.Length.ToString() +
        		" from2=" + from2.ToString() + " to2=" + to2.ToString() +
        		" S2.Len=" + S2.Length.ToString());
        	}
        #endif                                                          
            if (from1 < 0) from1 = 0;
            if (from2 < 0) from2 = 0;
            int last1 = to1;
            if (last1 >= S1.Length) last1 = S1.Length - 1;
            int last2 = to2;
            if (last2 >= S2.Length) last2 = S2.Length - 1;
            int j = from2;
            for (int i = from1; i <= last1; i++, j++)
            {
                if (j > last2) 
                {
                    if (i <= last1) return 1;
                    break;
                }
                int Result = (int)S1[i] - (int)S2[j];
                if (Result != 0) return Result;
            }
            if (j <= last2) return -1;
            return 0;
        }

        //---------------------------
        // Optimized comparison of a sub-string with a string
        public static int CompareSubstrWithStr(string S1,  
            int from1, int to1, string S2)
        {
        #if DIAGNOSTICS
        	if (from1 < 0 || from1 > to1 || from1 >= S1.Length || to1 >= S1.Length)
        		diag_report("SC: Compare substring with string bounds violation, from1=" +
        		from1.ToString() + " to1=" + to1.ToString() + " S1.Len=" +
        		S1.Length.ToString() + " S2.Len=" + S2.Length.ToString());
        #endif                                                          
            int last1 = to1;
            if (from1 < 0) from1 = 0;
            if (last1 >= S1.Length) last1 = S1.Length - 1;
            int j = 0;
            for (int i = from1; i <= last1; i++, j++)
            {
                if (j >= S2.Length) 
                {
                    if (i <= last1) return 1;
                    break;
                }
                int Result = (int)S1[i] - (int)S2[j];
                if (Result != 0) return Result;
            }
            if (j < S2.Length) return -1;
            return 0;
        }
        
        public static bool like_str(string S1, string S2)
        {
        	string s1 = last_uppered_lowered == 0 ? ToUpper1(S1) : ToLower1(S1);
        	string s2 = last_uppered_lowered == 0 ? ToUpper1(S2) : ToLower1(S2);
        	bool result = s1 == s2;
        	if (result) return true;
        	if (!s2.Contains('%') && !s2.Contains('?')) return false;
//?{String_functions}
			result = C_String_functions.M_Like(s1, s2);        	
//.
			return result;
		}

		[ThreadStatic]
	    static int last_uppered_lowered;

		[ThreadStatic]
	    public static string last1_uppered = null;
		[ThreadStatic]
	    public static string uppered1;
		[ThreadStatic]
	    public static string last2_uppered = null;
		[ThreadStatic]
	    public static string uppered2;
		[ThreadStatic]
	    static int next_uppered = 0;
	    
	    public static string ToUpper1(string s) {
	    	last_uppered_lowered = 0;
	    	
	    	if ((object)s == (object)last1_uppered) {
	    		next_uppered = 0;
	    		return uppered1;
	    	}
	    	if ((object)s == (object)last2_uppered) {
	    		next_uppered = 1;
	    		return uppered2;
	    	}
	    	next_uppered = 1 - next_uppered;
	    	if (next_uppered == 0) {
	    		last1_uppered = s;
	    		uppered1 = s.ToUpper();
	    		return uppered1;
	    	}
	    	else {
	    		last2_uppered = s;
	    		uppered2 = s.ToUpper();
	    		return uppered2;
	    	}
	    }
	
		[ThreadStatic]
	    public static string last1_lowered = null;
		[ThreadStatic]
	    public static string lowered1;
		[ThreadStatic]
	    public static string last2_lowered = null;
		[ThreadStatic]
	    public static string lowered2;
		[ThreadStatic]
	    static int next_lowered = 0;
	    
	    public static string ToLower1(string s) {
	    	last_uppered_lowered = 1;
	    	
	    	if ((object)s == (object)last1_lowered) {
	    		next_lowered = 0;
	    		return lowered1;
	    	}
	    	if ((object)s == (object)last2_lowered) {
	    		next_lowered = 1;
	    		return lowered2;
	    	}
	    	next_lowered = 1 - next_lowered;
	    	if (next_lowered == 0) {
	    		last1_lowered = s;
	    		lowered1 = s.ToLower();
	    		return lowered1;
	    	}
	    	else {
	    		last2_lowered = s;
	    		lowered2 = s.ToLower();
	    		return lowered2;
	    	}
	    }
	
        public static bool ArrayContains(byte[] A, byte Value)
        {
            for (int i = 0; i < A.Length; i++)
                if (A[i] == Value) return true;
            return false;
        }

        public static bool ArrayContains(
@int32:	int[] A, int Value
@int64:	long[] A, long Value
        )
        {
            for (int i = 0; i < A.Length; i++)
                if (A[i] == Value) return true;
            return false;
        }

        public static bool ArrayContains(int[] A, byte bValue)
        {
        	int Value = bValue;
            for (int i = 0; i < A.Length; i++)
                if (A[i] == Value) return true;
            return false;
        }

        public static bool ArrayContains(string[] A, string Value)
        {
            for (int i = 0; i < A.Length; i++)
                if (A[i] == Value) return true;
            return false;
        }

        //-----------------------------------------
        // Operation S[i] = c (not available in C#)
        public static string Replace_symbol(string S, int i, string r)
        {
            if (i < 0 || i >= S.Length) return S;
            return S.Substring(0, i) + r + S.Substring(i + 1);
        }

        //----------------------
        // Convert int to string
        public static string Str(int x)
        {
            return x.ToString();
        }

        //-------------------------
        // Convert double to string
        public static string Str(double x)
        {
            string Result = x.ToString().Replace(',', '.');
            if (!"-+0123456789.".Contains(Result[0])) {
            	if (Double.IsNegativeInfinity(x)) return("-INF");
            	if (Double.IsPositiveInfinity(x)) return("+INF");
            	if (Double.IsNaN(x)) return("NAN_constant");
            }
            Result = Result.Replace('e', 'E');
            for (int i = Result.Length-2; i > 0; i--)
                if (Result[i] == '-' || Result[i] == '+' || Result[i] == 'E')
                    while (Result[i+1] == '0' && i < Result.Length-1)
                        Result = Result.Substring(0, i+1) + Result.Substring(i+2);
            return Result;
        }

        //-------------------------
        // Convert bool to string
        public static string Str(bool x)
        {
            if (x) return "TRUE";
            return "FALSE";
        }
        
        public static string Null_to_EOF(string may_be_null)
        {
        	if (may_be_null == null) return "" + (char)26;
        	return may_be_null;
        }
        
        public static int Int(string s)
        {
            int Result = 0;
            bool Neg = false;
            if (s == "") return Result;
            int i = 0;
            if (s[i] == '-')
            {
                i++;
                Neg = true;
            }
            else if (s[i] == '+') i++;
            for (int j = i; j < s.Length; j++)
            {
                if (s[j] == '_') continue;
                if (s[j] >= '0' && s[j] <= '9')
                    Result = Result * 10 + (int)s[j] - (int)'0';
                else break;
            }
            if (Neg) return -Result;
            return Result;
        }

        public static int RealAsInt(double X)
        {
            return (int)X;
        }
        
        public static int EnumAsInt(int X)
        {
            return X;
        }
        
        //------------- 'string as a sequence of hexadecimal, 4 digits per char'
        private static string hex16(int value16)
        {
            string Result = "";
            for (int i = 0; i < 4; i++)
            {
                int digit = (value16 >> 12) & 0xf;
                value16 = value16 << 4;
                if (digit < 10) Result += "" + (Char)((int)'0' + digit);
                else Result += "" + (Char)((int)'A' + digit - 10);
            }
            return Result;
        }

        public static string StrHex16(string s)
        {
            string Result = "";
            for (int i = 0; i < s.Length; i++)
                Result += hex16((int)s[i]);
            return Result;
        }

        public static 
@int32:	int
@int64:	long
        ShiftLeft(
@int32:	int
@int64:	long
        i, int n)
        {
            return i << n;
        }

        public static 
@int32:	int
@int64:	long
        ShiftRight(
@int32:	int
@int64:	long
        i,
        int n)
        {
            return (int)(((uint)i) >> n);
        }

        public static 
@int32:	int
@int64:	long
        RotateLeft(
@int32:	int
@int64:	long
        i, int m)
        {
@int32:		if (m > 32) return i << 1;
@int64:		if (m > 64) return i << 1;
@int64:   	ulong mask = (unchecked((ulong)-1L) << (m-1))<<1;
@int32:    	uint mask = (unchecked((uint)-1) << (m-1))<<1;
@int64:     ulong r = (mask & (ulong)i) 
@int64:   		   | (((ulong)i << 1) & ~mask) 
@int64:    		   | (((ulong)i & ~mask) >> (m-1));
@int32:     uint r = (mask & (uint)i) 
@int32:   		   | (((uint)i << 1) & ~mask) 
@int32:    		   | (((uint)i & ~mask) >> (m-1));
@int32:    	return (int)r;
@int64:    	return (long)r;
        }

        public static 
@int32:	int
@int64:	long
        RotateRight(
@int32:	int
@int64:	long
        i, int m)
        {
@int32:		if (m > 32) return i >> 1;
@int64:		if (m > 64) return i >> 1;
@int32:     uint mask = (unchecked((uint)-1) << (m-1))<<1;
@int64:     ulong mask = (unchecked((ulong)-1L) << (m-1))<<1;
@int32:   	uint r = (mask & (uint)i)
@int32:   		   | (((uint)i << (m-1)) & ~mask) 
@int32:    		   | (((uint)i & ~mask) >> 1);
@int64:   	ulong r = (mask & (ulong)i)
@int64:   		   | (((ulong)i << (m-1)) & ~mask) 
@int64:    		   | (((ulong)i & ~mask) >> 1);
@int32:    	return (int)r;
@int64:    	return (long)r;
        }

        //------------------------------------------
        // Find substring first position in a string
        public static int Find_str(string S, string Pattern)
        {
            int r = S.IndexOf(Pattern);
            return r;
        }

        //--------------------------------------
        // Is object variable referencing NONE ?
        public static bool Is_none(Ref_obj obj)
        {
            return obj.Obj.Is_NONE_object;
        }

        //---------------------------------------------------------------
        // Safe division of real numbers. Returns INF or NaN in bad cases
        public static double Safe_div(double X, double Y)
        {
            if (Y == 0) return X > 0 ?
                double.PositiveInfinity : double.NegativeInfinity;
            try
            {
                return X / Y;
            }
            catch (Exception Ex) {
            	if (Ex is AL4_Exception) throw; 
                AL4_system.Any_exception(Ex);
                return double.NaN; 
            }
        }

        //-------------------------------------------------
        // Safe division of int numbers. Returns very large 
        // or negative large integer number in bad cases.
        public static 
@int32:	int
@int64:	long
        Safe_div_int(
@int32:	int X, int Y
@int64:	long X, long Y
        )
        {
            if (Y == 0)
            {
        #if DIAGNOSTICS
        	#if DIAGNOSTICS_LIGHT
        	#else
        		diag_report("IZD: Integer zero divide, X=" + X.ToString());
        	#endif
        #endif
            	return X > 0 ?
@int32:			int.MaxValue : int.MinValue;
@int64:			long.MaxValue : long.MinValue;
            } 
            return X / Y;
        }

        //---------------------------------
        // Safe rest of division operation.
        public static 
@int32:	int
@int64:	long
        Safe_rest(
@int32:	int X, int Y
@int64:	long X, long Y
        )
        {
            if (Y == 0) return X;
            return X % Y;
        }

        //-----------------------
        // STOP operation
        public static void STOP(string message)
        {
            throw new Stop(message);
        }

        [ThreadStatic]
        public static List<String> Errors = null;
        
        //-------------------------
        // Should be called on any exception to collect errors:
        // maximum 10 errors are stored
        // If there were more then 10, middle errors are removed and 
        // then Errors list contains:
        // 0 to 4 - first 5 errors from Reset_errors
        // 5 - empty (to signal that Errors count > 10)
        // 6 TO 9 - last 4 errors
        public static void Any_exception(Exception E)
        {
        #if DIAGNOSTICS
        	diag_report(E.GetType().Name + ": " + E.Message);
        #endif
            if (Errors == null) Errors = new List<String>();
            if (Errors.Count >= 10)
            {
                Errors.RemoveAt(5);
                Errors[5] = "";
            }
            Errors.Add(E.GetType().Name + ": " + E.Message);
        }
        
        public static void Add_error_descr(String E)
        {
            if (Errors == null) Errors = new List<String>();
            if (Errors.Count >= 10)
            {
                Errors.RemoveAt(5);
                Errors[5] = "";
            }
            Errors.Add(E);
        }
        
        
        public static void Reset_errors()
        {
            Errors = null;
        }
        
        public static int Errors_count()
        {
            if (Errors == null) return 0;
            return Errors.Count; 
        }
        
        public static String Errors_info(int index)
        {
            if (Errors == null || index < 0 || index >= Errors.Count)
                return "";
            return Errors[index];
        }

        //------------------------------------------------------------
        // Operation X.{Type}. Returns NONE is X is not of type {Type}. 
        public static Ref_obj As_obj(Ref_obj X, Ref_obj None_y)
        {
            AL4_object probe = X.Obj;
            while (probe != null)
            {
                if (probe.NONE_obj_instance().Obj == None_y.Obj)
                    return X;
                probe = probe.NONE_base_obj();
            }
            return None_y;
        }

        //----------------------------------------------------------
        // Application startup directory
        public static string Start_dir()
        {
            return Startup_path();
        }

        //----------------------------------------------------------
        // Application startup directory
        public static string Startup_path()
        {
            string s = Environment.CommandLine;
            if (s[0] == (char)34)
            {
                s = s.Substring(1);
                int i = s.IndexOf((char)34);
                s = s.Substring(0, i);
            }
            else
            {
                int j = s.IndexOf(' ');
                if (j > 0) s = s.Substring(0, j);
            }
            s = Path.GetDirectoryName(s);
            if (s[s.Length - 1] != '\\') s += '\\';
            return s;
        }

        //---------------------------------------------------------
        // Clear test data
        public static void Clear_test_data(long[] test_lines,
            long[] init_test_lines)
        {
            for (int i = 0; i < test_lines.Length; i++)
            {
                if (test_lines[i] < 0) continue;
                if (i >= init_test_lines.Length) break;
                test_lines[i] = init_test_lines[i];
            }
        }

        //---------------------------------------------------------
        // Remove a range from test data
        public static void Remove_test_data(long[] test_lines, int from, int to)
        {
            for (int i = from; i < to; i++)
            {
                if (i >= test_lines.Length) return;
                //if (test_lines[i] < 0) continue;
                //if (test_lines[i] == 0) 
                test_lines[i] = -from;
            }
        }

        //---------------------------------------------------------
        // Output test data of class
        public static void Output_test_data(long[] test_lines,
            List<int> test_assert, List<string> test_assert_failed_text, 
            string Class_test_file, string Class_path_source)
        {
            string path = Class_test_file;
            string s = "";
            StreamWriter sw = new StreamWriter(path);
            try
            {
                sw.WriteLine("source: " + Class_path_source);
                for (int i = 0; i < test_lines.Length; i++)
                {
                    s = s + test_lines[i].ToString() + " ";
                    if (s.Length >= 75)
                    {
                        sw.WriteLine(s);
                        s = "";
                    }
                }
                if (s != "") sw.WriteLine(s);
                if (test_assert != null)
                {
                    sw.WriteLine("* assertions failed in lines:");
                    for (int i = 0; i < test_assert.Count; i++)
                    {
                        sw.Write(test_assert[i].ToString());
                        if (test_assert_failed_text[i] != "")
                            sw.Write(" " + test_assert_failed_text[i]);
                        sw.WriteLine("");
                    }
                }
            }
            finally { sw.Close(); }
        }

        // adding an assertion failed to list of failed assertions:
        public static void Assertion_failed(int line, ref List<int> test_assert,
               ref List<string> test_assert_failed_text, string text_if_failed)
        {
            if (test_assert == null) 
            {
                test_assert = new List<int>();
                test_assert_failed_text = new List<string>();
            }
            test_assert.Add(line);
            test_assert_failed_text.Add(text_if_failed);
        }
        
		public static void Profiler_save_reset()
		{
//#profiler_save_reset
		}

        [DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        public static bool Need_console = false;
        
        public static void Write_direct(string S)
        {
        	Console.Write(S);
        }
        
        public delegate void RedirectWrite(string S);
        public static RedirectWrite Redirect_write = Write_direct;
        
        public static void Write(string S)
        {
            if (Need_console)
            {
                Need_console = false;
                AllocConsole();
            }
            Redirect_write(S);
        }

        public static void WriteLine(string S)
        {
            Write(S + "\n");
        }
        
        public static void Save_strings(List<string> L, string Path)
        {
            try {
            StreamWriter sw = new StreamWriter(Path);
            for (int i = 0; i < L.Count(); i++)
                sw.WriteLine(L[i]);
            sw.Close();
            }
            catch (Exception Ex) {
            	if (Ex is AL4_Exception) throw;
                AL4_system.Any_exception(Ex);
            }
        }
        
        public static bool Is_TEST_stage()
        {
//#test:      return true;
//#not_test:  return false;
        }
        
		[ThreadStatic]
		public static int global_activity_counter;
		public static List<AL4_handler> long_operation_handlers 
			= new List<AL4_handler>();
		
		public static void check_long_operation()
		{
			global_activity_counter = 65535;
			for (int i = long_operation_handlers.Count-1; i >= 0; i--)
				long_operation_handlers[i].Handler();
		}
//#localize
//#app_icon

		public static List<int> id_limits = new List<int>();
		public static List<int> kind_limits = new List<int>();
		public static List<long> value_limits = new List<long>();
		public static int total_id_limits;

		public static int limit_by_time(double time, int units) {
			total_id_limits += 1;
			int id = total_id_limits;
			id_limits.Add(id);
			kind_limits.Add(0);
			
			DateTime point = new DateTime(1970, 1, 1);
			TimeSpan span = DateTime.Now.Subtract(point);
			switch (units)
			{
				case 0: span = span.Add(TimeSpan.FromMilliseconds(time));
						break;
				case 1: span = span.Add(TimeSpan.FromSeconds(time));
						break;
				case 2: span = span.Add(TimeSpan.FromMinutes(time));
						break;
				case 3: span = span.Add(TimeSpan.FromHours(time));
						break;
				case 4: span = span.Add(TimeSpan.FromDays(time));
						break;
			}
			
			value_limits.Add((long)span.TotalMilliseconds);
			add_limit_handler();
			return id;
		}
		
		public static long total_func;

		public static int limit_by_func(long limit_func) {
			total_id_limits += 1;
			int id = total_id_limits;
			id_limits.Add(id);
			kind_limits.Add(1);
			value_limits.Add(total_func + limit_func);
			add_limit_handler();
			return id;
		}

		public static long total_loops;

		public static int limit_by_loops(long limit_loops) {
			total_id_limits += 1;
			int id = total_id_limits;
			id_limits.Add(id);
			kind_limits.Add(1);
			value_limits.Add(total_loops + limit_loops);
			add_limit_handler();
			return id;
		}
		
		public static void dismiss_limit(int id)
		{
			for (int i= id_limits.Count-1; i >= 0; i--)
			{
				if (id_limits[i] != id) continue;
				id_limits.RemoveAt(i);
				kind_limits.RemoveAt(i);
				value_limits.RemoveAt(i);
				return;
			}
		}
		
		public static bool limit_handler_added;
		
		public static void add_limit_handler()
		{
			if (limit_handler_added) return;
			limit_handler_added = true;
			Limit_handler lh = new Limit_handler();
			long_operation_handlers.Add(lh); 
		}

    } // end of class AL4_system
    
    public class E_Limit_exceeded : AL4_Exception
    {
    	public int id;
    	
    	public E_Limit_exceeded(int id_exception)
    	{
    		id = id_exception;
    	}
    }
    
    public class Limit_handler : AL4_handler
    {
    	public static bool Lock_raise;
    	public static int Need_raise = -1;
    
    	public override void Handler()
    	{
    		//if ( AL4_thread.mainThreadId != Thread.CurrentThread.ManagedThreadId)
    		//	return;
    		for (int i= 0; i < AL4_system.id_limits.Count; i++)
    		{
    			switch (AL4_system.kind_limits[i])
    			{
    				case 0:
		                 DateTime point = new DateTime(1970, 1, 1);
		                 TimeSpan span = DateTime.Now.Subtract(point);
		                 if ((long)span.TotalMilliseconds > 
		                 	 AL4_system.value_limits[i])
		                 {
		                 	if (Lock_raise) Need_raise = AL4_system.id_limits[i];
		                 	else
		                 	throw new E_Limit_exceeded(AL4_system.id_limits[i]);
		                 }
		                 break;
    				case 1:
		    			 if (AL4_system.total_func > AL4_system.value_limits[i])
		    			 {
		                 	if (Lock_raise) Need_raise = AL4_system.id_limits[i];
		                 	else
		                 	throw new E_Limit_exceeded(AL4_system.id_limits[i]);
		    			 }
		    			 break;
    				case 2:
		    			 if (AL4_system.total_loops > AL4_system.value_limits[i])
		    			 {
		                 	if (Lock_raise) Need_raise = AL4_system.id_limits[i];
		                 	else
		                 	throw new E_Limit_exceeded(AL4_system.id_limits[i]);
		    			 }
		    			 break;
    			}
    		}
    	}
    
    }
    
    
//#shadow_classes
    
    public class AL4_object
    {

//?{RTTI}
		public virtual int RTTI_object_type() {return 0;}
//#RTTI_type_info

		public static string RTTI_type_name(int index, int flags)
		{
			string[] info = RTTI_type_info[index].Split(',');
			string result = info[0];
			int pos = result.IndexOf('|');
			switch (flags)
			{
			case 0: if (pos >= 0)
					{
						result = result.Substring(0, pos);
						if (result[0] == '{') result += "}";
					}
					break;
			case 1: if (pos >= 0)
						result = result.Substring(0, pos) + 
								 result.Substring(pos+1);
					break;
			}
			return result;
		}
		
		public static int RTTI_type_kind(int index)
		{
			return RTTI_type_kinds[index];
		}
		
		public static int RTTI_count_classes()
		{
			int result = RTTI_type_info.Length;
			return result;
		}
		
		public static int RTTI_base_class(int class_index)
		{
			string info = RTTI_type_info[class_index];
			int pos = info.IndexOf(",base:");
			if (pos < 0) return -1;
			string[] ss = info.Substring(pos+6).Split(',');
			return Convert.ToInt32(ss[0]);
		}
		
		public static int RTTI_starting_class_record_index(int class_index)
		{
			string info = RTTI_type_info[class_index];
			int pos = info.IndexOf(",rec:");
			if (pos < 0) return -1;
			string[] ss = info.Substring(pos+5).Split(',');
			int start = Convert.ToInt32(ss[0]);
			return start;
		}
		
		public static int RTTI_count_class_records(int class_index)
		{
			string info = RTTI_type_info[class_index];
			int pos = info.IndexOf(",rec:");
			if (pos < 0) return -1;
			string[] ss = info.Substring(pos+5).Split(',');
			if (ss[1].Substring(0, 6) != "count:") return -1;
			int count = Convert.ToInt32(ss[1].Substring(7));
			return count;
		}

		public static void RTTI_class_records(
			int class_index, ArrayInt records)
		{
			records.Clear();
			int base_index = RTTI_base_class(class_index);
			if (base_index >= 0)
				RTTI_class_records(base_index, records);
			
			int start = RTTI_starting_class_record_index(class_index);
			int count = RTTI_count_class_records(class_index);
			
			for (int i = start; count-- > 0; i++)
			{
				string info = RTTI_type_info[i];
				if (info.Contains(",items:")) continue;
				records.Add(i);
			}
		}
		
		public static void RTTI_class_enums(
			int class_index, ArrayInt enums)
		{
			enums.Clear();
			int base_index = RTTI_base_class(class_index);
			if (base_index >= 0)
				RTTI_class_enums(base_index, enums);
			
			int start = RTTI_starting_class_record_index(class_index);
			int count = RTTI_count_class_records(class_index);
			
			for (int i = start; count-- > 0; i++)
			{
				string info = RTTI_type_info[i];
				if (!info.Contains(",items:")) continue;
				enums.Add(i);
			}
		}

		public static int RTTI_starting_enum_items_index(int enum_type_index)
		{
			string info = RTTI_type_info[enum_type_index];
			int pos = info.IndexOf(",items:");
			if (pos < 0) return -1;
			string[] ss = info.Substring(pos+7).Split(',');
			int start = Convert.ToInt32(ss[0]);
			return start;
		}
		
		public static int RTTI_enum_count(int enum_type_index)
		{
			string info = RTTI_type_info[enum_type_index];
			int pos = info.IndexOf(",count:");
			if (pos < 0) return 0;
			int count = Convert.ToInt32(info.Substring(pos+7));
			return count;
		}

		public static string RTTI_enum_item(
			int enum_type_index, int index_item)
		{
			int start = RTTI_starting_enum_items_index(enum_type_index);
			int count = RTTI_enum_count(enum_type_index);
			if (index_item < 0 || index_item >= count) return "";
			return RTTI_enum_items[start + index_item];
		}
		
//.
public static int probe_line;

        public static AL4_object NoneObj_AL4_object;
        public static AL4_object DummyObj_AL4_object;
        
        //just for debugging:
        private static int total_obj_counter;
        public int TOTAL_obj_index;
        public AL4_object()
        {
            DO = new Methods_AL4_object(this);
            TOTAL_obj_index = ++total_obj_counter;
            if (TOTAL_obj_index == 999) // == 999
            { }
        }

        // Fastest way to check if a variable is referencing the NONE
        public bool Is_NONE_object = false;

        // Back reference to a Ref_obj, containing a hard link onto the object
        private Ref_obj h_link;
        public Ref_obj hard_link
        {
            get { return h_link; }
            set
            {
                if (TOTAL_obj_index == 197)
                { }

                h_link = value;
            }
        }

        // Back reference to a Ref_obj, containing a weak link to the object
        public Ref_obj weak_link;

        // Additional link onto the object itself to make changes in fields.
        // For the NONE object, it is referencing the dummy_obj, so NONE is never
        // changed (though it is not necessary to check value for NONE).
        public AL4_object write;

        // Object NONE instance (single for a class)
        protected static Ref_obj None_obj;

        // Object Dummy instance (single for a class)
        protected static Ref_obj dummy_obj;

        //------------- for OWNED BY children:
        public List<Ref_obj> children = null;

        public virtual Ref_obj NONE_obj_instance()
        {
            return None_obj;
        }

        public static Ref_obj Dummy_obj
        {
            get { return dummy_obj; }
        }

        public virtual AL4_object NONE_base_obj()
        {
            return null;
        }

        public static void Object_assign_hard(ref Ref_obj Dest, AL4_object Src)
        {
            // In case when an object is assigned to a field of NONE:
            //  the worst is what happened: a leak of an object created and 
            //  assigned to such field but no memory corruption occur.
            if (Dest == null)
            {
            	#if DIAGNOSTICS
            		#if DIAGNOSTICS_LIGHT
            		#else
            			AL4_system.diag_report(
            			"OAH: Object assigning hard to NONE destination");
            		#endif
            	#endif
            	return;
            } 
            
            // First increment source counter, so in case when a variable gets
            // as a new value itself, nothing bad is occur. }
            Src.hard_link.Count += 2;
            // Increment by 2, since 1 is used as a flag (In hard refs - as 
            // a flag that an object is owned and it should not be released
            // until its owner is released. In weak refs it is always set.)
            Dest.Ref_dec_hard();
            Dest = Src.hard_link;
        }
        
        public static void Object_assign_weak(ref Ref_obj Dest, AL4_object Src)
        {
            if (Dest == null) 
            {
            	#if DIAGNOSTICS
            		#if DIAGNOSTICS_LIGHT
            		#else
            			AL4_system.diag_report(
            			"OAW: Object assigning weak to NONE destination");
            		#endif
            	#endif
            	return;
            }
            Src.weak_link.Count += 2;
            Dest.Ref_dec_weak();
            Dest = Src.weak_link;
        }
        
        public static void Object_assign_hard_noincref(
               ref Ref_obj Dest, AL4_object Src)
        {
            if (Dest == null) 
            {
            	#if DIAGNOSTICS
            		#if DIAGNOSTICS_LIGHT
            		#else
            			AL4_system.diag_report(
            			"OAHN: Object assigning hard (no inc ref) " +
            			"to NONE destination");
            		#endif
            	#endif
            	return;
            }
            Dest.Ref_dec_hard();
            Dest = Src.hard_link;
        }
        
        public static void Object_assign_weak_noincref(
               ref Ref_obj Dest, AL4_object Src)
        {
            if (Dest == null) 
            {
            	#if DIAGNOSTICS
            		#if DIAGNOSTICS_LIGHT
            		#else
            			AL4_system.diag_report(
            			"OAWN: Object assigning weak (no inc ref) " +
            			"to NONE destination");
            		#endif
            	#endif
            	return;
            }
            Dest.Ref_dec_weak();
            Dest = Src.weak_link;
        }
        
        public AL4_object Write
        {
            get { return (AL4_object)write; }
            set { write = value; }
        }
        
        public static Ref_obj New()
        {
            return null;
        }
        
        public static Ref_obj New_owned(Ref_obj owner)
        {
            return null;
        }

        public Ref_obj Owned_by(Ref_obj owner)
        {
            if (owner.Obj.Is_NONE_object) return hard_link;
            if (owner.Obj.children == null)
                owner.Obj.children = new List<Ref_obj>();
            owner.Obj.children.Add(hard_link);
            hard_link.Count |= 1;
            return hard_link;
        }

        public Methods_AL4_object DO;
        
        public static void init_class_AL4_object()
        {
            NoneObj_AL4_object = (AL4_object)AL4_object.New_nofields().Obj;
            NoneObj_AL4_object.Is_NONE_object = true;
            None_obj = NoneObj_AL4_object.hard_link;
            DummyObj_AL4_object = (AL4_object)AL4_object.New_nofields().Obj;
            NoneObj_AL4_object.write = DummyObj_AL4_object;
            NoneObj_AL4_object.DO = new Noneclass_AL4_object(NoneObj_AL4_object);
            DummyObj_AL4_object.DO = new Noneclass_AL4_object(DummyObj_AL4_object);
        }
        
        public static Ref_obj New_nofields()
        {
            AL4_object Result = new AL4_object();
            Result.hard_link = new Ref_obj(Result, 2);
            Result.weak_link = new Ref_obj(Result, 1);
            Result.Write = Result;
            return Result.hard_link;
        }
        
    }
    
    public class Methods_AL4_object
    {
    
        public static int Debug_all_methods_counter;
        public int Debug_Total_methods_index;
    
        public AL4_object This_obj;
        
        public Methods_AL4_object() { 
            Debug_Total_methods_index = Debug_all_methods_counter++;
        }
        
        public Methods_AL4_object(AL4_object obj_this) { This_obj = obj_this; }

        public virtual void Erase()
        {
            if (This_obj == null)
            {
            	#if DIAGNOSTICS
            		AL4_system.diag_report(
            		"ERASE: Erasing null referenced object");
            	#endif 
            	return; 
            }

            // 1st, destroy children if those are present:
            if (This_obj.children != null)
            {
                foreach (Ref_obj c in This_obj.children)
                {
//?{Thread}
					if (c.Migrated_ref != null)
					{
						//delay destroying of the object utntil it is returned
						//to the thread address space:
                		Thread.BeginCriticalRegion();
                		try
                		{
	                		c.Count = 0;
	                		if (c.Migrated_ref != null) continue;
	                		//but if we was too late to go into the critical
	                		//section and the object was returned, then destroy
	                		//it immediatelly
                		}
                		finally
                		{
	                		Thread.EndCriticalRegion();
                		}
					}
//.
                    c.Obj.DO.Erase();
                }
                This_obj.children.Clear();
            }
            DESTRUCT();
            
            This_obj.children = null;

            // destroy the object removeing all three references onto it:
            Ref_obj none = This_obj.NONE_obj_instance();

            This_obj.weak_link.Obj = none.Obj;
            This_obj.hard_link.Obj = none.Obj;
            This_obj.write = none.Obj.write;

            This_obj.hard_link = none;
            This_obj.weak_link = none;
            
            This_obj = null;
            //This_obj = none.Obj;
        }

        public static long CNT_CONSTRUCT; 
        public virtual void CONSTRUCT()
        {
            CNT_CONSTRUCT++;
        }

        public static long CNT_DESTRUCT;
        public virtual void DESTRUCT()
        {
            CNT_DESTRUCT++;
        }

    }
  
    
	public class AL4_handler
	{
		public virtual void Handler()
		{
		}
	}


    public class Noneclass_AL4_object : Methods_AL4_object
    {
        public Noneclass_AL4_object(AL4_object obj_this)
               : base(obj_this)
        {
        }
        
        public override void Erase()
        {
        }
    }

    
    public class Ref_obj
    {
        public AL4_object Obj;
        public int fCount;
        public int Count
        {
        	get { return fCount; }
        	set 
        	{ 
        		// if (Obj.TOTAL_obj_index == )
        		// { }
        		fCount = value;
        	}
        }
//?{Thread}        
		public int Thread_handle;
		public Ref_obj Migrated_ref;
		public Ref_obj Parent_ref;
//.
        // Is calling from New_owned() when an object is created with its 
        // exclusive owner but without a counter in its hard_link.
        public Ref_obj(AL4_object obj, int count)
        {
            Obj = obj;
            Count = count;
        }

        public 
		void Ref_dec_weak()
        {
            Obj.weak_link.Count -= 2;
            //--if (Count <= 1 && Obj.Is_NONE_object)
            {
                // in platforms without garbage collector,
                // place here code to destroy this Ref_obj
                // representing Weak reference to the object
                // which was already destroyed

                // in case of DotNet platform, it will be
                // destroyed automatically since there are
                // no more references to it.
            }
        }

        public
//?{Thread}
        virtual
//.
        void Ref_dec_hard()
        {
            Obj.hard_link.Count -= 2;
            if (Obj.hard_link.Count == 0)
            {
                // destroy was_Dest object
                // Since there are only two links onto the 
                // object (from its Hard_link and Weak_link
                // small linking objects), it is sufficiently
                // to replace those with other values to
                // destroy the object.
                Ref_obj old_link = Obj.hard_link;
                int old_count = old_link.Count;
                Obj.hard_link.Count |= 1;
                
                	Obj.DO.Erase();
                	
                old_link.Count = old_count;
            }
        }
        
        public void Discard_struct()
        {
            if (Obj.Is_NONE_object) return;
        	Ref_obj struct_obj = Obj.hard_link;
            struct_obj.Count = 2;
            struct_obj.Ref_dec_hard();
        }

        public Ref_obj Owned_by(Ref_obj owner)
        {
            if (owner.Obj.Is_NONE_object) return this;
            if (owner.Obj.children == null)
                owner.Obj.children = new List<Ref_obj>();
            owner.Obj.children.Add(this);
            Count |= 1;
            return this;
        }

    }

    public static class Handle_list<T>
    {
        public static int Count(List<T> list)
        {
            return list.Count;
        }
    }

    //--------------------------------------------------------------------------
 	public class Record_any
 	{
 		public virtual void copy(Record_any source)
 		{ }
 		
		public virtual Record_any Clone()
		{
			return null; 
			//new Record_any();
		}
 	}   
	
    //--------------------------------------------------------------------------
 	public class Structure_any : AL4_object
 	{
		public virtual Ref_obj Clone()
		{
			return null; 
		}
		
		public static Ref_obj Dismiss_structure(ref Ref_obj source) {
			Structure_any result = (Structure_any)source.Obj;
			source = source.Obj.NONE_obj_instance();  
			return result.hard_link;
		}
		
		public static Ref_obj Dismiss_array_item(ArrayObjHard array,
			int Index)
		{
			Structure_any result = (Structure_any)array.get_obj(Index).Obj;
			//result.hard_link.Count += 2;
			if (!result.Is_NONE_object)
			{
		 		array.set_obj(Index, result.NONE_obj_instance());  
			}
			return result.hard_link;
		}
 	}   
	
	
    //--------------------------------------------------------------------------
 	public class ArrayAny
 	{
 		public virtual void Clear()
 		{}
 		
#debug:	public int TOTAL_array_index;
#debug: public static int TOTAL_arrays_counter;
#debug: public ArrayAny()
#debug: {
#debug: 	TOTAL_array_index = ++TOTAL_arrays_counter;
#debug: }
	
 		
		public CacheOfArrays Temps = null;
 		
		public static int MAX_CACHED_ARRAYS = 1024;
		
//?{Thread}
		[ThreadStatic]
//.
		public static List<List<ArrayAny>> List_lists_temps 
			= new List<List<ArrayAny>>();
 		
		public static void release_temp_lists(List<ArrayAny> List)
		{
			for (int i = List.Count-1; i >= 0; i--)
			{
				ArrayAny A = List[i];
				A.Clear();
				CacheOfArrays C = A.Temps;
				if (C != null && C.list.Count < MAX_CACHED_ARRAYS)
					C.list.Add(A);
			}
			List.Clear();
			List_lists_temps.Add(List);
		}
		
		public static void clear_list_temps(List<ArrayAny> List)
		{
			for (int i = List.Count-1; i >= 0; i--)
			{
				ArrayAny A = List[i];
				A.Clear();
				CacheOfArrays C = A.Temps;
				if (C != null && C.list.Count < MAX_CACHED_ARRAYS)
					C.list.Add(A);
			}
			List.Clear();
		}
		
		public static List<ArrayAny> allocate_list_temps()
		{
//?{Thread}
			if (List_lists_temps == null)
				List_lists_temps = new List<List<ArrayAny>>();
//.
			if (List_lists_temps.Count > 0)
			{
				List<ArrayAny> Result = List_lists_temps[List_lists_temps.Count-1];
				List_lists_temps.RemoveAt(List_lists_temps.Count-1);
				return Result;
			}
			var result = new List<ArrayAny>();
			return result;
		}
		
		public virtual int Count { get { return 0; } }
		public virtual void Delete(int index) { }
		public virtual void Delete_range(int index, 
@int32:	int
@int64:	long
		count) 
		{
			if (index < 0)
			{
				count+=index;
				index = 0;
			} 
			if (index == 0 && count >= Count)
			{
				Clear();
				return;
			}
			while (count-- > 0)
			{
				if (index >= Count) return;
				Delete(index);
			} 
		}
		
		public virtual ArrayAny Create_empty_array() { return this; }
		
		public virtual ArrayAny Clone_array() { return null; }
		
		public virtual ArrayAny Clone_struct_array() { return null; }
		
		public virtual void Allocate(int New_capacity) { }
		
 	}
 	
	public class CacheOfArrays
	{
		public List<ArrayAny> list = new List<ArrayAny>();
	}
	
    public class ArrayObjHard : ArrayAny
    {
        public Ref_obj none_obj;
        
        public ArrayObjHard(Ref_obj none)
        {
            none_obj = none;
        }
        
        //public Ref_obj this[int index]
        //{
            //get { return get_obj(index); }
            //set { set_obj(index, value); }
        //}
        
        public virtual Ref_obj get_obj(int index) { return null; }
        public virtual void set_obj(int index, Ref_obj value) {}
        public virtual void Add(Ref_obj X) { }
        public virtual void Insert(int index, Ref_obj X) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(Ref_obj Obj) { return -1; }
        public virtual void Remove(Ref_obj Obj) { }
        public virtual void Swap(int i, int j) { }
        
        public bool is_array_of_struc;
        
        public void Dispose()
        {
        	if (is_array_of_struc) ((DynAObjHard)this).Clear_struc();
        	else Clear();
        }
        
        public bool Contains(Ref_obj Obj)
        { 
            return IndexOf(Obj) >= 0;
        }
    }
    
    //--------------------------------------------------------------------------
    public class DynAObjHard : ArrayObjHard
    {
        public List<Ref_obj> Base;
        
        public DynAObjHard(Ref_obj none) : base(none)
        {
            Base = new List<Ref_obj>();
        }

        public override Ref_obj get_obj(int index)
        {
            if ((uint)index >= (uint)(Count))
            {
            #if DIAGNOSTICS
            	#if DIAGNOSTICS_LIGHT
            	if (index == Count || index==-1 && Count==0) {}
            	else
            	#endif
            		AL4_system.diag_report(
            		"AGO: Get object from objects array bounds violation, "
            		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
                return none_obj;
            }
            return Base[index];
        }
        
        public override void set_obj(int index, Ref_obj value)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
            		AL4_system.diag_report(
            		"ASO: Set object in an objects array bounds violation, "
            		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            } 
            Ref_obj old = Base[index];
            Base[index] = value;
            value.Obj.hard_link.Count += 2;
            old.Ref_dec_hard();
        }

		//-------------- for arrays of structures
        public void Remove_struc(Ref_obj Obj)
        {
            for (int i = Count-1; i>= 0; i--)
                if (Base[i].Obj == Obj.Obj)
                {
                	(Obj).Discard_struct();
                    Base.RemoveAt(i);
                    //return;
                }
        }
        
		//-------------- for arrays of structures
		public virtual void Delete_range_struc(int index, 
@int32:	int
@int64:	long
		count) 
		{
			if (index < 0)
			{
				count+=index;
				index = 0;
			} 
			if (index == 0 && count >= Count)
			{
				Clear_struc();
				return;
			}
			while (count-- > 0)
			{
				if (index >= Count) return;
				Del_struc(index);
			} 
		}
		
		//-------------- for arrays of structures
        public void Clear_struc()
        {
        	for (int i = Count-1; i >= 0; i--)
        	{
        		 Ref_obj obj = get_obj(i);
        		 obj.Count = 2;
        	}
        	Clear();
        }
        
        public override void Add(Ref_obj X)
        {
            Base.Add(X);
            X.Obj.hard_link.Count += 2;
        }
        
        public override void Insert(int index, Ref_obj X)
        {
        	if (index < 0) return;
        	if (index > Base.Count) index = Base.Count;
            Base.Insert(index, X);
            X.Obj.hard_link.Count += 2;
        }
      

        // Used only in case when new oject is added to an array
        // of hard links, to provide correct usage Count value
        //------------------------------------------------------
        public void Ref_dec_last()
        {
            if (Count == 0) return;
            get_obj(Count - 1).Ref_dec_hard();
        }

        public override void Clear()
        {
            for (int i = Count-1; i >= 0; i--)
            {
                Ref_obj obj = get_obj(i);
                obj.Ref_dec_hard();
            }
            Base.Clear();
        }
        
        public override int Count 
        {
            get { return Base.Count; }
        }
        
        public override int IndexOf(Ref_obj Obj)
        {
            for (int i = 0; i < Count; i++)
            {
                if (Base[i].Obj == Obj.Obj) return i;
            }
            return -1;
        }

        public override void Delete(int index)
        {
            if ((uint)index >= (uint)Base.Count)
            {
            #if DIAGNOSTICS
            		AL4_system.diag_report(
            		"DAO: Delete object in an objects array bounds violation, "
            		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            } 
            Base[index].Ref_dec_hard();
            Base.RemoveAt(index);
        }
        
        public override void Remove(Ref_obj Obj)
        {
            for (int i = Count-1; i >= 0; i--)
                if (Base[i].Obj == Obj.Obj)
                {
                    Base.RemoveAt(i);
                    Obj.Ref_dec_hard();
                }
        }
        
		public override void Swap(int i, int j) // of DynAObjHard
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
				return;
			Ref_obj X = Base[i];
			Ref_obj Y = Base[j];
			Base[i] = Y;
			Base[j] = X;
		}
        
		public static DynAObjHard new_DynAObjHard(Ref_obj none)
		{
			DynAObjHard result = new DynAObjHard(none);
			return result;
		}
        
		public static DynAObjHard new_DynAStruct(Ref_obj none)
		{
			DynAObjHard result = new DynAObjHard(none);
			result.is_array_of_struc = true;
			return result;
		}
        
		public override ArrayAny Create_empty_array()
		{ 
			return new DynAObjHard(none_obj); 
		}
		
		public override ArrayAny Clone_array() {
			DynAObjHard result = new DynAObjHard(none_obj);
			for (int i = 0; i < Count; i++) {
				result.Add(get_obj(i));
			}
			return result;
		}
		
		public override ArrayAny Clone_struct_array() {
			DynAObjHard result = new DynAObjHard(none_obj);
			for (int i = 0; i < Count; i++) {
				result.Add(( (Structure_any)(get_obj(i).Obj) ).Clone());
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			if (Count < New_size) Base.Capacity = New_size;
			for (int i = Count; i < New_size; i++)
				Base.Add(none_obj);
			for (int i = Count-1; i >= New_size; i--) {
				Delete(i);
			}
		}
		
		//-------------- for arrays of structures
        public void Del_struc(int index)
        {
            if ((uint)index >= Count) 
            {
	            #if DIAGNOSTICS
            		AL4_system.diag_report(
            		"DASTRUC: Delete structure in an array bounds violation, "
            		+ "i=" + index.ToString() + " Count=" + Count.ToString());
	            #endif
            	return;
            }
            (get_obj(index)).Discard_struct();
            Base.RemoveAt(index);
        }
        
    }

    //--------------------------------------------------------------------------
    public class DynAObjWeak : DynAObjHard
    {
        public DynAObjWeak(Ref_obj none) : base(none)
        {
            none_obj = none;
        }

        public override Ref_obj get_obj(int index)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
            	#if DIAGNOSTICS_LIGHT
            	if (index == Count || index==-1 && Count==0) {}
            	else
            	#endif
            		AL4_system.diag_report(
            		"AGOW: Get object from objects weak array bounds violation, "
            		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
                return none_obj;
            }
            return Base[index];
        }
        
        public override void set_obj(int index, Ref_obj value)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"ASOW: Set object in an objects weak array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            }
            Ref_obj old = Base[index];
            Base[index] = value;
            value.Obj.weak_link.Count += 2;
            old.Ref_dec_weak();
        }

        public override void Add(Ref_obj X)
        {
            Base.Add(X);
            X.Obj.weak_link.Count += 2;
        }
        
        public override void Insert(int index, Ref_obj X)
        {
        	if (index < 0) return;        
        	if (index > Base.Count) index = Base.Count;
            base.Insert(index, X);
            X.Obj.weak_link.Count += 2;
        }

        public override void Clear()
        {
            for (int i = Count-1; i >= 0; i--)
            {
                Ref_obj obj = get_obj(i);
                obj.Ref_dec_weak();
            }
//?{Slice}
            if (L > 0)
            	Base.RemoveRange(L, Count - L);
            else
//.
            	Base.Clear();
        }
        
        public override void Delete(int index)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"DAOW: Delete object in an objects weak array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            }
            Base[index].Ref_dec_weak();
            Base.RemoveAt(index);
        }
        
        public override void Remove(Ref_obj Obj)
        {
            for (int i = Count-1; i >=0; i--)
                if (Base[i] == Obj)
                {
                    Obj.Ref_dec_weak();
                    Base.RemoveAt(i);
                    //return;
                }
        }
        
		public static DynAObjWeak new_DynAObjWeak(Ref_obj none)
		{
			DynAObjWeak result = new DynAObjWeak(none);
			return result;
		}
        
		public override ArrayAny Create_empty_array() 
		{ 
			return new DynAObjWeak(none_obj); 
		}
		
		public override ArrayAny Clone_array() {
			DynAObjWeak result = new DynAObjWeak(none_obj);
			for (int i = 0; i < Count; i++) {
				result.Add(get_obj(i));
			}
			return result;
		}		
		
    }

    public class FixAObj : ArrayObjHard
    {
        public DynAObjHard BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;
        
        public FixAObj(int N_ignored_use_0) 
        	: base(AL4_object.NoneObj_AL4_object.hard_link)
        {
            BaseList = new DynAObjHard(AL4_object.NoneObj_AL4_object.hard_link);
        }

        public FixAObj(Ref_obj none) : base(none)
        {
            BaseList = new DynAObjHard(none);
        }

        public FixAObj(DynAObjHard base_list, int From_idx, int To_idx)
                : base(base_list.none_obj)
        {
            Is_range = true;
            BaseList = base_list;
            Starting = From_idx;
            Count_items = To_idx - From_idx + 1;
        }

        public FixAObj(FixAObj base_list, int From_idx, int To_idx)
                : base(base_list.none_obj)
        {
            Is_range = true;
            BaseList = base_list.BaseList;
            Starting = From_idx + base_list.Starting;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }
        
        public FixAObj(ArrayObjHard base_list, int From_idx, int To_idx)
        		: base(base_list.none_obj)
        {
        	if (base_list is FixAObj)
        	{
	            Is_range = true;
	            BaseList = ((FixAObj)base_list).BaseList;
	            Starting = From_idx + ((FixAObj)base_list).Starting;
	            Count_items = To_idx + 1 - From_idx;
        	}
        	else
        	{
	            Is_range = true;
	            BaseList = (DynAObjHard)base_list;
	            Starting = From_idx;
	            Count_items = To_idx - From_idx + 1;
        	}
        	if (Count_items < 0) Count_items = 0;
        }

        ~FixAObj()
        {
            Dispose();
            BaseList = null;
        }

        public override Ref_obj get_obj(int index)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"FAO: Getting object in a fixed objects array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
                return BaseList.none_obj;
            }
            return BaseList.Base[Starting + index];
        }
        
        public override void set_obj(int index, Ref_obj value)
        {
            if ((uint)index >= (uint)Count_items) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"FAOW: Setting object in a fixed objects array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            }
        	BaseList.set_obj(Starting + index, value);
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(Ref_obj Obj)
        {
            for (int i = Starting; i < Starting + Count_items; i++)
                if (BaseList.Base[i].Obj == Obj.Obj) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Dispose();
            Count_items = 0;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_obj(i, none_obj);
        }
        
        public override void Swap(int i, int j) // of FixAObj
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SFAO: Swapping objects in a fixed objects array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			Ref_obj X = BaseList.Base[Starting + i];
			Ref_obj Y = BaseList.Base[Starting + j];
			BaseList.set_obj(Starting + i, Y);
			BaseList.set_obj(Starting + j, X);
		}

//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAObj = new CacheOfArrays();
        
        public static FixAObj new_FixAObj(List<ArrayAny> List_temps,
        	DynAObjHard base_list, int From_idx, int To_idx)
		{
			FixAObj result = null;
			if (cache_FixAObj.list.Count > 0)
			{
				result = (FixAObj)cache_FixAObj.list[cache_FixAObj.list.Count-1];
				cache_FixAObj.list.RemoveAt(cache_FixAObj.list.Count-1);
			}
			else
			{
				result = new FixAObj(base_list, From_idx, To_idx);
				result.Temps = cache_FixAObj;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
        
        public static FixAObj new_FixAObj(List<ArrayAny> List_temps,
        	FixAObj base_list, int From_idx, int To_idx)
		{
			FixAObj result = null;
//?{Thread}
			if (cache_FixAObj == null)
				cache_FixAObj  = new CacheOfArrays();
//.
			if (cache_FixAObj.list.Count > 0)
			{
				result = (FixAObj)cache_FixAObj.list[cache_FixAObj.list.Count-1];
				cache_FixAObj.list.RemoveAt(cache_FixAObj.list.Count-1);
			}
			else
			{
				result = new FixAObj(base_list, From_idx, To_idx);
				result.Temps = cache_FixAObj;
			}
			result.BaseList = base_list.BaseList;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Starting + base_list.Count)
				From_idx = base_list.Starting + base_list.Count;
			if (To_idx > base_list.Starting + base_list.Count)
				To_idx = base_list.Starting + base_list.Count;
			result.Starting = From_idx + base_list.Starting;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
		
        public static FixAObj new_FixAObj(List<ArrayAny> List_temps,
        	ArrayObjHard base_array_obj, int From_idx, int To_idx)
		{
			if (base_array_obj is DynAObjHard) 
			{
				return new_FixAObj(List_temps, (DynAObjHard)base_array_obj,
					From_idx, To_idx);
			}
			if (base_array_obj is FixAObj)
			{
				return new_FixAObj(List_temps, (FixAObj)base_array_obj,
					From_idx, To_idx);
			}
			throw new Exception(
				"Incorrect array parameter type to create FixAObj");
		}
        
		public override ArrayAny Clone_array() {
			FixAObj result = new FixAObj(none_obj);
			result.BaseList = new DynAObjHard(none_obj);
			for (int i = 0; i < Count; i++)
				result.BaseList.Add(get_obj(i));
			result.Count_items = Count;
			return result;
		}
        
		public override ArrayAny Clone_struct_array() {
			FixAObj result = new FixAObj(none_obj);
			result.BaseList = new DynAObjHard(none_obj);
			for (int i = 0; i < Count; i++)
				result.BaseList.Add(( (Structure_any)(get_obj(i).Obj) ).Clone());
			result.Count_items = Count;
			return result;
		}
        
    }
    
    //--------------------------------------------------------------------------
    public class ArrayInt : ArrayAny
    {
        public 
@int32: int
@int64: long
        this[int index]
        {
            get { return get_int(index); }
            set { set_int(index, value); }
        }
        
        public virtual 
@int32: int
@int64: long
        get_int(int index) { return 0; }
        public virtual void set_int(int index, 
@int32: int value
@int64: long value
        ) {}
        public virtual void Add(
@int32: int X
@int64: long X
        ) { }
        public virtual void Insert(int index, 
@int32:	int X
@int64:	long X
        ) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(
@int32: int value
@int64: long value
        ) { return -1; }
        public virtual void Remove(
@int32: int value
@int64: long value
        ) { }
        public virtual void Set_capacity(int new_cap) { }
        public virtual void Swap(int i, int j) { }
        
        public void Dispose()
        {
            Clear();
        }
        
        public bool Contains(
@int32: int value
@int64: long value
        )
        { 
            return IndexOf(value) >= 0;
        }
        
		public virtual void Copy(int to_index, FixAInt Source)
		{
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_int(i, Source[j++]);
			}
		}
		
		public virtual void Copy(int to_index, ArrayInt Source,
			int from_start, int from_end)
		{
			int j = from_start;
			int last = to_index + from_end - from_start;
			if (last > Count) last = Count-1;
			for (int i = to_index; i <= last; i++)
			{
				set_int(i, Source[j++]);
			}
		}
		
		public void Fill(int to_index, 
@int32: int Value,
@int64: long Value,
		int count_fill)
		{
			for (int i = to_index; i < to_index + count_fill; i++)
			{
				if (i >= Count) break;
				set_int(i, Value);
			}
		}
		
		public void Repeat(int to_index, ArrayInt Source, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = 0; j < Source.Count; j++)
				{
					if (to_index >= Count) return;
					set_int(to_index++, Source[j]);
				}
			}
		}
        
		public void Repeat(int to_index, ArrayInt Source,
			int from_start, int from_end,
			int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = from_start; j <= from_end; j++)
				{
					if (to_index >= Count) return;
					set_int(to_index++, Source[j]);
				}
			}
		}
        
    }
    
    //--------------------------------------------------------------------------
    public class DynAInt : ArrayInt
    {
@int32: public List<int> Base;
@int64: public List<long> Base;

        public DynAInt() { Base = new 
@int32: List<int>
@int64: List<long>
        (); }
    
        public override 
@int32: int
@int64: long 
        get_int(int index)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IA: Getting item in an integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            }
            return Base[index];
        }
        
        public override void set_int(int index, 
@int32: int value
@int64: long value
        )
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IAW: Setting item in an integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            }
            Base[index] = value;
        }

        public override void Add(
@int32: int X
@int64: long X
        ) { Base.Add(X); }
        
        public override void Insert(int index, 
@int32: int X
@int64: long X
        )
        {
        	if (index < 0) 
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IIA: Inserting an item in an integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + X.ToString());
            #endif
        		return;
        	}
        	if (index > Base.Count) index = Base.Count;
            Base.Insert(index, X); 
        }
        
        public override void Clear() 
        {
        		Base.Clear();
        }
        
        public override int Count { 
        	   get { return Base.Count; } }
        
        public override int IndexOf(
@int32: int value
@int64: long value
        ) 
        {
        	return Base.IndexOf(value);
        }
        
        public override void Delete(int index)
        { 
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"DIA: Deletting item in an integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            }
            Base.RemoveAt(index);
        }
        
        public override void Remove(
@int32:	int value
@int64:	long value
        ) 
        {
        		Base.Remove(value);
        }
        
        public override void Swap(int i, int j) // of DynAInt
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SIA: Swapping items in an integers array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString()  
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
@int32:		int X = Base[i];
@int64:		long X = Base[i];
@int32:		int Y = Base[j];
@int64:		long Y = Base[j];
			Base[i] = Y;
			Base[j] = X;
		}

        public override void Set_capacity(int new_cap)
        { Base.Capacity = new_cap; }
        
		public static DynAInt new_DynAInt()
		{
			DynAInt result = new DynAInt();
			return result;
		}
        
		public override ArrayAny Create_empty_array() 
		{ 
			return new DynAInt(); 
		}
		
		public override ArrayAny Clone_array() {
			DynAInt result = new DynAInt();
			for (int i = 0; i < Count; i++) {
				result.Add(get_int(i));
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			if (Count < New_size) Base.Capacity = New_size;
			for (int i = Count; i < New_size; i++)
				Base.Add(0);
			for (int i = Count-1; i >= New_size; i--)
				Base.RemoveAt(i);
		}
				
    }
    
    //--------------------------------------------------------------------------
    public class FixAInt : ArrayInt
    {
        public ArrayInt BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;

        public FixAInt(int N)
        {
            BaseList = new DynAInt();
            BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                BaseList.Add(0);
            Count_items = BaseList.Count;
        }

        public FixAInt(
@int32: int[] A
@int64: long[] A
        )
        {
            BaseList = new DynAInt();
            BaseList.Set_capacity(A.Length);
            foreach (int i in A)
                BaseList.Add(i);
            Count_items = BaseList.Count;
        }

        public FixAInt(DynAInt base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list;
            Starting = From_idx;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }

        public FixAInt(FixAInt base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list.BaseList;
            Starting = From_idx + base_list.Starting;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }

        public FixAInt(ArrayInt base_list, int From_idx, int To_idx)
        {
            if (base_list is FixAInt)
            {
                Is_range = true;
                BaseList = ((FixAInt)base_list).BaseList;
                Starting = From_idx + ((FixAInt)base_list).Starting;
                Count_items = To_idx + 1 - From_idx;
            }
            else
            {
                Is_range = true;
                BaseList = (DynAInt)base_list;
                Starting = From_idx;
                Count_items = To_idx + 1 - From_idx;
            }
            if (Count_items < 0) Count_items = 0;
        }

        ~FixAInt()
        {
            Dispose();
        }

        public override 
@int32: int
@int64: long
        get_int(int index)
        {
            if ((uint)index >= (uint)Count_items) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IFA: Getting item in a fixed integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            }
            return ((DynAInt)BaseList).get_int(Starting + index);
        }
        
        public override void set_int(int index, 
@int32:	int value
@int64:	long value
        )
        {
            if ((uint)index >= (uint)Count_items) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IFAW: Setting item in a fixed integers array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            }
            ((DynAInt)BaseList).set_int(Starting + index, value);
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(
@int32:	int Value
@int64:	long Value
        )
        {
            for (int i = Starting; i < Starting + Count_items; i++)
                if (((DynAInt)BaseList).Base[i] == Value) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Clear();
            Count_items = 0;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_int(i, 0);
        }
        
        public override void Swap(int i, int j) // of FixAInt
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count) 
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SIFA: Swapping items in a fixed integers array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
@int32:		int X = ((DynAInt)BaseList).Base[Starting + i];
@int64:		long X = ((DynAInt)BaseList).Base[Starting + i];
@int32:		int Y = ((DynAInt)BaseList).Base[Starting + j];
@int64:		long Y = ((DynAInt)BaseList).Base[Starting + j];
			((DynAInt)BaseList).Base[Starting + i] = Y;
			((DynAInt)BaseList).Base[Starting + j] = X;
		}

		public FixAInt copy()
		{
			FixAInt result = new FixAInt(Count);
            for (int i = 0; i < Count; i++)
                result.set_int(i, get_int(i));
            return result;
		}
		
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAInt = new CacheOfArrays();
        
		public static FixAInt new_FixAInt(List<ArrayAny> List_temps, int N)
		{
			FixAInt result = null;
//?{Thread}
			if (cache_FixAInt == null)
				cache_FixAInt  = new CacheOfArrays();
//.
			if (cache_FixAInt.list.Count > 0)
			{
				result = (FixAInt)cache_FixAInt.list[cache_FixAInt.list.Count-1];
				cache_FixAInt.list.RemoveAt(cache_FixAInt.list.Count-1);
			}
			else
			{
				result = new FixAInt(N);
				result.Temps = cache_FixAInt;
			}
			result.BaseList = new DynAInt();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(0);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;
			if (List_temps != null) List_temps.Add(result);			
			return result;
		}
        
		public static FixAInt new_FixAInt(List<ArrayAny> List_temps, 
@int32:	int[] A
@int64:	long[] A
		)
		{
			FixAInt result = null;
//?{Thread}
			if (cache_FixAInt == null)
				cache_FixAInt  = new CacheOfArrays();
//.
			if (cache_FixAInt.list.Count > 0)
			{
				result = (FixAInt)cache_FixAInt.list[cache_FixAInt.list.Count-1];
				cache_FixAInt.list.RemoveAt(cache_FixAInt.list.Count-1);
			}
			else
			{
				result = new FixAInt(A);
				result.Temps = cache_FixAInt;
			}
			result.BaseList = new DynAInt();
        	result.BaseList.Set_capacity(A.Length);
        	for (int i = 0; i < A.Length; i++)
         	   result.BaseList.Add(A[i]);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;		   
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
		
		public static FixAInt new_FixAInt(List<ArrayAny> List_temps,
			DynAInt base_list, int From_idx, int To_idx)
		{
			FixAInt result = null;
//?{Thread}
			if (cache_FixAInt == null)
				cache_FixAInt  = new CacheOfArrays();
//.
			if (cache_FixAInt.list.Count > 0)
			{
				result = (FixAInt)cache_FixAInt.list[cache_FixAInt.list.Count-1];
				cache_FixAInt.list.RemoveAt(cache_FixAInt.list.Count-1);
			}
			else
			{
				result = new FixAInt(base_list, From_idx, To_idx);
				result.Temps = cache_FixAInt;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

		public static FixAInt new_FixAInt(List<ArrayAny> List_temps,
			FixAInt base_list, int From_idx, int To_idx)
		{
			FixAInt result = null;
//?{Thread}
			if (cache_FixAInt == null)
				cache_FixAInt  = new CacheOfArrays();
//.
			if (cache_FixAInt.list.Count > 0)
			{
				result = (FixAInt)cache_FixAInt.list[cache_FixAInt.list.Count-1];
				cache_FixAInt.list.RemoveAt(cache_FixAInt.list.Count-1);
			}
			else
			{
				result = new FixAInt(base_list, From_idx, To_idx);
				result.Temps = cache_FixAInt;
			}
			result.BaseList = base_list.BaseList;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Starting + base_list.Count)
				From_idx = base_list.Starting + base_list.Count;
			if (To_idx > base_list.Starting + base_list.Count)
				To_idx = base_list.Starting + base_list.Count;
			result.Starting = From_idx + base_list.Starting;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
		
		public static FixAInt new_FixAInt(List<ArrayAny> List_temps, 
			ArrayInt base_list, int From_idx, int To_idx)
		{
			FixAInt result = null;
//?{Thread}
			if (cache_FixAInt == null)
				cache_FixAInt  = new CacheOfArrays();
//.
			if (cache_FixAInt.list.Count > 0)
			{
				result = (FixAInt)cache_FixAInt.list[cache_FixAInt.list.Count-1];
				cache_FixAInt.list.RemoveAt(cache_FixAInt.list.Count-1);
			}
			else
			{
				result = new FixAInt(base_list, From_idx, To_idx);
				result.Temps = cache_FixAInt;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	

		public override ArrayAny Clone_array() {
			FixAInt result = new FixAInt(Count);
			for (int i = 0; i < Count; i++)
				result.set_int(i, get_int(i));
			return result;
		}
    }
    
	public class FixAInt_clamp : FixAInt
	{
		int mask_clamp;
		
		public override ArrayAny Clone_array() {
			FixAInt_clamp result = new FixAInt_clamp(Count);
			for (int i = 0; i < Count; i++)
				result.set_int(i, get_int(i));
			return result;
		}
	
		public FixAInt_clamp(int N) : base(N)
        {
        	mask_clamp = 1;
        	while (N > 2)
        	{
        		mask_clamp = (mask_clamp << 1) | 1;
        		N = N >> 1;
        	}
        }
        
        public override 
@int32:	int
@int64:	long
        get_int(int index)
        {
            return ((DynAInt)BaseList).Base[Starting + (index & mask_clamp)];
        }
        
        public override void set_int(int index, 
@int32:	int value
@int64:	long value
        )
        {
            ((DynAInt)BaseList).Base[Starting + (index & mask_clamp)] = value;
        }

		public new FixAInt_clamp copy()
		{
			FixAInt_clamp result = new FixAInt_clamp(Count);
            for (int i = 0; i < Count; i++)
                result.set_int(i, get_int(i));
            return result;
		}
		
        public override void Swap(int i, int j) // of FixAInt_clamp
		{
			i &= mask_clamp;
			j &= mask_clamp;
			
@int32:		int X = ((DynAInt)BaseList).Base[Starting + i];
@int64:		long X = ((DynAInt)BaseList).Base[Starting + i];
@int32:		int Y = ((DynAInt)BaseList).Base[Starting + j];
@int64:		long Y = ((DynAInt)BaseList).Base[Starting + j];
			((DynAInt)BaseList).Base[Starting + i] = Y;
			((DynAInt)BaseList).Base[Starting + j] = X;
		}

//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAInt_clamp = new CacheOfArrays();
		
		public static FixAInt_clamp new_FixAInt_clamp(List<ArrayAny> List_temps,
			int N)
		{
			FixAInt_clamp result = null;
//?{Thread}
			if (cache_FixAInt_clamp == null)
				cache_FixAInt_clamp  = new CacheOfArrays();
//.
			if (cache_FixAInt_clamp.list.Count > 0)
			{
				result = (FixAInt_clamp)cache_FixAInt_clamp.list[
					cache_FixAInt_clamp.list.Count-1];
				cache_FixAInt_clamp.list.RemoveAt(
					cache_FixAInt_clamp.list.Count-1);
			}
			else
			{
				result = new FixAInt_clamp(N);
				result.Temps = cache_FixAInt_clamp;
			}
			result.BaseList = new DynAInt();
            result.BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                result.BaseList.Add(0);
            result.Starting = 0;
            result.Count_items = result.BaseList.Count;
            if (List_temps != null) List_temps.Add(result);
			return result;
		}	

	}

    
    //--------------------------------------------------------------------------
    public class ArrayReal : ArrayAny
    {
        public double this[int index]
        {
            get { return get_real(index); }
            set { set_real(index, value); }
        }
        
        public virtual double get_real(int index) { return 0; }
        public virtual void set_real(int index, double value) { }
        public virtual void Add(double X) { }
        public virtual void Insert(int index, double X) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(double value) { return -1; }
        public virtual void Remove(double value) { }
        public virtual void Set_capacity(int new_cap) { }
        public virtual void Swap(int i, int j) { }
        
        public void Dispose()
        {
            Clear();
        }
        
        public bool Contains(double value)
        { 
            return IndexOf(value) >= 0;
        }
        
		public virtual void Copy(int to_index, FixAReal Source)
		{
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_real(i, Source[j++]);
			}
		}
		
		public virtual void Copy(int to_index, ArrayReal Source,
			int from_start, int from_end)
		{
			int j = from_start;
			int last = to_index + from_end - from_start;
			if (last >= Count) last = Count-1;
			for (int i = to_index; i <= last; i++)
			{
				set_real(i, Source[j++]);
			}
		}
		
		public void Fill(int to_index, double Value, int count_fill)
		{
			for (int i = to_index; i < to_index + count_fill; i++)
			{
				if (i >= Count) break;
				set_real(i, Value);
			}
		}
		
		public void Repeat(int to_index, FixAReal Source, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = 0; j < Source.Count; j++)
				{
					if (to_index >= Count) return;
					set_real(to_index++, Source[j]);
				}
			}
		}
        
		public void Repeat(int to_index, ArrayReal Source, 
			int from_start, int from_end,
			int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = from_start; j <= from_end; j++)
				{
					if (to_index >= Count) return;
					set_real(to_index++, Source[j]);
				}
			}
		}
        
		public override ArrayAny Create_empty_array() 
		{ 
			return new DynAReal(); 
		}
		
    }

    //--------------------------------------------------------------------------
    public class DynAReal : ArrayReal
    {
    
        public List<double> Base;

        public DynAReal() { Base = new List<double>(); }
    
        public override double get_real(int index) 
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"RA: Getting item in a real array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            }
            return Base[index];
        }
        
        public override void set_real(int index, double value)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"RAW: Setting item in a real array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            }
            Base[index] = value;
        }
        
        public override void Add(double X) { Base.Add(X); }
        
        public override void Insert(int index, double X) 
        {
        	if (index < 0) 
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"RAI: Inserting item in a real array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + X.ToString());
            #endif
        		return;
        	}
        	if (index > Base.Count) index = Base.Count;
            Base.Insert(index, X);
        }
        
        public override void Clear()
        {
        	Base.Clear();
        }
        
        public override int Count 
        { 
        	get { return Base.Count; }
        }
         
        public override int IndexOf(double value)
        {
        	return Base.IndexOf(value);
        }
        
        public override void Delete(int index)
        { 
            if ((uint)index >= (uint)Count) return;
            Base.RemoveAt(index);
        }
        
        public override void Remove(double value)
        {
        	Base.Remove(value);
        }
        
        public override void Set_capacity(int new_cap)
        { Base.Capacity = new_cap; }
        
        public override void Swap(int i, int j) // of DynAReal 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SRA: Swapping items in a real array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			double X = Base[i];
			double Y = Base[j];
			Base[i] = Y;
			Base[j] = X;
		}

		public static DynAReal new_DynAReal()
		{
			DynAReal result = new DynAReal();
			return result;
		}	
	
		public override ArrayAny Clone_array() {
			DynAReal result = new DynAReal();
			result.Set_capacity(Count);
			for (int i = 0; i < Count; i++) {
				result.Add(get_real(i));
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			if (Count < New_size) Base.Capacity = New_size;
			for (int i = Count; i < New_size; i++)
				Base.Add(0);
			for (int i = Count-1; i >= New_size; i--)
				Base.RemoveAt(i);
		}
		
    }
    
    //--------------------------------------------------------------------------
    public class FixAReal : ArrayReal
    {
        public DynAReal BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;

        public FixAReal(int N)
        {
            BaseList = new DynAReal();
            BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                BaseList.Add(0);
            Count_items = BaseList.Count;
        }

        public FixAReal(double[] A)
        {
            BaseList = new DynAReal();
            BaseList.Set_capacity(A.Length);
            foreach (int i in A)
                BaseList.Add(i);
            Count_items = BaseList.Count;
        }

        public FixAReal(DynAReal base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list;
            Starting = From_idx;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }

        public FixAReal(FixAReal base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list.BaseList;
            Starting = From_idx + base_list.Starting;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }
        
        public FixAReal(ArrayReal base_list, int From_idx, int To_idx)
        {
        	if (base_list is FixAReal)
        	{
	            Is_range = true;
	            BaseList = ((FixAReal)base_list).BaseList;
	            Starting = From_idx + ((FixAReal)base_list).Starting;
	            Count_items = To_idx + 1 - From_idx;
        	}
        	else
        	{
	            Is_range = true;
	            BaseList = (DynAReal)base_list;
	            Starting = From_idx;
	            Count_items = To_idx + 1 - From_idx;
        	}
        	if (Count_items < 0) Count_items = 0;
        }

        ~FixAReal()
        {
            Dispose();
        }

        public override double get_real(int index) 
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"FRA: Getting item in a fixed real array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            } 
            return BaseList.Base[Starting + index];
        }
        
        public override void set_real(int index, double value)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"FRAW: Setting item in a fixed real array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            } 
            BaseList.Base[Starting + index] = value;
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(double Value)
        {
            for (int i = Starting; i < Starting + Count_items; i++)
                if (BaseList.Base[i] == Value) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Clear();
            Count_items = 0;
        }        
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_real(i, 0);
        }
        
        public override void Swap(int i, int j) // of FixAReal 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SFRA: Swapping items in a fixed real array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			double X = BaseList.Base[Starting + i];
			double Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}

		public FixAReal copy()
		{
			FixAReal result = new FixAReal(Count);
            for (int i = 0; i < Count; i++)
                result.set_real(i, get_real(i));
            return result;
		}
		
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAReal = new CacheOfArrays();
        
		public static FixAReal new_FixAReal(List<ArrayAny> List_temps, int N)
		{
			FixAReal result = null;
//?{Thread}
			if (cache_FixAReal == null)
				cache_FixAReal  = new CacheOfArrays();
//.
			if (cache_FixAReal.list.Count > 0)
			{
				result = (FixAReal)cache_FixAReal.list[cache_FixAReal.list.Count-1];
				cache_FixAReal.list.RemoveAt(cache_FixAReal.list.Count-1);
			}
			else
			{
				result = new FixAReal(N);
				result.Temps = cache_FixAReal;
			}
			result.BaseList = new DynAReal();
            result.BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                result.BaseList.Add(0);
            result.Starting = 0;
            result.Count_items = result.BaseList.Count;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	

		public static FixAReal new_FixAReal(List<ArrayAny> List_temps,
			double[] A)
		{
			FixAReal result = null;
//?{Thread}
			if (cache_FixAReal == null)
				cache_FixAReal  = new CacheOfArrays();
//.
			if (cache_FixAReal.list.Count > 0)
			{
				result = (FixAReal)cache_FixAReal.list[cache_FixAReal.list.Count-1];
				cache_FixAReal.list.RemoveAt(cache_FixAReal.list.Count-1);
			}
			else
			{
				result = new FixAReal(A);
				result.Temps = cache_FixAReal;
			}
			result.BaseList = new DynAReal();
        	result.BaseList.Set_capacity(A.Length);
        	for (int i = 0; i < A.Length; i++)
         	   result.BaseList.Add(A[i]);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
		
		public static FixAReal new_FixAReal(List<ArrayAny> List_temps,
			DynAReal base_list, int From_idx, int To_idx)
		{
			FixAReal result = null;
//?{Thread}
			if (cache_FixAReal == null)
				cache_FixAReal  = new CacheOfArrays();
//.
			if (cache_FixAReal.list.Count > 0)
			{
				result = (FixAReal)cache_FixAReal.list[cache_FixAReal.list.Count-1];
				cache_FixAReal.list.RemoveAt(cache_FixAReal.list.Count-1);
			}
			else
			{
				result = new FixAReal(base_list, From_idx, To_idx);
				result.Temps = cache_FixAReal;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	
		
		public static FixAReal new_FixAReal(List<ArrayAny> List_temps,
			FixAReal base_list, int From_idx, int To_idx)
		{
			FixAReal result = null;
//?{Thread}
			if (cache_FixAReal == null)
				cache_FixAReal  = new CacheOfArrays();
//.
			if (cache_FixAReal.list.Count > 0)
			{
				result = (FixAReal)cache_FixAReal.list[cache_FixAReal.list.Count-1];
				cache_FixAReal.list.RemoveAt(cache_FixAReal.list.Count-1);
			}
			else
			{
				result = new FixAReal(base_list, From_idx, To_idx);
				result.Temps = cache_FixAReal;
			}
			result.BaseList = base_list.BaseList;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Starting + base_list.Count)
				From_idx = base_list.Starting + base_list.Count;
			if (To_idx > base_list.Starting + base_list.Count)
				To_idx = base_list.Starting + base_list.Count;
			result.Starting = From_idx + base_list.Starting;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	

		public override ArrayAny Clone_array() {
			FixAReal result = new FixAReal(Count);
			for (int i = 0; i < Count; i++)
				result.set_real(i, get_real(i));
			return result;
		}
    }
    
	public class FixAReal_clamp : FixAReal
	{
		int mask_clamp;
		
		public override ArrayAny Clone_array() {
			FixAReal_clamp result = new FixAReal_clamp(Count);
			for (int i = 0; i < Count; i++)
				result.set_real(i, get_real(i));
			return result;
		}		
	
		public FixAReal_clamp(int N) : base(N)
        {
        	mask_clamp = 1;
        	while (N > 2)
        	{
        		mask_clamp = (mask_clamp << 1) | 1;
        		N = N >> 1;
        	}
        }
        
        public override double get_real(int index)
        {
        	return BaseList.Base[Starting + (index & mask_clamp)];
        }
        
        public override void set_real(int index, double value)
        {
            BaseList.Base[Starting + (index & mask_clamp)] = value;
        }

		public new FixAReal_clamp copy()
		{
			FixAReal_clamp result = new FixAReal_clamp(Count);
            for (int i = 0; i < Count; i++)
                result.set_real(i, get_real(i));
            return result;
		}
		
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAReal_clamp = new CacheOfArrays();
		
		public static FixAReal_clamp new_FixAReal_clamp(List<ArrayAny> List_temps,
			int N)
		{
			FixAReal_clamp result = null;
//?{Thread}
			if (cache_FixAReal_clamp == null)
				cache_FixAReal_clamp  = new CacheOfArrays();
//.
			if (cache_FixAReal_clamp.list.Count > 0)
			{
				result = (FixAReal_clamp)cache_FixAReal_clamp.list[
					cache_FixAReal_clamp.list.Count-1];
				cache_FixAReal_clamp.list.RemoveAt(
					cache_FixAReal_clamp.list.Count-1);
			}
			else
			{
				result = new FixAReal_clamp(N);
				result.Temps = cache_FixAReal_clamp;
			}
			result.BaseList = new DynAReal();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(0);
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	
		
        public override void Swap(int i, int j) // of FixAReal_clamp
		{
			i = i & mask_clamp;
			j = j & mask_clamp;
			
			double X = BaseList.Base[Starting + i];
			double Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}
	
	}	

    //--------------------------------------------------------------------------
    
    public class ArrayBool : ArrayAny
    {
        public bool this[int index]
        {
            get { return get_bool(index); }
            set { set_bool(index, value); }
        }
        
        public virtual bool get_bool(int index) { return false; }
        public virtual void set_bool(int index, bool value) { }
        public virtual void Add(bool X) { }
        public virtual void Insert(int index, bool X) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(bool value) { return -1; }
        public virtual void Remove(bool value) { }
        public virtual void Set_capacity(int new_cap) { }
        public virtual void Swap(int i, int j) { }
        
        public void Dispose()
        {
            Clear();
        }
        
        public bool Contains(bool value)
        { 
            return IndexOf(value) >= 0;
        }
        
		public virtual void Copy(int to_index, FixABool Source)
		{
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_bool(i, Source[j++]);
			}
		}
		
		public virtual void Copy(int to_index, ArrayBool Source,
			int from_start, int from_end)
		{
			int j = from_start;
			int last = to_index + (from_end - from_start);
			if (last >= Count) last = Count-1;
			for (int i = to_index; i <= last; i++)
			{
				set_bool(i, Source[j++]);
			}
		}
		
		public void Fill(int to_index, bool Value, int count_fill)
		{
			for (int i = to_index; i < to_index + count_fill; i++)
			{
				if (i >= Count) break;
				set_bool(i, Value);
			}
		}
		
		public void Repeat(int to_index, FixABool Source, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = 0; j < Source.Count; j++)
				{
					if (to_index >= Count) return;
					set_bool(to_index++, Source[j]);
				}
			}
		}

		public void Repeat(int to_index, ArrayBool Source,
			int from_start, int from_end,
			int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = from_start; j <= from_end; j++)
				{
					if (to_index >= Count) return;
					set_bool(to_index++, Source[j]);
				}
			}
		}

    }

    //--------------------------------------------------------------------------
    public class DynABool : ArrayBool
    {
    
        public List<bool> Base;
        
        public DynABool() { Base = new List<bool>(); }
    
        public override bool get_bool(int index)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BA: Getting item in a Boolean array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return false;
            }
            return Base[index];
        }
        
        public override void set_bool(int index, bool value)
        {
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BAW: Setting item in a Boolean array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + (value ? "TRUE" : "FALSE"));
            #endif
            	return;
            }
            Base[index] = value;
        }
        
        public override void Add(bool X) { Base.Add(X); }
        public override void Insert(int index, bool X)
        { 
        	if (index < 0) 
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IBA: Inserting item in a Boolean array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + (X ? "TRUE" : "FALSE"));
            #endif
        		return;
        	}
        	if (index > Base.Count) index = Base.Count;
            Base.Insert(index, X);
        }
        
        public override void Clear() 
        {
        	Base.Clear();
        }
        
        public override int Count
        { 
        	get { return Base.Count; }
        }
         
        public override int IndexOf(bool value) 
        {
        	return Base.IndexOf(value);
        }
        
        public override void Delete(int index)
        { 
            if ((uint)index >= (uint)Count) 
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"DBA: Deleting item in a Boolean array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            }
            Base.RemoveAt(index);
        }
        
        public override void Remove(bool value)
        {
        	Base.Remove(value);
        }
        
        public override void Set_capacity(int new_cap) { Base.Capacity = new_cap; }
        
		public override void Swap(int i, int j) // of DynABool
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SBA: Swapping item in a Boolean array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			bool X = Base[i];
			bool Y = Base[j];
			Base[i] = Y;
			Base[j] = X;
		}

		public static DynABool new_DynABool()
		{
			DynABool result = new DynABool();
			return result;
		}
        
		public override ArrayAny Create_empty_array() 
		{ 
			return new DynABool(); 
		}
		
		public override ArrayAny Clone_array() {
			DynABool result = new DynABool();
			result.Set_capacity(Count);
			for (int i = 0; i < Count; i++) {
				result.Add(get_bool(i));
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			if (Count < New_size) Base.Capacity = New_size;
			for (int i = Count; i < New_size; i++)
				Base.Add(false);
			for (int i = Count-1; i >= New_size; i--)
				Base.RemoveAt(i);
		}
		
    }

    //--------------------------------------------------------------------------
    public class FixABool : ArrayBool
    {
        public DynABool BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;

        public FixABool(int N)
        {
            BaseList = new DynABool();
            BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                BaseList.Add(false);
            Count_items = BaseList.Count;
        }

        public FixABool(bool[] A)
        {
            BaseList = new DynABool();
            BaseList.Set_capacity(A.Length);
            foreach (bool i in A)
                BaseList.Add(i);
            Count_items = BaseList.Count;
        }

        public FixABool(DynABool base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list;
            Starting = From_idx;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }

        public FixABool(FixABool base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list.BaseList;
            Starting = From_idx + base_list.Starting;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }
        
        public FixABool(ArrayBool base_list, int From_idx, int To_idx)
        {
        	if (base_list is FixABool)
        	{
	            Is_range = true;
	            BaseList = ((FixABool)base_list).BaseList;
	            Starting = From_idx + ((FixABool)base_list).Starting;
	            Count_items = To_idx + 1 - From_idx;
            }
            else
            {
	            Is_range = true;
	            BaseList = (DynABool)base_list;
	            Starting = From_idx;
	            Count_items = To_idx + 1 - From_idx;
            }
            if (Count_items < 0) Count_items = 0;
        }

        ~FixABool()
        {
            Dispose();
        }

        public override bool get_bool(int index)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BFA: Getting item in a Boolean fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return false;
            } 
            return BaseList.Base[Starting + index];
        }
        
        public override void set_bool(int index, bool value)
        {
            if ((uint)index >= Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BFAW: Setting item in a Boolean fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + (value ? "TRUE" : "FALSE"));
            #endif
            	return;
            } 
            BaseList.Base[Starting + index] = value;
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(bool Value)
        {
            for (int i = Starting; i < Starting + Count_items; i++)
                if (BaseList.Base[i] == Value) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Clear();
            Count_items = 0;
            Starting = 0;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_bool(i, false);
        }
        
        public override void Swap(int i, int j) // of FixABool 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SBFA: Swapping item in a Boolean fixed array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			bool X = BaseList.Base[Starting + i];
			bool Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}
		
		public FixABool copy()
		{
			FixABool result = new FixABool(Count);
            for (int i = 0; i < Count; i++)
                result.set_bool(i, get_bool(i));
            return result;
		}
		
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixABool = new CacheOfArrays();
		
		public static FixABool new_FixABool(List<ArrayAny> List_temps,
			int N)
		{
			FixABool result = null;
//?{Thread}
			if (cache_FixABool == null)
				cache_FixABool  = new CacheOfArrays();
//.
			if (cache_FixABool.list.Count > 0)
			{
				result = (FixABool)cache_FixABool.list[cache_FixABool.list.Count-1];
				cache_FixABool.list.RemoveAt(cache_FixABool.list.Count-1);
			}
			else
			{
				result = new FixABool(N);
				result.Temps = cache_FixABool;
			}
			result.BaseList = new DynABool();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(false);
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
        
		public static FixABool new_FixABool(List<ArrayAny> List_temps,
			bool[] A)
		{
			FixABool result = null;
//?{Thread}
			if (cache_FixABool == null)
				cache_FixABool  = new CacheOfArrays();
//.
			if (cache_FixABool.list.Count > 0)
			{
				result = (FixABool)cache_FixABool.list[cache_FixABool.list.Count-1];
				cache_FixABool.list.RemoveAt(cache_FixABool.list.Count-1);
			}
			else
			{
				result = new FixABool(A);
				result.Temps = cache_FixABool;
			}
			result.BaseList = new DynABool();
        	result.BaseList.Set_capacity(A.Length);
        	for (int i = 0; i < A.Length; i++)
         	   result.BaseList.Add(A[i]);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;	  
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
        
		public static FixABool new_FixABool(List<ArrayAny> List_temps,
			DynABool base_list, int From_idx, int To_idx)
		{
			FixABool result = null;
//?{Thread}
			if (cache_FixABool == null)
				cache_FixABool  = new CacheOfArrays();
//.
			if (cache_FixABool.list.Count > 0)
			{
				result = (FixABool)cache_FixABool.list[cache_FixABool.list.Count-1];
				cache_FixABool.list.RemoveAt(cache_FixABool.list.Count-1);
			}
			else
			{
				result = new FixABool(base_list, From_idx, To_idx);
				result.Temps = cache_FixABool;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
        
		public static FixABool new_FixABool(List<ArrayAny> List_temps,
			FixABool base_list, int From_idx, int To_idx)
		{
			FixABool result = null;
//?{Thread}
			if (cache_FixABool == null)
				cache_FixABool  = new CacheOfArrays();
//.
			if (cache_FixABool.list.Count > 0)
			{
				result = (FixABool)cache_FixABool.list[cache_FixABool.list.Count-1];
				cache_FixABool.list.RemoveAt(cache_FixABool.list.Count-1);
			}
			else
			{
				result = new FixABool(base_list, From_idx, To_idx);
				result.Temps = cache_FixABool;
			}
			result.BaseList = base_list.BaseList;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Starting + base_list.Count)
				From_idx = base_list.Starting + base_list.Count;
			if (To_idx > base_list.Starting + base_list.Count)
				To_idx = base_list.Starting + base_list.Count;
			result.Starting = From_idx + base_list.Starting;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

		public override ArrayAny Clone_array() {
			FixABool result = new FixABool(Count);
			for (int i = 0; i < Count; i++)
				result.set_bool(i, get_bool(i));
			return result;
		}
    }
    
	public class FixABool_clamp : FixABool
	{
		int mask_clamp;
	
		public override ArrayAny Clone_array() {
			FixABool_clamp result = new FixABool_clamp(Count);
			for (int i = 0; i < Count; i++)
				result.set_bool(i, get_bool(i));
			return result;
		}		
	
		public FixABool_clamp(int N) : base(N)
        {
        	mask_clamp = 1;
        	while (N > 2)
        	{
        		mask_clamp = (mask_clamp << 1) | 1;
        		N = N >> 1;
        	}
        }
        
        public override bool get_bool(int index)
        {
            return BaseList.Base[Starting + (index & mask_clamp)];
        }
        
        public override void set_bool(int index, bool value)
        {
            BaseList.Base[Starting + (index & mask_clamp)] = value;
        }

		public new FixABool_clamp copy()
		{
			FixABool_clamp result = new FixABool_clamp(Count);
            for (int i = 0; i < Count; i++)
                result.set_bool(i, get_bool(i));
            return result;
		}
		
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixABool_clamp = new CacheOfArrays();
		
        public override void Swap(int i, int j) // of FixABool_clamp
		{
			i &= mask_clamp;
			j &= mask_clamp;
			
			bool X = BaseList.Base[Starting + i];
			bool Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}
		
		public static FixABool_clamp new_FixABool_clamp(List<ArrayAny> List_temps,
			int N)
		{
			FixABool_clamp result = null;
//?{Thread}
			if (cache_FixABool_clamp == null)
				cache_FixABool_clamp  = new CacheOfArrays();
//.
			if (cache_FixABool_clamp.list.Count > 0)
			{
				result = (FixABool_clamp)cache_FixABool_clamp.list[
					cache_FixABool_clamp.list.Count-1];
				cache_FixABool_clamp.list.RemoveAt(
					cache_FixABool_clamp.list.Count-1);
			}
			else
			{
				result = new FixABool_clamp(N);
				result.Temps = cache_FixABool_clamp;
			}
			result.BaseList = new DynABool();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(false);
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}
        
	
	}	

    //--------------------------------------------------------------------------
    public class ArrayByte : ArrayAny
    {
        public byte this[int index]
        {
            get { return get_byte(index); }
            set { set_byte(index, value); }
        }
        
        public virtual byte get_byte(int index) { return 0; }
        public virtual void set_byte(int index, byte value) { }
        public virtual void Add(byte X) { }
        public virtual void Insert(int index, byte X) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(byte value) { return -1; }
        public virtual void Remove(byte value) { }
        public virtual void Set_capacity(int new_cap) { }
        public virtual void Swap(int i, int j) { }
        
        public void Dispose()
        {
            Clear();
        }
        
        public bool Contains(byte value)
        { 
            return IndexOf(value) >= 0;
        }
        
		public virtual byte[] ToBytesArray()
		{
			byte[] result = new byte[Count];
			for (int i = 0; i < Count; i++)
				result[i] = this[i]; 
			return result;
		}
        
		public virtual void Copy(int to_index, FixAByte Source)
		{
			if (Source.Count <= st_buf.Length)
			{
				Source.ToBytes(st_buf, 0, Source.Count);
				int jj = 0;
				for (int i = to_index; i < to_index + Source.Count; i++)
				{
					if (i >= Count) break;
					set_byte(i, st_buf[jj++]);
				}
				return;
			}
			byte[] buf = new byte[Source.Count];
			Source.ToBytes(buf, 0, Source.Count);
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_byte(i, buf[j++]);
			}
		}
		
		public virtual void Copy(int to_index, ArrayByte Source,
			int from_start, int from_end)
		{
			int last = to_index + from_end - from_start;
			if (last >= Count) last = Count-1;
			
			if (last-to_index+1 <= st_buf.Length)
			{
				Source.ToBytes(st_buf, from_start, last-to_index+1);
				int  jj = 0;
				for (int i = to_index; i <= last; i++)
					set_byte(i, st_buf[jj++]);
				return;
			}
			
			byte[] buf = new byte[last-to_index+1];
			Source.ToBytes(buf, from_start, buf.Length);
			int  j = 0;
			for (int i = to_index; i <= last; i++)
			{
				set_byte(i, buf[j++]);
			}
		}
		
		public static byte[] st_buf = new byte[4096];

		public virtual void ToBytes(byte[] dest, int from_idx, int count)
		{
			for (int i = 0; i < count; i++)
				dest[i] = this[from_idx++];
		}
		
		public virtual void Fill(int to_index, byte Value, int count_fill)
		{
			for (int i = to_index; i < to_index + count_fill; i++)
			{
				if (i >= Count) break;
				set_byte(i, Value);
			}
		}
		
		public void Repeat(int to_index, FixAByte Source, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = 0; j < Source.Count; j++)
				{
					if (to_index >= Count) return;
					set_byte(to_index++, Source[j]);
				}
			}
		}

		public void Repeat(int to_index, ArrayByte Source,
			int from_start, int from_end, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = from_start; j <= from_end; j++)
				{
					if (to_index >= Count) return;
					set_byte(to_index++, Source[j]);
				}
			}
		}

    }
    
    //--------------------------------------------------------------------------
    public class DynAByte : ArrayByte
    {
        public byte[] Values;
        int count_values;
        
		public int Capacity
		{
			get { return Values.Length; }
			set
			{
				if (value < Count) return;

				byte[] old_values = Values;
				Values = new byte[value];
				Array.Copy(old_values, 0, Values, 0, Count);

			}
		}
		
		public override int Count { get { return count_values; } } 
		
		public override void ToBytes(byte[] dest, int from_idx, int count)
		{
			if (from_idx >= 0 && from_idx+count <= Count)
			{
				Array.Copy(Values, from_idx, dest, 0, count);
			}
			else
			{
			for (int i = 0; i < count; i++)
				dest[i] = this[from_idx++];
			}
		}
		
		public override void Copy(int to_index, FixAByte Source)
		{
			if (Source.Count <= st_buf.Length)
			{
				Source.ToBytes(st_buf, 0, Source.Count);
				if (to_index >= 0 && to_index + Source.Count <= Count)
				{
					Array.Copy(st_buf, 0, Values, to_index, Source.Count);
					return;
				}
				int jj = 0;
				for (int i = to_index; i < to_index + Source.Count; i++)
				{
					if (i >= Count) break;
					set_byte(i, st_buf[jj++]);
				}
				return;
			}
			
			byte[] buf = new byte[Source.Count];
			Source.ToBytes(buf, 0, Source.Count);
			if (to_index >= 0 && to_index + Source.Count <= Count)
			{
				Array.Copy(buf, 0, Values, to_index, Source.Count);
				return;
			}
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_byte(i, buf[j++]);
			}
		}
		
		public override void Copy(int to_index, ArrayByte Source,
			int from_start, int from_end)
		{
			int last = to_index + from_end - from_start;
			if (last >= Count) last = Count-1;
			
			if (last-to_index+1 <= st_buf.Length)
			{
				Source.ToBytes(st_buf, from_start, last-to_index+1);
				if (to_index >= 0)
				{
					Array.Copy(st_buf, 0, Values, to_index, last-to_index+1);
					return; 
				}
				int jj = 0;
				for (int i = to_index; i <= last; i++)
					set_byte(i, st_buf[jj++]);
				return;
			}
			
			byte[] buf = new byte[last-to_index+1];
			Source.ToBytes(buf, from_start, last-to_index+1);
			if (to_index >= 0)
			{
				Array.Copy(buf, 0, Values, to_index, last-to_index+1);
				return; 
			}
			int  j = 0;
			for (int i = to_index; i <= last; i++)
			{
				set_byte(i, buf[j++]);
			}
		}	
		        
        public DynAByte()
        {
            Values = new byte[32];
        }
        
		public static DynAByte new_DynAByte()
		{
			DynAByte result = new DynAByte();
			return result;
		}
    
        public override byte get_byte(int index)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEA: Getting item in a bytes array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            } 
            return Values[index];
        }
        
        public override void set_byte(int index, byte value)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEAW: Setting item in a bytes array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            } 
            Values[index] = value;
        }

        public void Reallocate(int New_size)
        {
            if (Count >= New_size || New_size < 0) return;
            Capacity = New_size;
            while (Count < New_size)
                Add((byte)0);
        }
        
        public override void Add(byte Value)
        {
            if (Capacity <= Count)
            	Capacity = Count + Count/2 + 1;
            Values[count_values++] = Value;
        }
        
        public override void Clear()
        {
        	count_values = 0;
        }
        
        public override int IndexOf(byte Value)
        {
        	for (int i = 0; i < Count; i++)
        		if (Values[i] == Value) return i;
        	return -1;
        }
        
        public override void Insert(int At, byte Value)
        {
        	if (At < 0)
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"IBYTEA: Inserting item in a bytes array bounds violation, "
        		+ "i=" + At.ToString() + " Count=" + Count.ToString()
        		+ " value=" + Value.ToString());
            #endif
        		return;
        	} 
        	if (At > Count) At = Count;
        	if (Capacity <= Count)
        		Capacity = Capacity + Capacity / 2 + 1;
        	if (At < Count)
        		Array.Copy(Values, At, Values, At+1, Count-At);
        	Values[At] = Value;
        	count_values++;
        }
        
        public override void Delete(int index)
        {
        	if ((uint)index >= (uint)Count)
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"DBYTEA: Deleting item in a bytes array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
        		return;
        	} 
            Array.Copy(Values, index+1, Values, index, Count-index-1);
            count_values--;
        }
        
        public override void Remove(byte Value)
        {
            for (int i = Count-1; i >= 0; i--)
                if (this[i] == Value)
                {
                    Delete(i);
                }
        }
        
        public override void Swap(int i, int j) // of DynAByte 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SBYTEA: Swapping item in a bytes array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			byte X = this[i];
			byte Y = this[j];
			this[i] = Y;
			this[j] = X;
		}

        public override byte[] ToBytesArray()
        {
        	byte[] result = new byte[Count];
        	if (Count > 0)
        		Array.Copy(Values, 0, result, 0, Count);
        	return result; 
        }
        
		public override ArrayAny Create_empty_array() 
		{ 
			return new DynAByte(); 
		}
		
		public override ArrayAny Clone_array() {
			DynAByte result = new DynAByte();
			result.Set_capacity(Count);
			for (int i = 0; i < Count; i++) {
				result.Add(get_byte(i));
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			byte[] old = Values;
			Values = new byte[New_size];
			int last = Count-1;
			if (last > New_size-1) last = New_size-1;
			for (int i = 0; i <= last; i++) {
				Values[i] = old[i];
			}
			count_values = New_size;
		}
    }

    //--------------------------------------------------------------------------
    public class FixAByte_OnArray : DynAByte
    {
        public byte[] BaseArray;
        
		public override void ToBytes(byte[] dest, int from_idx, int count)
		{
			if (from_idx >= 0 && from_idx+count <= Count)
			{
				Array.Copy(BaseArray, from_idx, dest, 0, count);
			}
			else
			{
			for (int i = 0; i < count; i++)
				dest[i] = this[from_idx++];
			}
		}
		
		public override void Copy(int to_index, FixAByte Source)
		{
			if (Source.Count <= st_buf.Length)
			{
				Source.ToBytes(st_buf, 0, Source.Count);
				if (to_index >= 0 && to_index + Source.Count <= Count)
				{
					Array.Copy(st_buf, 0, BaseArray, to_index, Source.Count);
					return;
				}
				int jj = 0;
				for (int i = to_index; i < to_index + Source.Count; i++)
				{
					if (i >= Count) break;
					set_byte(i, st_buf[jj++]);
				}
				return;
			}
			
			byte[] buf = new byte[Source.Count];
			Source.ToBytes(buf, 0, Source.Count);
			if (to_index >= 0 && to_index + Source.Count <= Count)
			{
				Array.Copy(buf, 0, BaseArray, to_index, Source.Count);
				return;
			}
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_byte(i, buf[j++]);
			}
		}
		
		public override void Copy(int to_index, ArrayByte Source,
			int from_start, int from_end)
		{
			int last = to_index + from_end - from_start;
			if (last >= Count) last = Count-1;
					
	  		if (last-to_index+1 <= st_buf.Length)
	  		{
				Source.ToBytes(st_buf, from_start, last-to_index+1);
				if (to_index >= 0)
				{
					Array.Copy(st_buf, 0, BaseArray, to_index, last-to_index+1);
					return; 
				}
				int  jj = 0;
				for (int i = to_index; i <= last; i++)
				{
					set_byte(i, st_buf[jj++]);
				}
				return;
	  		}
	  		
			byte[] buf = new byte[last-to_index+1];
			Source.ToBytes(buf, from_start, last-to_index+1);
			if (to_index >= 0)
			{
				Array.Copy(buf, 0, BaseArray, to_index, last-to_index+1);
				return; 
			}
			int  j = 0;
			for (int i = to_index; i <= last; i++)
			{
				set_byte(i, buf[j++]);
			}
		}	
		        
        public FixAByte_OnArray(byte[] Array)
        {
            BaseArray = Array;
        }
        
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAByte_OnArray = new CacheOfArrays();
        
		public static FixAByte_OnArray new_FixAByte_OnArray(
			List<ArrayAny> List_temps, byte[] Array)
		{
			FixAByte_OnArray result = null;
//?{Thread}
			if (cache_FixAByte_OnArray == null)
				cache_FixAByte_OnArray = new CacheOfArrays();
//.
			if (cache_FixAByte_OnArray.list.Count > 0)
			{
				result = (FixAByte_OnArray)cache_FixAByte_OnArray.list[
					cache_FixAByte_OnArray.list.Count-1];
				cache_FixAByte_OnArray.list.RemoveAt(
					cache_FixAByte_OnArray.list.Count-1);
			}
			else
			{
				result = new FixAByte_OnArray(Array);
				result.Temps = cache_FixAByte_OnArray;
			}
			result.BaseArray = Array;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

        public override byte get_byte(int index)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEFAA: Getting item in a bytes fixed array on array "
        		+ "bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            } 
            return BaseArray[index];
        }
        
        public override void set_byte(int index, byte value)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEFAAW: Setting item in a bytes fixed array on array "
        		+ "bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            } 
            BaseArray[index] = value;
        }

        public override int Count
        {
            get { return BaseArray.Length; }
        }
        
        public override void Clear()
        {
            BaseArray = null;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_byte(i, 0);
        }
        
        public override void Swap(int i, int j) // of FixAByte_OnArray
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SBYTEFAA: Swapping item in a bytes fixed array on array "
        		+ "bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			byte X = BaseArray[i];
			byte Y = BaseArray[j];
			BaseArray[i] = Y;
			BaseArray[j] = X;
		}

        public override int IndexOf(byte Value) // for FixAByte_OnArray
        {
            for (int i = 0; i < BaseArray.Length; i++)
                if (BaseArray[i] == Value) return i;
            return -1;
        }
        
        public override byte[] ToBytesArray() { return BaseArray; }
        
		public FixAByte copy()
		{
			FixAByte result = new FixAByte(Count);
            for (int i = 0; i < Count; i++)
                result.set_byte(i, get_byte(i));
            return result;
		}
        
		public override ArrayAny Clone_array() {
			FixAByte_OnArray result = new FixAByte_OnArray(BaseArray);
			return result;
		}
    }

    //--------------------------------------------------------------------------
    public class FixAByte : ArrayByte
    {
        public ArrayByte BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;

        public FixAByte()
        {
        }
        
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAByte = new CacheOfArrays();
        
		public static FixAByte new_FixAByte()
		{
			FixAByte result = null;
//?{Thread}
			if (cache_FixAByte == null)
				cache_FixAByte = new CacheOfArrays();
//.
			if (cache_FixAByte.list.Count > 0)
			{
				result = (FixAByte)cache_FixAByte.list[cache_FixAByte.list.Count-1];
				cache_FixAByte.list.RemoveAt(cache_FixAByte.list.Count-1);
			}
			else
			{
				result = new FixAByte();
				result.Temps = cache_FixAByte;
			}
			result.BaseList = new DynAByte();
			result.Starting = 0;
        	result.Count_items = 0;			
			return result;
		}


        
		public override void ToBytes(byte[] dest, int from_idx, int count)
		{
			BaseList.ToBytes(dest, Starting + from_idx, count);
		}
		
		public override void Copy(int to_index, FixAByte Source)
		{
			BaseList.Copy(Starting + to_index, Source);
		}
		
		public override void Copy(int to_index, ArrayByte Source,
			int from_start, int from_end)
		{
			BaseList.Copy(Starting + to_index, Source, from_start, from_end);
		}	
		        
        public FixAByte(int N)
        {
            BaseList = new DynAByte();
            BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                BaseList.Add(0);
            Count_items = BaseList.Count;
        }

		public static FixAByte new_FixAByte(List<ArrayAny> List_temps, int N)
		{
			FixAByte result = null;
//?{Thread}
			if (cache_FixAByte == null)
				cache_FixAByte = new CacheOfArrays();
//.
			if (cache_FixAByte.list.Count > 0)
			{
				result = (FixAByte)cache_FixAByte.list[cache_FixAByte.list.Count-1];
				cache_FixAByte.list.RemoveAt(cache_FixAByte.list.Count-1);
			}
			else
			{
				result = new FixAByte(N);
				result.Temps = cache_FixAByte;
			}
			result.BaseList = new FixAByte();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(0);
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

        public FixAByte(byte[] Array)
        {
            BaseList = new FixAByte_OnArray(Array);
            Count_items = BaseList.Count;
        }
        
		public static FixAByte new_FixAByte(List<ArrayAny> List_temps,
			byte[] Array)
		{
			FixAByte result = null;
//?{Thread}
			if (cache_FixAByte == null)
				cache_FixAByte = new CacheOfArrays();
//.
			if (cache_FixAByte.list.Count > 0)
			{
				result = (FixAByte)cache_FixAByte.list[cache_FixAByte.list.Count-1];
				cache_FixAByte.list.RemoveAt(cache_FixAByte.list.Count-1);
			}
			else
			{
				result = new FixAByte(Array);
				result.Temps = cache_FixAByte;
			}
			result.BaseList = new FixAByte_OnArray(Array);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;		  
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

	

        public FixAByte(ArrayByte base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            if (base_list is FixAByte)
            {
                BaseList = ((FixAByte)base_list).BaseList;
            }
            else
            {
                BaseList = (DynAByte)base_list;
            }
            Starting = From_idx;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
            if (base_list is FixAByte)
                Starting += ((FixAByte)base_list).Starting;
        }
        
		public static FixAByte new_FixAByte(List<ArrayAny> List_temps,
			ArrayByte base_list, int From_idx, int To_idx)
		{
			FixAByte result = null;
//?{Thread}
			if (cache_FixAByte == null)
				cache_FixAByte = new CacheOfArrays();
//.
			if (cache_FixAByte.list.Count > 0)
			{
				result = (FixAByte)cache_FixAByte.list[cache_FixAByte.list.Count-1];
				cache_FixAByte.list.RemoveAt(cache_FixAByte.list.Count-1);
			}
			else
			{
				result = new FixAByte(base_list, From_idx, To_idx);
				result.Temps = cache_FixAByte;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

	

        ~FixAByte()
        {
            Dispose();
        }

        public override byte get_byte(int index)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEFA: Getting item in a bytes fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return 0;
            } 
            return(BaseList.get_byte(Starting + index));
        }
        
        public override void set_byte(int index, byte value)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"BYTEFAW: Setting item in a bytes fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString()
        		+ " value=" + value.ToString());
            #endif
            	return;
            } 
            BaseList.set_byte(Starting + index, value);
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(byte Value)
        {
            if (BaseList is FixAByte_OnArray)
            {
	            for (int i = Starting; i < Starting + Count_items; i++)
	                if (BaseList.get_byte(i) == Value) return i - Starting;
	            return -1;
            }

            for (int i = Starting; i < Starting + Count_items; i++)
                if (((DynAByte)BaseList).Values[i] == Value) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Clear();
            Count_items = 0;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_byte(i, 0);
        }
        
        public override void Swap(int i, int j) // of FixAByte 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SBYTEFA: Swapping item in a bytes fixed array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
            if (BaseList is FixAByte_OnArray)
            {
				byte X = BaseList.get_byte(Starting + i);
				byte Y = BaseList.get_byte(Starting + j);
				BaseList.set_byte(Starting + i, Y);
				BaseList.set_byte(Starting + j, X);
				return;
            }
			else
			{
				byte X = ((DynAByte)BaseList).Values[Starting + i];
				byte Y = ((DynAByte)BaseList).Values[Starting + j];
				((DynAByte)BaseList).Values[Starting + i] = Y;
				((DynAByte)BaseList).Values[Starting + j] = X;
			}
		}
		
        public override byte[] ToBytesArray() { return BaseList.ToBytesArray(); } 

		public FixAByte copy()
		{
			FixAByte result = new FixAByte(Count);
            for (int i = 0; i < Count; i++)
                result.set_byte(i, get_byte(i));
            return result;
		}
        
		public override void Fill(int to_index, byte Value, int count_fill)
		{
			if (to_index < 0)
			{
				count_fill += to_index;
				to_index = 0;
			}
			if (to_index + count_fill > Count)
				count_fill = Count - to_index;
			BaseList.Fill(to_index + Starting, Value, count_fill);
		}
        
		public override ArrayAny Clone_array() {
			FixAByte result = new FixAByte(Count);
			for (int i = 0; i < Count; i++)
				result.set_byte(i, get_byte(i));
			return result;
		}
	}
	
	public class FixAByte_clamp : FixAByte
	{
		int mask_clamp;
	
		public override ArrayAny Clone_array() {
			FixAByte_clamp result = new FixAByte_clamp(Count);
			for (int i = 0; i < Count; i++)
				result.set_byte(i, get_byte(i));
			return result;
		}		
	
		public FixAByte_clamp(int N) : base(N)
        {
        	mask_clamp = 1;
        	while (N > 2)
        	{
        		mask_clamp = (mask_clamp << 1) | 1;
        		N = N >> 1;
        	}
        }
        
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAByte_clamp = new CacheOfArrays();
        
		public static FixAByte_clamp new_FixAByte_clamp(List<ArrayAny> List_temps,
			int N)
		{
			FixAByte_clamp result = null;
//?{Thread}
			if (cache_FixAByte_clamp == null)
				cache_FixAByte_clamp  = new CacheOfArrays();
//.
			if (cache_FixAByte_clamp.list.Count > 0)
			{
				result = (FixAByte_clamp)cache_FixAByte_clamp.list[
					cache_FixAByte_clamp.list.Count-1];
				cache_FixAByte_clamp.list.RemoveAt(
					cache_FixAByte_clamp.list.Count-1);
			}
			else
			{
				result = new FixAByte_clamp(N);
				result.Temps = cache_FixAByte_clamp;
			}
			result.BaseList = new DynAByte();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add(0);
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

	
        
        public override byte get_byte(int index)
        {
            return ((DynAByte)BaseList).Values[Starting + (index & mask_clamp)];
        }
        
        public override void set_byte(int index, byte value)
        {
            ((DynAByte)BaseList).Values[Starting + (index & mask_clamp)] = value;
        }

		public new FixAByte_clamp copy()
		{
			FixAByte_clamp result = new FixAByte_clamp(Count);
            for (int i = 0; i < Count; i++)
                result.set_byte(i, get_byte(i));
            return result;
		}
        
	}	

    //--------------------------------------------------------------------------
    public class ArrayStr : ArrayAny
    {
        public string this[int index]
        {
            get { return get_str(index); }
            set { set_str(index, value); }
        }
        
        public virtual string get_str(int index) { return ""; }
        public virtual void set_str(int index, string value) { }
        public virtual void Add(string X) { }
        public virtual void Insert(int index, string X) { }
        public override void Clear() { }
        public override int Count { get { return 0; } } 
        public virtual int IndexOf(string value) { return -1; }
        public virtual void Remove(string value) { }
        public virtual void Set_capacity(int new_cap) { }
        public virtual void Swap(int i, int j) { }
        
        public void Dispose()
        {
            Clear();
        }
        
        public bool Contains(string value)
        { 
            return IndexOf(value) >= 0;
        }
        
		public virtual void Copy(int to_index, FixAStr Source)
		{
			int j = 0;
			for (int i = to_index; i < to_index + Source.Count; i++)
			{
				if (i >= Count) break;
				set_str(i, Source[j++]);
			}
		}
		
		public virtual void Copy(int to_index, ArrayStr Source,
			int from_start, int from_end)
		{
			int j = from_start;
			int last = to_index + from_end - from_start;
			if (last >= Count) last = Count-1;
			for (int i = to_index; i <= last; i++)
			{
				set_str(i, Source[j++]);
			}
		}
		
		public void Fill(int to_index, string Value, int count_fill)
		{
			for (int i = to_index; i < to_index + count_fill; i++)
			{
				if (i >= Count) break;
				set_str(i, Value);
			}
		}
		
		public void Repeat(int to_index, FixAStr Source, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = 0; j < Source.Count; j++)
				{
					if (to_index >= Count) return;
					set_str(to_index++, Source[j]);
				}
			}
		}

		public void Repeat(int to_index, ArrayStr Source,
			int from_start, int from_end, int count_repeat)
		{
			for (int i = 0; i < count_repeat; i++)
			{
				for (int j = from_start; j <= from_end; j++)
				{
					if (to_index >= Count) return;
					set_str(to_index++, Source[j]);
				}
			}
		}

    }
    
    //--------------------------------------------------------------------------
    public class DynAStr : ArrayStr
    {
        public List<string> Base; 
        
        public DynAStr() { Base = new List<string>(); }
        
		public static DynAStr new_DynAStr()
		{
			DynAStr result = new DynAStr();
			return result;
		}
        

        
        public override string get_str(int index)
        {
            if ((uint)index >= (uint)Count)
            {
            #if DIAGNOSTICS
            	#if DIAGNOSTICS_LIGHT
            		if (index==0 && Count==0) {}
            		else
            	#else
	        		AL4_system.diag_report(
	        		"SA: Getting item in a string array bounds violation, "
	        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
        		#endif
            #endif
            	return "";
            } 
            return Base[index];
        }
        public override void set_str(int index, string value)
        {
            if ((uint)index >= Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SAW: Setting item in a string array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString() 
        		+ " value: '" + (value.Length>20 ? value.Substring(0, 20) : value) 
        		+ (value.Length>20?"...":"") + "'");
            #endif
            	return;
            } 
            Base[index] = value;
        }
        
        public override void Add(string X) { Base.Add(X); }
        
        public override void Insert(int index, string X) 
        { 
        	if (index < 0)
        	{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"ISA: Inserting item in a string array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString() 
        		+ " value: '" + (X.Length>20 ? X.Substring(0, 20) : X) 
        		+ (X.Length>20?"...":"") + "'");
            #endif
        		return;
        	} 
        	if (index > Base.Count) index = Base.Count;
            Base.Insert(index, X);
        }
        
        public override void Clear()
        {
        		Base.Clear();
        }
        
        public override int Count
        { 
        	get { return Base.Count; }
        }
         
        public override int IndexOf(string value)
        {
        	return Base.IndexOf(value);
        }
        
        public override void Delete(int index)
        { 
            if (index < 0 || index >= Count)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"DSA: Deleting item in a string array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return;
            } 
            Base.RemoveAt(index);
        }
        public override void Remove(string value) 
        {
        	Base.Remove(value);
        }
        
        public override void Set_capacity(int new_cap) { Base.Capacity = new_cap; }
        
        public override void Swap(int i, int j) // of DynAStr
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
				return;
			{
				string X = Base[i];
				string Y = Base[j];
				Base[i] = Y;
				Base[j] = X;
			}
		}

		public override ArrayAny Create_empty_array() 
		{ 
			return new DynAStr(); 
		}
		
		public override ArrayAny Clone_array() {
			DynAStr result = new DynAStr();
			result.Set_capacity(Count);
			for (int i = 0; i < Count; i++) {
				result.Add(get_str(i));
			}
			return result;
		}
		
		public override void Allocate(int New_size) {
			if (New_size < 0) New_size = 0;
			if (Count < New_size) Base.Capacity = New_size;
			for (int i = Count; i < New_size; i++)
				Base.Add("");
			for (int i = Count-1; i >= New_size; i--)
				Base.RemoveAt(i);
		}
    }
    
    //--------------------------------------------------------------------------
    public class FixAStr : ArrayStr
    {
        public DynAStr BaseList;
        public int Starting;
        public int Count_items;
        public bool Is_range;

        public FixAStr(int N)
        {
            BaseList = new DynAStr();
            BaseList.Set_capacity(N);
            for (int i = 0; i < N; i++)
                BaseList.Add("");
            Count_items = BaseList.Count;
        }
        
//?{Thread}
		[ThreadStatic]
//.
		public static CacheOfArrays cache_FixAStr = new CacheOfArrays();
        
		public static FixAStr new_FixAStr(List<ArrayAny> List_temps, int N)
		{
			FixAStr result = null;
//?{Thread}
			if (cache_FixAStr == null)
				cache_FixAStr  = new CacheOfArrays();
//.
			if (cache_FixAStr.list.Count > 0)
			{
				result = (FixAStr)cache_FixAStr.list[
					cache_FixAStr.list.Count-1];
				cache_FixAStr.list.RemoveAt(
					cache_FixAStr.list.Count-1);
			}
			else
			{
				result = new FixAStr(N);
				result.Temps = cache_FixAStr;
			}
			result.BaseList = new DynAStr();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add("");
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}



        public FixAStr(string[] A)
        {
            BaseList = new DynAStr();
            BaseList.Set_capacity(A.Length);
            foreach (string i in A)
                BaseList.Add(i);
            Count_items = BaseList.Count;
        }

		public static FixAStr new_FixAStr(List<ArrayAny> List_temps, string[] A)
		{
			FixAStr result = null;
//?{Thread}
			if (cache_FixAStr == null)
				cache_FixAStr = new CacheOfArrays();
//.
			if (cache_FixAStr.list.Count > 0)
			{
				result = (FixAStr)cache_FixAStr.list[
					cache_FixAStr.list.Count-1];
				cache_FixAStr.list.RemoveAt(
					cache_FixAStr.list.Count-1);
			}
			else
			{
				result = new FixAStr(A);
				result.Temps = cache_FixAStr;
			}
			result.BaseList = new DynAStr();
        	result.BaseList.Set_capacity(A.Length);
        	for (int i = 0; i < A.Length; i++)
         	   result.BaseList.Add(A[i]);
        	result.Starting = 0;
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

        public FixAStr(ArrayStr base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            if (base_list is DynAStr)
            {
	            BaseList = (DynAStr)base_list;
	            Starting = From_idx;
            	Count_items = To_idx + 1 - From_idx;
            }
            else if (base_list is FixAStr)
            {
	            BaseList = ((FixAStr)base_list).BaseList;
	            Starting = From_idx + ((FixAStr)base_list).Starting;
            	Count_items = To_idx + 1 - From_idx;
            }
            if (Count_items < 0) Count_items = 0;
        }
        
		public static FixAStr new_FixAStr(List<ArrayAny> List_temps,
			DynAStr base_list, int From_idx, int To_idx)
		{
			FixAStr result = null;
//?{Thread}
			if (cache_FixAStr == null)
				cache_FixAStr  = new CacheOfArrays();
//.
			if (cache_FixAStr.list.Count > 0)
			{
				result = (FixAStr)cache_FixAStr.list[
					cache_FixAStr.list.Count-1];
				cache_FixAStr.list.RemoveAt(
					cache_FixAStr.list.Count-1);
			}
			else
			{
				result = new FixAStr(base_list, From_idx, To_idx);
				result.Temps = cache_FixAStr;
			}
			result.BaseList = base_list;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Count) From_idx = base_list.Count;
			if (To_idx >= base_list.Count) To_idx = base_list.Count-1;
			result.Starting = From_idx;
			result.Count_items = To_idx - From_idx + 1;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}

	

        public FixAStr(FixAStr base_list, int From_idx, int To_idx)
        {
            Is_range = true;
            BaseList = base_list.BaseList;
            Starting = From_idx + base_list.Starting;
            Count_items = To_idx + 1 - From_idx;
            if (Count_items < 0) Count_items = 0;
        }
        
		public static FixAStr new_FixAStr(List<ArrayAny> List_temps,
			FixAStr base_list, int From_idx, int To_idx)
		{
			FixAStr result = null;
//?{Thread}
			if (cache_FixAStr == null)
				cache_FixAStr  = new CacheOfArrays();
//.
			if (cache_FixAStr.list.Count > 0)
			{
				result = (FixAStr)cache_FixAStr.list[
					cache_FixAStr.list.Count-1];
				cache_FixAStr.list.RemoveAt(
					cache_FixAStr.list.Count-1);
			}
			else
			{
				result = new FixAStr(base_list, From_idx, To_idx);
				result.Temps = cache_FixAStr;
			}
			result.BaseList = base_list.BaseList;
			if (From_idx < 0) From_idx = 0;
			if (From_idx > base_list.Starting + base_list.Count)
				From_idx = base_list.Starting + base_list.Count;
			if (To_idx > base_list.Starting + base_list.Count)
				To_idx = base_list.Starting + base_list.Count;
			result.Starting = From_idx + base_list.Starting;
			result.Count_items = To_idx - From_idx + 1;
			if (result.Count_items < 0) result.Count_items = 0;
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	

        ~FixAStr()
        {
            Dispose();
        }

        public override string get_str(int index)
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SFA: Getting item in a strings fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString());
            #endif
            	return "";
            } 
            return BaseList.Base[Starting + index];
        }
        
        public override void set_str(int index, string value) 
        {
            if ((uint)index >= (uint)Count_items)
            {
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SFAW: Setting item in a strings fixed array bounds violation, "
        		+ "i=" + index.ToString() + " Count=" + Count.ToString() 
        		+ " value: '" + (value.Length>20 ? value.Substring(0, 20) : value) 
        		+ (value.Length>20?"...":"") + "'");
            #endif
            	return;
            } 
            BaseList.Base[Starting + index] = value;
        }

        public override int Count { get { return Count_items; } }

        public override int IndexOf(string Value)
        {
            for (int i = Starting; i < Starting + Count_items; i++)
                if (BaseList.Base[i] == Value) return i - Starting;
            return -1;
        }

        public override void Clear()
        {
            if (!Is_range)
                BaseList.Clear();
            Count_items = 0;
        }
        
        public void Nullify()
        {
        	for (int i = 0; i < Count; i++)
            	set_str(i, "");
        }
        
        public override void Swap(int i, int j) 
		{
			if ((uint)i >= (uint)Count || (uint)j >= (uint)Count)
			{
            #if DIAGNOSTICS
        		AL4_system.diag_report(
        		"SSA: Swapping item in a string array bounds violation, "
        		+ "i=" + i.ToString() + " j=" + j.ToString() 
        		+ " Count=" + Count.ToString());
            #endif
				return;
			}
			string X = BaseList.Base[Starting + i];
			string Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}
		
		public FixAStr copy()
		{
			FixAStr result = new FixAStr(Count);
            for (int i = 0; i < Count; i++)
                result.set_str(i, get_str(i));
            return result;
		}
        
		public override ArrayAny Clone_array() {
			FixAStr result = new FixAStr(Count);
			for(int i = 0; i < Count; i++)
				result.set_str(i, get_str(i));
			return result;
		}
	
    }
    
	public class FixAStr_clamp : FixAStr
	{
		int mask_clamp;
	
		public override ArrayAny Clone_array() {
			FixAStr_clamp result = new FixAStr_clamp(Count);
			for(int i = 0; i < Count; i++)
				result.set_str(i, get_str(i));
			return result;
		}		
	
		public FixAStr_clamp(int N) : base(N)
        {
        	mask_clamp = 1;
        	while (N > 2)
        	{
        		mask_clamp = (mask_clamp << 1) | 1;
        		N = N >> 1;
        	}
        }
        
//?{Thread}
		[ThreadStatic]
//.
        public static CacheOfArrays cache_FixAStr_clamp = new CacheOfArrays();
        
		public static FixAStr_clamp new_FixAStr_clamp(List<ArrayAny> List_temps,
			int N)
		{
			FixAStr_clamp result = null;
//?{Thread}
			if (cache_FixAStr_clamp == null)
				cache_FixAStr_clamp  = new CacheOfArrays();
//.
			if (cache_FixAStr_clamp.list.Count > 0)
			{
				result = (FixAStr_clamp)cache_FixAStr_clamp.list[
					cache_FixAStr_clamp.list.Count-1];
				cache_FixAStr_clamp.list.RemoveAt(
					cache_FixAStr_clamp.list.Count-1);
			}
			else
			{
				result = new FixAStr_clamp(N);
				result.Temps = cache_FixAStr_clamp;
			}
			result.BaseList = new DynAStr();
        	result.BaseList.Set_capacity(N);
        	for (int i = 0; i < N; i++)
         	   result.BaseList.Add("");
        	result.Count_items = result.BaseList.Count;			
			if (List_temps != null) List_temps.Add(result);
			return result;
		}	
        
        public override string get_str(int index)
        {
            return BaseList.Base[Starting + (index & mask_clamp)];
        }
        
        public override void set_str(int index, string value)
        {
            BaseList.Base[Starting + (index & mask_clamp)] = value;
        }

        public override void Swap(int i, int j) 
		{
			i &= mask_clamp;
			j &= mask_clamp;
			
			string X = BaseList.Base[Starting + i];
			string Y = BaseList.Base[Starting + j];
			BaseList.Base[Starting + i] = Y;
			BaseList.Base[Starting + j] = X;
		}
		
		public new FixAStr_clamp copy()
		{
			FixAStr_clamp result = new FixAStr_clamp(Count);
            for (int i = 0; i < Count; i++)
                result.set_str(i, get_str(i));
            return result;
		}
        
	}	

    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------

    public class AL4_Exception : Exception
    {
    }

    public class Stop : AL4_Exception
    {
        public string Stop_message;

        public Stop(string message)
        {
            Stop_message = message;
        }
    }

    public class TooDeepRecursionException : AL4_Exception
    {
    }
    
    public class AL4_log_methods
    {
		public static List<string> buf_out = new List<string>();
		public static int call_count;
		public static string LOG_METHODS_PATH;
		public static void log_method(string fun_name)
		{
			if (buf_out.Count >= 10000 || fun_name == "")
			{
				string path = LOG_METHODS_PATH + "log_methods.log"; 
				FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
				for (int i = 0; i < (int)buf_out.Count; i++)
				{
					byte[] text = Encoding.ASCII.GetBytes(buf_out[i]);
					fs.Write(text, 0, text.Length);
				}
				fs.Close();
				buf_out.Clear();
			}
			if (disabled_logging > 0 || fun_name == "") return;
			if (++call_count == 0)
		    { }
		      
			buf_out.Add(    
				AL4_system.Str(call_count) + ": " + fun_name + "\n");
		}
		
		public static int disabled_logging;
		public static void disable_log(int d)
		{
			disabled_logging += d;
		}
		
		public static void reset_logging()
		{
			call_count = 0;
		 	disabled_logging = 0;
			buf_out.Clear();
			string path = LOG_METHODS_PATH + "log_methods.log";
	        File.Delete(path);
		}

    }
    
}
--AL4.cs--)
--app.config--(
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=vFRAMEWORK-VERSION"/></startup>
</configuration>
--app.config--)
<ItemGroup>
    <None Include="app.config" />
</ItemGroup>
*/

