/*

CLASS {Var|iable}, UNTESTED :

IMPORT: {Type}, {Function}, {Parser}, {Text_parser}, {Compiler}, {Expression},
        {String_functions}, {Localize_str}, {Statement}, {For}, {Local} ;

*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AL4Compiler
{
    public class Variable
    {
        /*
        BOOL    Is_const|ant
        INT     Line|_where_defined, INIT
        STR     Names|_of_variable[]
        STR		Names_low|ered[]
        
        METHOD Provide_names_lowered :
			CASE Names_low[].Count > 0 ? ==> ;
			FOR n IN Names[] : Names_low[] << n.Lower ; .
			
		STR whole_name|_cached
		
		METHOD Whole_name ==> STR :
		    CASE whole_name != "" ? RESULT = whole_name ==> ;
		    whole_name = Whole_name_of(Names[])
		    RESULT = whole_name .

        {Type}  In_type_|located_
        {Fun}   In_fun_|ction_
        {Local}	In_local_|block_
        --------------------------- 'loop FOR variable'
        BOOL    Is_loop|_variable
        {For}	For_|statement_
        
        --------------------------- 'interpreter needs'
        INT		Local_offset
        INT		Field_index
        --------------------------- 'if has a setter'
        {Fun}   Setter_method_
        --------------------------- 'redirection (while TRANSLATION of class)'
        {Var}   Redirect_|to_field_
        --------------------------- 'optimizations'
        {Statement} First_st_|atement_used_in_
        INT		First_index|_of_first_statement
        INT 	Last_index|_of_last_statement
        BOOL	Cannot_union|_with_other_variables
        BOOL	Replaced|_do_not_generate_declaration_initialization
        {Var}	Replace_to_|variable_
        STR		Original_name|_before_replacing
        --------------------------- 'inline'
        {Var}	Corresponding_|inlined_variable_
        BOOL	Is_inline_param|eter
        --------------------------- 'temp'
        BOOL	Really_temp|orary_used_for_inlining
        --------------------------- 'debug'
        INT     Total_i|ndex
        BOOL    Declared_in_debug|_block_Do_not_use_it_out_of_debug_code
        --------------------------- 'trapping'
        {Fun}	Trap_read_|function_
        {Fun}	Trap_write_|function_
        {Fun}	Trap_add_|del_function_
        STR		Trap_fun|ction_names_max_3[]
        --------------------------- 'prevent some strange things'
        BOOL	Same_name_as_field|_of_class
        --------------------------- 'for variable created while LIKE is used'
        BOOL	From_LIKE
        ----------------- 'INT variable or array indexing arrays of type...'
        STR 	Type_indexing|_what
        {Type}  Indexing_|arrays_of_types_[]
        BOOL	Automatic_indexing|_in_FOR_statement

        CONSTRUCT : Total_i = comp.Total_var 
                    comp.Total_var = comp.Total_var + 1
        	CASE In_fun_ != NONE && In_fun_.Compiling_like ?
        	     From_LIKE = TRUE ; .
        */
        public bool Is_constant = false;
        public int Line = 0;
        public List<string> Names = new List<string>();
        public Type In_class_ = null;
        public Function In_fun_ = null;
        public bool Is_loop_var;

        //------------------------- 'debug'
        public int Total_index;

        public Variable(Compiler c)
        {
            Total_index = c.Total_var_index++;
            if (Total_index == 423 || Total_index == 572)
            { }
        }
        /*
        -------------------------------------------- 'references'
        
        METHOD Parse|r_of_source ==> {Parser} :
            CASE ?
            [In_type_.Kind == 'CLASS'] ?
                 RESULT = In_type_.Parse
            [In_type_.Kind == 'STRUCTURE'] ?
                 RESULT = In_type_.In_class_.Parse
            ELSE RESULT = In_fun_.Parse ; .

        METHOD comp|iler ==> {Compiler} : RESULT = Parse.Compiler_.{Compiler} .
        --------------------------------------------- 'attributes'
        
        METHOD Is_pub|lic ==> BOOL: 
            RESULT = Names[0].[0] == Names[0].Upper.[0]
            RESULT ||= Modifiers['PUBLIC_VAR'] .

        METHOD Is_weak|_reference ==> BOOL :
			RESULT = Names[0].[*] == "_" .

        */

        public Parser Parse()
        {
            if (In_class_ != null) return In_class_.Parse;
            else return In_fun_.Parse;
        }

        private Compiler comp() { return Parse().Compiler_; }

        public bool Is_public()
        {
            return Names.Count > 0 && Names[0].Length > 0 &&
                Names[0][0] == Names[0].ToUpper()[0];
        }

        public bool Is_weak()
        {
            string s = Names[0];
            if (s == "") return false;
            return s[s.Length - 1] == '_';
        }

        /*
        BOOL    Is_param|eter
        {Type}  Type_|of_variable_ //, TRAP(trap_type)
        
        //METHOD trap_type({Type} v|alue_to_set), TRAP :
        //    CASE Type_ != NONE && v == NONE ?
        //         << "nonification!" >> ; .
        
        
        
        STR     Type_n|ame   
        
        ENUMERATION {var_mod|ifiers}: 'READ|ONLY',
            'INIT|IALIZY',
            'TRAP|PING',
            'CLAMP|_ARRAY_INDEX',
            'DEBUG_VAR|IABLE_ONLY',
            'DEPRECATED_FIELD',
            'ABANDONED_FIELD',
            'PUBLIC_VAR|IABLE' .

                
        BOOL    Modifier|s[{var_mod}]
        STR     Deprecate|d_abandoned_use_what
        ------------------------------ 'arrays'
        BOOL    Is_array|_variable
        BOOL    Is_fixed|_array
        BOOL	Is_temp_fixed|_until_end_of_PUSH_statement
        STR     Size_n|ame_type
        {Type}  Size_type_|enum_
        INT     Size_value
        
        BOOL	Has_changing_size|_operations_Actual_for_parameters_only
        BOOL	Passed_as_dynamic|_array_parameter_while_calling_functions
        
		METHOD Provide_size_value ==> INT :
			CASE Size_value == 0 ?
				 Size_value = calculate_size_value(Size_n) ;
			RESULT = Size_value .
			
		METHOD calculate_size_value(
			STR S|tring_value ) ==> INT
			:
		    CASE S.[0] == "{" ?
		         {Type} fclass|_in_which_defined_as_afield
		         fclass = In_type_
		         CASE ?
		         [fclass.Kind == 'STRUCTURE'] ?
		              fclass = fclass.In_class_ ;
		         {Type} enum|eration = fclass.Find_type(S)
		         CASE enum == NONE ?
		              fclass.Parse.Err(
		              "Enumeration type was not found"._Eenum ": " S)
		         ;
		         CASE enum.Kind != 'ENUM' ?
		              fclass.Parse.Err(
		              "Type is not a enumeration"._Etype ": " S)
		         ;
		         RESULT = enum.Items[].Count ==> ;
		    RESULT = S.ToInt
		    CASE RESULT <= 0 ?
		         fclass = In_type_
		         CASE fclass.Kind == 'STRUCTURE' ?
		              fclass = fclass.In_class_ ;
		              
		         fclass.Parse.Err(
		         "Array size value must be greater then 0"._Earray)
		    ; .
		
	
	
        BOOL    Is_native_array|_used_as_field_of_record_in_Delphi
        ------------------------------ 'array parameter prevent bad using'
        BOOL    Used_to_add_to|_new_objects
        {Fun}   Passed_to_other_|functions_where_can_be_used_to_add_to_[]
        INT     Passed_as_param|eter_index_to_other_functions[]
        ------------------------------ 'initial value'
        STR     Constant_value|_expression
        {Expr}  Initial_|value_compiled_from_Value_
        ------------------------------ 'constant'
        //BOOL    Bool_c|onstant
        INT     Int_c|onstant
        REAL    Real_c|onstant
        STR     Str_c|onstant
        {Var}   Items_|of_const_array_[]
        ------------------------------ 'compiled'
        STR     Final_name
        METHOD Set_final_name(STR N|ew_final_name) : Final_name = N .
        
        BOOL    Used_for_r|ead_in_code
        BOOL    Used_for_w|rite_in_code
        INT		Count_ref|erenced
        BOOL    Assigned|_in_code
        //BOOL    Need_q|ualification_enum_item
        ------------------------------ 'function parameter'
        {Fun}   Function_param_|eter_GENERIC_
        ------------------------------ 'STOREd parameter'
        BOOL    Is_stored_param|eter
        */

        public bool Is_param;
        public Type Type_ = null;
        public string Type_n = "";
        public enum Var_mod { READ, INIT };
        public bool[] Modifiers = new bool[(int)Var_mod.INIT + 1];
        //-------------------- 'arrays'
        public bool Is_array;
        public bool Is_fixed;
        public string Size_n = "";
        public Type Size_type_ = null;
        //-------------------- 'initial value'
        public string Value = "";
        public Expression Initial_ = null;
        //-------------------- 'constant'
        public bool Bool_c;
        public int Int_c;
        public double Real_c;
        public string Str_c = "";
        public List<Variable> Items_ = new List<Variable>();
        //-------------------- 'compiled'
        public string Final_name = "";
        public bool Used;
        public bool Need_q;


        public void Init_constants()
        {
            comp().TRUE_c = new Variable(comp());
            comp().TRUE_c.Is_constant = true;
            comp().TRUE_c.Type_ = comp().TYPE_BOOL;
            comp().TRUE_c.Value = "true";
            comp().TRUE_c.Bool_c = true;

            comp().FALSE_c = new Variable(comp());
            comp().FALSE_c.Is_constant = true;
            comp().FALSE_c.Type_ = comp().TYPE_BOOL;
            comp().FALSE_c.Value = "false";

            comp().NONE_c = new Variable(comp());
            comp().NONE_c.Is_constant = true;
            comp().NONE_c.Type_ = comp().TYPE_OBJ;
            comp().NONE_c.Value = "NONE";

            comp().N0_c = new Variable(comp());
            comp().N0_c.Is_constant = true;
            comp().N0_c.Type_ = comp().TYPE_INT;
            comp().N0_c.Value = "0";

            comp().N1_c = new Variable(comp());
            comp().N1_c.Is_constant = true;
            comp().N1_c.Type_ = comp().TYPE_INT;
            comp().N1_c.Value = "1";
            comp().N1_c.Int_c = 1;

            comp().EMPTY_str = new Variable(comp());
            comp().EMPTY_str.Is_constant = true;
            comp().EMPTY_str.Type_ = comp().TYPE_STR;
            comp().EMPTY_str.Value = "\"\"";

            comp().TEST_c = new Variable(comp());
            comp().TEST_c.Is_constant = true;
            comp().TEST_c.Type_ = comp().TYPE_BOOL;
            comp().TEST_c.Value = "false";

            comp().INF_c = new Variable(comp());
            comp().INF_c.Is_constant = true;
            comp().INF_c.Type_ = comp().TYPE_REAL;
            comp().TEST_c.Value = "Infinity";
            comp().TEST_c.Real_c = double.PositiveInfinity;

            comp().THIS_var = new Variable(comp());
            comp().THIS_var.Type_ = comp().TYPE_OBJ;
            comp().THIS_var.Names.Add("THIS");
            comp().THIS_var.Value = "this";
            comp().THIS_var.Final_name = "this";

            comp().THIS_expr = new Expression();
            comp().THIS_expr.Operation = Expression.Operation_kind.VAR;
            comp().THIS_expr.Var_arg = comp().THIS_var;

            comp().NAN_c = new Variable(comp());
            comp().NAN_c.Is_constant = true;
            comp().NAN_c.Type_ = comp().TYPE_REAL;
            comp().NAN_c.Real_c = Double.NaN;
            comp().NAN_c.Final_name = "Double.NAN";

            Parser Parse = new Parser();
            Parse.Compiler_ = comp();

            comp().SYSFUN_Index = new Function(Parse);
            comp().SYSFUN_Index.Is_system = true;
            comp().SYSFUN_Index.Names.Add("Index");
            comp().SYSFUN_Index.Result = new Variable(comp());
            comp().SYSFUN_Index.Result.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Index.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Index.Final_name = "Index";

            Variable P = new Variable(comp());
            P.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Index.Param.Add(P);

            comp().SYSFUN_Len = new Function(Parse);
            comp().SYSFUN_Len.Is_system = true;
            comp().SYSFUN_Len.Names.Add("Len");
            comp().SYSFUN_Len.Names.Add("Length");
            comp().SYSFUN_Len.Result = new Variable(comp());
            comp().SYSFUN_Len.Result.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Len.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Len.Final_name = "Length";

            P = new Variable(comp());
            P.Type_ = comp().TYPE_STR;
            comp().SYSFUN_Len.Param.Add(P);

            comp().SYSFUN_Count = new Function(Parse);
            comp().SYSFUN_Count.Is_system = true;
            comp().SYSFUN_Count.Names.Add("Count");
            comp().SYSFUN_Count.Result = new Variable(comp());
            comp().SYSFUN_Count.Result.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Count.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Count.Final_name = "Count";

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Count.Param.Add(P);

            comp().SYSFUN_Name = new Function(Parse);
            comp().SYSFUN_Name.Is_system = true;
            comp().SYSFUN_Name.Names.Add("Name");
            comp().SYSFUN_Name.Result = new Variable(comp());
            comp().SYSFUN_Name.Result.Type_ = comp().TYPE_STR;
            comp().SYSFUN_Name.Modifiers[(int)Function.Fun_mod.STATIC] = true;

            P = new Variable(comp());
            P.Type_ = comp().TYPE_ENUM;
            comp().SYSFUN_Name.Param.Add(P);

            comp().SYSFUN_Find_str = new Function(Parse);
            comp().SYSFUN_Find_str.Is_system = true;
            comp().SYSFUN_Find_str.Names.Add("Find");
            comp().SYSFUN_Find_str.Names.Add("Find_str");
            comp().SYSFUN_Find_str.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            comp().SYSFUN_Find_str.Final_name = "Find_str";

            comp().SYSFUN_Find_str.Result = new Variable(comp());
            comp().SYSFUN_Find_str.Result.Type_ = comp().TYPE_INT;

            P = new Variable(comp());
            P.Type_ = comp().TYPE_STR;
            comp().SYSFUN_Find_str.Param.Add(P);

            P = new Variable(comp());
            P.Type_ = comp().TYPE_STR;
            comp().SYSFUN_Find_str.Param.Add(P);

            //--------------------------------------- 'array system functions'
            comp().SYSFUN_Insert = new Function(Parse);
            comp().SYSFUN_Insert.Is_system = true;
            comp().SYSFUN_Insert.Names.Add("Insert");
            comp().SYSFUN_Insert.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Insert.Final_name = "Insert";

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Insert.Param.Add(P);
            P = new Variable(comp());
            P.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Insert.Param.Add(P);

            comp().SYSFUN_Delete = new Function(Parse);
            comp().SYSFUN_Delete.Is_system = true;
            comp().SYSFUN_Delete.Names.Add("Delete");
            comp().SYSFUN_Delete.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Delete.Final_name = "RemoveAt";

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Delete.Param.Add(P);
            P = new Variable(comp());
            P.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Delete.Param.Add(P);

            comp().SYSFUN_Remove = new Function(Parse);
            comp().SYSFUN_Remove.Is_system = true;
            comp().SYSFUN_Remove.Names.Add("Remove");
            comp().SYSFUN_Remove.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Remove.Final_name = "Remove";

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Remove.Param.Add(P);
            P = new Variable(comp());
            comp().SYSFUN_Remove.Param.Add(P);

            comp().SYSFUN_Clear = new Function(Parse);
            comp().SYSFUN_Clear.Is_system = true;
            comp().SYSFUN_Clear.Names.Add("Clear");
            comp().SYSFUN_Clear.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Clear.Final_name = "Clear";

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Clear.Param.Add(P);

            comp().SYSFUN_Find_item = new Function(Parse);
            comp().SYSFUN_Find_item.Is_system = true;
            comp().SYSFUN_Find_item.Names.Add("Find");
            comp().SYSFUN_Find_item.Names.Add("Find_item");
            comp().SYSFUN_Find_item.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            //comp().SYSFUN_Find_item.Final_name = "Find_item";
            
            comp().SYSFUN_Find_item.Result = new Variable(comp());
            comp().SYSFUN_Find_item.Result.Type_ = comp().TYPE_INT;

            P = new Variable(comp());
            P.Is_array = true;
            comp().SYSFUN_Find_item.Param.Add(P);

            P = new Variable(comp());
            comp().SYSFUN_Find_item.Param.Add(P);

            //------------------------------------------- 'conversions'
            comp().SYSFUN_Str = new Function(Parse);
            comp().SYSFUN_Str.Is_system = true;
            comp().SYSFUN_Str.Names.Add("Str");
            comp().SYSFUN_Str.Result = new Variable(comp());
            comp().SYSFUN_Str.Result.Type_ = comp().TYPE_STR;
            comp().SYSFUN_Str.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            comp().SYSFUN_Str.Final_name = "Str";

            P = new Variable(comp());
            P.Type_ = comp().TYPE_INT;
            comp().SYSFUN_Str.Param.Add(P);

            comp().SYSFUN_RealStr = new Function(Parse);
            comp().SYSFUN_RealStr.Is_system = true;
            comp().SYSFUN_RealStr.Names.Add("Str");
            comp().SYSFUN_RealStr.Result = new Variable(comp());
            comp().SYSFUN_RealStr.Result.Type_ = comp().TYPE_STR;
            comp().SYSFUN_RealStr.Modifiers[(int)Function.Fun_mod.STATIC] = true;
            comp().SYSFUN_RealStr.Final_name = "Str";

            P = new Variable(comp());
            P.Type_ = comp().TYPE_REAL;
            comp().SYSFUN_RealStr.Param.Add(P);

        }

        /*
        
        METHOD Handle_modifier|_of_variable :
            STR m|odifier = Parse.Ident.Upper
            CASE m ?
            ["INIT", "INITIALIZY"]: {var_mod} vm|odifier = 'INIT'
            ["READ", "READONLY"]:    vm = {var_mod}.'READ'
            ["TRAP"]:				 vm = 'TRAP'
            ["CLAMP"]:				 vm = 'CLAMP'
            ["DEPRECATED"]:          vm = 'DEPRECATED_FIELD'
            ["ABANDONED"]:           vm = 'ABANDONED_FIELD'
            ["DEBUG"]:				 vm = 'DEBUG_VAR'
            ["PUBLIC"]:				 vm = 'PUBLIC_VAR'
            ELSE comp.Error("Unknown variable modifier: " m) ==>
            ;
            Modifiers[vm] = TRUE
            CASE vm IN ['TRAP', 'DEPRECATED_FIELD', 'ABANDONED_FIELD'] ?
                 CASE In_type_ == NONE ?
                     Parse.Err(m 
                     " " ("is applicable only to fields"._Eisapplic )) ;
            ;
            CASE vm ?
            ['INIT', 'READ']: NONE
            ['TRAP']:
				---------------------------- 'variable is trapping'
				Parse.Wait("(")
				STR id|entifier_function = Parse.Ident 
				Trap_fun[] << id
				CASE Parse.Symbol(",") ?
				     id = Parse.Ident 
				     Trap_fun[] << id ;
				Parse.Wait(")")
				
            ['CLAMP']:
				---------------------------- 'array is clamping'
				CASE !Is_fixed ?
				     Parse.Err("Only fixed array can be clamping"._EonlyFixed)
				;
				
            ['DEPRECATED_FIELD', 'ABANDONED_FIELD']:
                ---------------------------- '(deprecation text)'
                Parse.Wait("(")
                Parse.Wait("'")
                INT from|_pos = Parse.Pos
                NONE = Parse.Skip_to("'")
                Deprecate = Parse.Source[Parse.Line].[from TO Parse.Pos-1]
                Parse.Wait("'")
                Parse.Wait(")")
                ---------------------------- 'both abandoned + deprecated ?'
                CASE Modifiers['ABANDONED_FIELD'] && Modifiers[
                     'DEPRECATED_FIELD']
                     ?
                     Parse.Err("Field can be either abandoned or deprecated, "
                     "not both"._Efield )
                ;
            ['DEBUG_VAR', 'PUBLIC_VAR']: NONE
            ; .
        */
        public void Handle_modifier()
        {
            string m = Parse().Ident().ToUpper();
            bool sw_ok = false;
            if (m != "")
                switch (m[0])
                {
                    case 'I':
                        if (m == "INIT" || m == "INITIALIZY")
                        {
                            sw_ok = true;
                            Modifiers[(int)Var_mod.INIT] = true;
                        }
                        break;
                    case 'R':
                        if (m == "READ" || m == "READONLY")
                        {
                            sw_ok = true;
                            Modifiers[(int)Var_mod.READ] = true;
                        }
                        break;
                }
            if (!sw_ok)
                Parse().Compiler_.Error("Unknown variable modifier: " + m);
        }

        /*
        
 		METHOD Provide_traps :
 			CASE Trap_fun[].Count == 0 ? ==> ;
 			CASE Trap_read_ != NONE || Trap_write_ != NONE || Trap_add_ != NONE
 				 ?
 			     ==> ;
 		PUSH comp.Current_class = In_type_ :
 		PUSH Parse.Line = Line :
 			{Type} cc|lass_current = In_type_
 			CASE cc.Kind == 'STRUCTURE' ? cc = cc.In_class_ ;
 			FOR fn IN Trap_fun[]:
 			    PUSH comp.Current_fun = NONE :
 					 {Fun} f|unction_to_use_as_trap = cc.Find_fun(fn, FALSE)
 					 CASE !f.Modifiers['TRAP_FUN'] ?
 					      Parse.Err("Method specified in TRAP modifier for a "
 					      "variable must have the modifier TRAP too"._ETrapMod)
 					 ;
 			    ;
 				PUSH comp.Current_class = cc:
 				PUSH Parse.Line = Line :
	 				 CASE f.Class != cc ?
	 				      Parse.Err("Trap method should be in the same class as "
	 				      "a trapped field"._ETrapMethod)
	 				 ;
	 				 CASE f.Modifiers['STATIC'] ?
	 				      Parse.Err("Trap function should be the method rather "
	 				      "then the static function"._ETrapShouldBeMethod)
	 				 ;
	 				 {Fun} read_trap = NONE
	 				 {Fun} write_trap = NONE
	 				 {Fun} add_del_trap = NONE
	 				 CASE ?
	 				 [Is_array && f.Param[].Count == 1 && (
	 				 f.Param[0].Type_.Kind == 'INT')] ?
	 				 	  read_trap = f
	 				 [Is_array && f.Param[].Count == 2 && (
	 				 f.Param[0].Type_.Kind == 'INT') && (
	 				 f.Param[1].Type_ == Type_)] ?
	 				      write_trap = f
	 				 [!Is_array && f.Param[].Count == 0] ?
	 				      read_trap = f
	 				 [!Is_array && f.Param[].Count == 1 && (
	 				 f.Param[0].Type_ == Type_)] ?
	 				      write_trap = f
	 				 [Is_array && f.Param[].Count == 2 && (
	 				 f.Param[0].Type_.Kind == 'BOOL') && (
	 				 f.Param[1].Type_.Kind == 'INT')] ?
	 				      add_del_trap = f
	 				 ;
	 				 CASE read_trap == NONE && write_trap == NONE && (
	 				 	  add_del_trap == NONE)
	 				 	  ?
	 				      CASE Is_array ?
					 	       Parse.Err("Trap function for an array must have "
					 	       "either a single INT parameter or two parameters"
					 	       " the first INT and the second the same type as "
					 	       "the field or the first BOOL and the second "
					 	       "INT"._ETrapArrayParam)
	 				      ELSE Parse.Err("Trap function for a scalar must have "
	 				      	   "either no parameters or a single parameter of "
	 				      	   "the same type as the field"._ETrapParam)
	 				      ;
	 				 ;
	 				 CASE ?
	 				 [read_trap != NONE] ?
	 				      CASE Trap_read_ != NONE ?
		 				       Parse.Err("Read trap method is set more "
		 				       "then once for a field"._EReadTrap " " Names[0])
	 				      ;
	 				      Trap_read_ = read_trap
	 				      CASE comp.Debugging ?
	 				           Trap_read_.Usage_count += 1 ;
	 				      {Fun} trap_any = read_trap
	 				 [write_trap != NONE] ?
	 				      CASE Trap_write_ != NONE ?
	 				           Parse.Err("Write trap method is set more "
	 				           "then once for a field"._EWriteTrap " " Names[0])
	 				      ;
	 				      Trap_write_ = write_trap
	 				      CASE comp.Debugging ?
	 				           Trap_write_.Usage_count += 1 ;
	 				      trap_any = write_trap
	 				 [add_del_trap != NONE] ?
	 				      CASE Trap_add_ != NONE ?
	 				           Parse.Err("Add/delete trap method is set more "
	 				           "then once for a field"._EAddDelTrap 
	 				           " " Names[0])
	 				      ;
	 				      Trap_add_ = add_del_trap
	 				      CASE comp.Debugging ?
	 				           Trap_add_.Usage_count += 1 ;
	 				      trap_any = add_del_trap
	 				 ;
 				     CASE trap_any.Trap_field != THIS && (
 				      	  trap_any.Trap_field != NONE)
 				      	  ?
 				          Parse.Err("Trap function can be used "
 				          "to trap only a single field"._ETrapSingle)
 				     ;
 				     trap_any.Trap_field = THIS
 				;
 				;
 			;
 		;
 		; .
	
	
        TEST Variables :
             ------------------------------- 'hello'
             << "TEST Variables -- begin ----------------------------------" #NL
             << "QUE".[1]
             //CASE "QUE"[1] != "U" ? << "single symbol failed" >> ;
             //<< "U".Upper "U".Lower #NL >>
             ASSERT TRUE
             ------------------------------- 'prepare compiler'
             c|ompiler_temp = {Compiler}
             class|_temp = {Type}(Kind = 'CLASS'), >> c.All_classes[]
             
             class.Parse = {Parser}(Class_ = class, Compiler_ = c,
             	Warning_80=FALSE)
             
             fun|ction_temp = {Fun}(Parse = class.Parse, A_Name_1 = ""),
             	>> class.Method[]
             	
             v|ariable_temp = {Var}(Line = 1, In_fun_ = fun, Is_array = TRUE,
                 In_type_ = class)
                 
             ASSERT v.Is_array
             ------------------------------ 'Init_constants'
             << "Init_constants" #NL
             c.Init_const(class.Parse)
             ASSERT v.Parse != NONE
             ------------------------------- 'field of class'
             << "create field" #NL
             
             f|ield_temp = {Var}(Line = 2, In_type_ = class,
                Names[] << "Temp")
                
             ASSERT f.Parse != NONE
             ASSERT f.Is_public && !f.Is_weak
             -------------------------------- 'handle modifier'
             << "handle modifier" #NL
             
             class.Parse.Test_line("READ INIT ABANDONED('Other') "
                "DEPRECATED('another') ERROR")
                
             << "rest of line>" class.Parse.Rest_of_line "<" #NL
             PUSH class.Parse.Pos :
                  << "ident: " class.Parse.Ident #NL ;
             << "rest of line>" class.Parse.Rest_of_line "<" #NL
             STR bad|_errors_count
             FOR x IN [class.Parse.Pos TO class.Parse.Last] :
                 CASE class.Parse.End_of_line ? BREAK x ;
                 v.Handle_modifier
                 //<< "x=" x.Str ", Errors:" c.Errors_count.Str
                 CASE x ?
                 [0]: 
                      CASE c.Errors_count != 0 ? bad = bad x.Str "," ;
                 [1]: 
                      CASE c.Errors_count != 0 ? bad = bad x.Str "," ;
                 [2]: 
                      CASE c.Errors_count != 0 ? bad = bad x.Str "," ;
                 [3]: 
                      CASE c.Errors_count != 1 ? bad = bad x.Str "," ; 
                 [4]: 
                      CASE c.Errors_count != 1 ? bad = bad x.Str "," ;
                 ;
                 c.Errors_count = 0 ;
             ASSERT bad == "", "Errors_count incorrect, case: " bad
             //>> STR input_wait
             -------------------------------- 'modifier SHORT_STR'
             class.Parse.Test_line("MAXLEN[1] DEPRECATED('aaa')")
             v.Is_array = FALSE
             v.In_type_ = NONE
             PUSH v.In_type_ = class :
             PUSH v.Type_ = c.TYPE_STR :
                 v.Handle_modifier
                 //STR inp|up_dummy
                 //<< "errors: " c.Errors_count.Str >> inp
                 ASSERT c.Errors_count IN [1, 2], c.Errors_count.Str
                 -------------------------- 'to test message "only for fields"'
                 v.In_type_ = NONE
                 v.Handle_modifier ;
             ;
             ---------------------------------- 'Integer'
             << "Testing integer"
             class.Parse.Test_line("0 -1 2")
             << "Rest of line>" class.Parse.Rest_of_line #NL
             INT tint|eger_test = class.Parse.Integer
             << "Integer: " tint.Str ", >" class.Parse.Rest_of_line #NL
             ASSERT tint == 0
             ASSERT class.Parse.Integer == -1
             ---------------------------------- 'end'
             << "TEST Variables -- end ------------------------------------" #NL
             ASSERT TRUE
        .
		
		
        */

    }
}
/*
END
*/

