Пример #1
0
		private string GetGenericFlag(common_function_node cfn)
		{
			if (!cfn.is_generic_function) return "";
			return "``"+cfn.get_generic_params_list().Count.ToString();
		}
        //\ssyy

        //(ssyy) "Я" бывают разные :)

		//Я хочу модифицировать этот метод так, чтобы в случае предописания наличия метода
		//он не выкидывал исключение, а понимал все правильно
		//Этот метод вызывается только для функций с телом

        /// <summary>
        /// Ищет предописание функции, производя необходимые проверки. Возвращает true-уникальная, false-предописанная
        /// </summary>
        /// <param name="fn">Проверяемая функция</param>
        /// <returns></returns>
		private bool check_unique_or_predefined(common_function_node fn)
		{
			SymbolInfo si=null;
			bool in_unit = false;
			if (_func_stack.size<=1)
			{
                if (_explicit_interface_type != null)
                {
                    si = _explicit_interface_type.find_in_type(fn.name);
                }
				else if (_ctn!=null)
				{
					si=_ctn.Scope.FindOnlyInScope(fn.name);
                    if (_ctn is compiled_generic_instance_type_node && fn is common_namespace_function_node)
                    { 
                        si = (_ctn as compiled_generic_instance_type_node).compiled_original_generic.find_in_type(fn.name);
                        SymbolInfo si_tmp = si;
                        while (si_tmp != null)
                        {
                            if (si_tmp.sym_info.general_node_type != general_node_type.function_node)
                            {
                                TreeRealization.BasePCUReader.RestoreSymbols(si_tmp, fn.name);
                            }
                            common_namespace_function_node cnfn = si_tmp.sym_info as common_namespace_function_node;
                            if (cnfn != null)
                            {
                                if (cnfn.namespace_node == (fn as common_namespace_function_node).namespace_node)
                                {
                                    break;
                                }
                            }
                            si_tmp = si_tmp.Next;
                        }
                        si = si_tmp;
                    }
                }
                else if (_compiled_tn != null)
                {
                    si = _compiled_tn.find_in_type(fn.name);
                }
                else
                {
                    in_unit = true;
                    si = _cmn.scope.FindOnlyInScope(fn.name);
                }
			}
			else
			{
				common_function_node temp=_func_stack.pop();
                si = _func_stack.top().scope.FindOnlyInScope(fn.name);
				_func_stack.push(temp);
			}
            bool predef_find = false;
            SymbolInfo tmp_si = si;
            int overloads = 0;
            while(tmp_si!=null)
			{
            	if (tmp_si.sym_info != fn && !(si.sym_info is basic_function_node))
				{
					overloads++;
				}
            	tmp_si = tmp_si.Next;
            }
			while(si!=null)
			{
				if (si.sym_info==fn)
				{
					si=si.Next;
					continue;
				}
                if (si.sym_info.general_node_type != general_node_type.function_node)
                {
                    TreeRealization.BasePCUReader.RestoreSymbols(si, fn.name);
                }
#if (DEBUG)
				if (si.sym_info.general_node_type!=general_node_type.function_node)
				{
                    throw new CompilerInternalError("Function name is used to define not function.");
				}
#endif
                if (si.sym_info is basic_function_node || si.sym_info is compiled_function_node)
                {
                    si = si.Next;
                    continue;
                }
				//compar - найденная функция
				common_function_node compar=((common_function_node)(si.sym_info));
				
				//Проверяем, если мы нашли не предописание
                if (compar.function_code != null || is_order_independed_method_description)
                {
                    if (compar.is_overload == false)
                    {
                        AddError(new FunctionMustBeWithOverloadDirective(compar, fn));
                    }
                    if (convertion_data_and_alghoritms.function_eq_params(fn, compar, false) && fn.is_extension_method == compar.is_extension_method)
                    {
                    	if (fn.IsOperator && (fn.name == compiler_string_consts.explicit_operator_name || fn.name == compiler_string_consts.implicit_operator_name))
                    	{
                    		if (convertion_data_and_alghoritms.function_eq_params_and_result(fn,compar))
                    			AddError(new FunctionDuplicateDefinition(compar, fn));
                    	}
                    	else
                        {
                            if (fn is common_method_node && compar is common_method_node)
                            {
                                common_method_node cmn1 = fn as common_method_node;
                                common_method_node cmn2 = compar as common_method_node;
                                if (cmn1.explicit_interface == cmn2.explicit_interface)
                                    AddError(new FunctionDuplicateDefinition(compar, fn));
                            }
                            else
                                AddError(new FunctionDuplicateDefinition(compar, fn));
                        }
                    }
                    si = si.Next;
                    continue;
                }
               
				bool is_find_predefinition=false;

				if (compar.is_overload==false || overloads == 1 && in_unit)
				{
					//Если нет параметров в описании тела функции
					if (fn.parameters.Count==0)
					{
                        
						is_find_predefinition=true;
					}
					else
					{
						is_find_predefinition=is_predefinition(compar,fn,true);
					}
				}
				else
				{
					is_find_predefinition=is_predefinition(compar,fn,false);
				}

                if (!is_find_predefinition)
                {
                    si = si.Next;
                    continue;
                }
                else
                {
                    predef_find = true;
                    foreach (common_parameter par in fn.parameters)
                    {
                        if (par.default_value != null)
                        {
                            syntax_tree_visitor.AddError(par.loc, "DEFAULT_VALUE_MUST_BE_ONLY_IN_FIRST_DECLARATION");
                        }
                    }
                }

                if (compar.function_code!=null)
                {
                    AddError(fn.loc, "FUNCTION_{0}_ALREADY_HAVE_A_BODY", fn.name);
                }

                if ((compar.polymorphic_state == PascalABCCompiler.SemanticTree.polymorphic_state.ps_static) !=
                    (fn.polymorphic_state == PascalABCCompiler.SemanticTree.polymorphic_state.ps_static))
                {
                    syntax_tree_visitor.AddError(fn.loc, "CLASS_FUNCTION_ATTRIBUTE_MISMATCH");
                }

                common_method_node compiled_meth = fn as common_method_node;

                if (compiled_meth != null)
                {
                    common_method_node finded_method = (common_method_node)compar;
                    if (compiled_meth.is_constructor)
                    {
                        if (finded_method.is_constructor == false)
                        {
                            AddError(compiled_meth.loc, "CONSTRUCTOR_MUST_BE_REALIZED_WITH_CONSTRUCTOR_KEYWORD");
                        }
                        compiled_meth.return_value_type = finded_method.return_value_type;
                        convertion_data_and_alghoritms.create_function_return_variable(finded_method,null);
                    }
                }

				if (!convertion_data_and_alghoritms.eq_type_nodes(compar.return_value_type,fn.return_value_type) && fn.return_value_type != null)
				{
					AddError(fn.loc, "FUNCTION_PREDEFINITION_AND_DEFINITION_HAVE_DIFFERENT_RESULT_TYPES");
				}

				//НУЖЕН СПИСОК ФУНКЦИЙ С ПРЕДОПРЕДЕЛЕНИЯМИ, ЧТОБЫ ОБНАРУЖИТЬ ОПИСАННЫЕ НО НЕ ОПРЕДЕЛЕННЫЕ
				//Или не нужен???

				//TODO: СИНХРОНИЗИРОВАТЬ АТТРИБУТЫ!!!!!
				if (fn.is_overload)
				{
					compar.is_overload=true;
				}

                //TODO: Внимательно проверить следующий if.
                if (compar.is_overload)
                {
                    fn.is_overload = true;
                    last_created_function.symbol_kind = symbol_kind.sk_overload_function;
                }
				
				common_function_node cfn11=_func_stack.pop();
                compar.scope = cfn11.scope;

                common_method_node cmnode=compar as common_method_node;
                if (cmnode != null)
                {
                    SymbolInfo si_local = cfn11.scope.FindOnlyInScope(compiler_string_consts.self_word);
                    if (si_local != null)
                    {
                        si_local.sym_info = cmnode.self_variable;
                    }
                }

				//Удаляем текущую функцию
                SymbolInfo siint = null;
				switch(converting_block())
				{
					case block_type.function_block:
					{
						_func_stack.top().functions_nodes_list.remove((common_in_function_function_node)fn);
                        siint = _func_stack.top().scope.FindOnlyInScope(fn.name);
						break;
					}
					case block_type.namespace_block:
					{
						_cmn.functions.remove((common_namespace_function_node)fn);
                        siint = _cmn.scope.FindOnlyInScope(fn.name);
						break;
					}
					case block_type.type_block:
					{
                        //TODO: Доделать описание методов класса.
                        _ctn.methods.remove((common_method_node)fn);
                        siint = _ctn.scope.FindOnlyInScope(fn.name);
						break;
					}
                    case block_type.compiled_type_block:
                    {
                        if (syntax_tree_visitor.compiled_unit.namespaces[0].functions.Contains((common_namespace_function_node)fn))
                            syntax_tree_visitor.compiled_unit.namespaces[0].functions.remove((common_namespace_function_node)fn);
                        siint = _compiled_tn.find_in_type(fn.name);
                        break;
                    }

					default:
					{
						throw new CompilerInternalError("Undefined block type");
					}
				}
                while (siint.sym_info != fn && siint.Next != null)
                {
                    siint = siint.Next;
                }
                siint.sym_info = compar;

                //Мы удалили новую функцию. Сейчас мы должны перенести параметры из новой функции в старую.
                //TODO: У новой функции может вообще не быть параметров. Они все в старой. Разобраться с этим.  А зачем вообще переносить параметры?

                if (compar.parameters.Count != 0)
                {
                    if (fn.parameters.Count == 0)
                    {
                        foreach (common_parameter pr in compar.parameters)
                        {
                            compar.scope.AddSymbol(pr.name, new SymbolInfo(pr));
                        }
                    }
                    else
                    {
                        foreach (common_parameter pr in compar.parameters)
                        {
                            SymbolInfo par_sim_info = fn.scope.FindOnlyInScope(pr.name);
                            par_sim_info.sym_info = pr;
                        }
                    }
                }

                if (fn.is_generic_function)
                {
                    for (int i = 0; i < fn.generic_params.Count; ++i)
                    {
                        common_type_node t_fn = fn.generic_params[i] as common_type_node;
                        common_type_node t_compar = compar.generic_params[i] as common_type_node;
                        t_fn.is_class = t_compar.is_class;
                        t_fn.internal_is_value = t_compar.internal_is_value;
                        t_fn.SetImplementingInterfaces(t_compar.ImplementingInterfaces);
                        (t_fn.Scope as SymbolTable.IInterfaceScope).TopInterfaceScopeArray =
                            (t_compar.Scope as SymbolTable.IInterfaceScope).TopInterfaceScopeArray;
                        t_fn.SetBaseType(t_compar.base_type);
                        if (t_compar.has_default_constructor)
                        {
                            generic_parameter_eliminations.add_default_ctor(t_fn);
                        }
                        //t_fn.generic_function_container = compar;
                    }
                    //конверитируем параметры предописания в параметры описания.
                    List<type_node> fn_types = fn.get_generic_params_list();
                    foreach (common_parameter par in compar.parameters)
                    {
                        par.type = generic_convertions.determine_type(par.type, fn_types, true);
                    }
                    if (compar.return_value_type != null)
                    {
                        compar.return_value_type = generic_convertions.determine_type(compar.return_value_type, fn_types, true);
                        if (compar.return_variable != null)
                        {
                            compar.return_variable.type = compar.return_value_type;
                        }
                    }
                    compar.generic_params = fn.generic_params;
                    foreach (common_type_node tn in compar.generic_params)
                    {
                        tn.generic_function_container = compar;
                    }
                }

				_func_stack.push(compar);
				compar.attributes.AddRange(fn.attributes);
				//si.sym_info=fn;
				break;
			}
            if (fn is common_method_node && !predef_find && syntax_tree_visitor.current_converted_method_not_in_class_defined && _explicit_interface_type == null)
            {
                AddError(new NoMethodInClassWithThisParams(fn as common_method_node, (fn as common_method_node).cont_type, fn.loc));
            }
            return !predef_find;
		}