// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) //Посетитель синтаксического дерева. using System; using System.Linq; using System.Collections; using System.Collections.Generic; using PascalABCCompiler.SyntaxTree; using PascalABCCompiler.TreeRealization; using SyntaxTreeBuilder = PascalABCCompiler.SyntaxTree.SyntaxTreeBuilder; using SymTable = SymbolTable; using array_const = PascalABCCompiler.TreeRealization.array_const; using compiler_directive = PascalABCCompiler.TreeRealization.compiler_directive; using empty_statement = PascalABCCompiler.TreeRealization.empty_statement; using for_node = PascalABCCompiler.TreeRealization.for_node; using goto_statement = PascalABCCompiler.TreeRealization.goto_statement; using if_node = PascalABCCompiler.TreeRealization.if_node; using labeled_statement = PascalABCCompiler.TreeRealization.labeled_statement; using question_colon_expression = PascalABCCompiler.TreeRealization.question_colon_expression; using repeat_node = PascalABCCompiler.TreeRealization.repeat_node; using sizeof_operator = PascalABCCompiler.TreeRealization.sizeof_operator; using typeof_operator = PascalABCCompiler.TreeRealization.typeof_operator; using while_node = PascalABCCompiler.TreeRealization.while_node; using static PascalABCCompiler.StringConstants; using TreeConverter.LambdaExpressions.Closure; using TreeConverter.LambdaExpressions; using PascalABCCompiler.TreeConverter.TreeConversion; using System.Reflection; using PascalABCCompiler.SemanticTree; using PascalABCCompiler.CoreUtils; namespace PascalABCCompiler.TreeConverter { // Сахарный узел синтаксического дерева. Не генерируется автоматически, поскольку содержит ссылку на узел семантического дерева // Нужен только при генерации синтаксических узлов на семантическом уровне, т.е. для синтаксического сахара /* public class semantic_type_node : SyntaxTree.type_definition { public type_node type { get; set; } public semantic_type_node(type_node t) { type = t; } }*/ public partial class syntax_tree_visitor : SyntaxTree.WalkingVisitorNew // SSM 02.01.17 менять на визитор с другим порядком обхода можно, но бессмысленно // Порядок обхода не важен поскольку все узлы visit переопределяются // SSM 02.01.17 Использование ReplaceStatement из BaseChangeVisitor плохо изучено - что-то не работает // Поэтому используется явный Parent и ReplaceStatement из узла statement_list { public SymbolTable.PrimaryScope MainScope { get { var a = SymbolTable.ScopeTable.Where(s => (s.GetType() == typeof(SymbolTable.UnitInterfaceScope))).Skip(1); return new SymbolTable.PrimaryScope(a.Last()); } } public SymbolTable.PrimaryScope CurrentScope { get { if(context.CurrentScope != null) return new SymbolTable.PrimaryScope(context.CurrentScope); return null; } } public convertion_data_and_alghoritms convertion_data_and_alghoritms; public returner ret; internal string current_document; public compilation_context context; private bool var_def_statement_converting; private List inherited_from_partials_list = new List(); public ContextChanger contextChanger; internal using_namespace_list using_list = new using_namespace_list(); internal using_namespace_list interface_using_list = new using_namespace_list(); // SSM 6/08/15 Стек для хранения вложенных лямбд для одной цели - вычислить истинный тип выражения, присваиваемого Result. Это нужно для выбора перегруженной функции, у которой параметр лямбда и один из типов возвращаемого значения в точности совпадает с типом возвращаемого значения лямбды internal Stack stflambda = new Stack(); //TODO: Загнать в request. motivation_keeper motivation_keeper = new motivation_keeper(); private PascalABCCompiler.TreeRealization.unit_node_list _referenced_units; private common_unit_node _compiled_unit; public common_unit_node _system_unit; internal bool debug=true; public bool debugging=false; public bool for_intellisense = false; private List compiledVariables = new List(); internal List ErrorsList; internal List WarningsList; internal Dictionary docs; public bool for_native_code = false; public Dictionary DirectivesToNodesLinks; public bool ThrowCompilationError = true; public bool MustVisitBody = true; public LambdaProcessingState lambdaProcessingState = LambdaProcessingState.None; //lroman #region (MikhailoMMX) Положение визитора относительно параллельных конструкций public ParallelPosition CurrentParallelPosition = ParallelPosition.Outside; #endregion private GeneratedNamesManager generatedNamesManager; public GeneratedNamesManager GeneratedNamesManager => generatedNamesManager; public void InitializeForCompilingInterface(InitializationDataForCompilingInterface initializationData) { //convertion_data_and_alghoritms.__i = 0; Initialize(initializationData); this.docs = initializationData.docs; //comp_units=UsedUnits; //visit(SyntaxUnit //SyntaxTreeToSemanticTreeConverter.interface_using_list = namespaces; interface_using_list.Clear(); using_list.AddRange(initializationData.interfaceNamespaces); } public void InitializeForCompilingImplementation(InitializationDataForCompilingImplementation initializationData) { Initialize(initializationData); if (this.docs != null) this.docs = initializationData.docs; using_list.AddRange(initializationData.interfaceNamespaces); interface_using_list.AddRange(initializationData.interfaceNamespaces); using_list.AddRange(initializationData.implementationNamespaces); unit_module umod = initializationData.syntaxUnit as unit_module; if (umod == null) { throw new CompilerInternalError("Program has not implementation part"); } CompiledUnit = initializationData.semanticUnit; } private void Initialize(InitializationDataForCompilingInterface initializationData) { ParserError = initializationData.parserError; BadNodesInSyntaxTree = initializationData.badNodes; ReferencedUnits = initializationData.usedUnits; using_list.Clear(); current_document = initializationData.syntaxUnit.file_name; ErrorsList = initializationData.errorsList; WarningsList = initializationData.warningsList; this.debug = initializationData.debug; this.debugging = initializationData.debugging; this.for_intellisense = initializationData.forIntellisense; // Возможно, это тоже вызывает ошибки, если присваивается не паскалевский визитор, пока непонятно EVA SystemLibrary.SystemLibrary.syn_visitor = this; // Добавлено, потому что в SPython используются эти же объекты, а не создаются новые EVA convertion_data_and_alghoritms.syntax_tree_visitor = this; ret.syntax_tree_visitor = this; context.syntax_tree_visitor = this; // Счетчики для сгенерированных переменных generatedNamesManager = initializationData.generatedNamesManager; } /// /// Можно переопределять для добавления действий перед конвертацией интерфейсной и имплементационной частей /// public virtual void BeforeCompilationActions() { ResetBeforeModuleCompilation(); } /// /// Можно переопределять для добавления действий после конвертации интерфейсной и имплементационной частей /// public virtual void PostCompilationActions() { } public List CompiledVariables => compiledVariables; internal Errors.Error LastError() { Errors.Error err = ErrorsList[ErrorsList.Count-1]; ErrorsList.RemoveAt(ErrorsList.Count - 1); return err; } internal void RemoveLastError() { if (ErrorsList.Count > 0) ErrorsList.RemoveAt(ErrorsList.Count - 1); } public virtual void AddError(Errors.Error err, bool shouldReturn=false) { if (!for_intellisense && (ThrowCompilationError || !shouldReturn) /*|| err.MustThrow && !shouldReturn*/) { throw err; } else { ErrorsList.Add(err); } } public virtual void AddError(location loc, string ErrResourceString, params object[] values) { Errors.Error err = new SimpleSemanticError(loc, ErrResourceString, values); if ((ThrowCompilationError && !for_intellisense) || ErrResourceString == "FORWARD_DECLARATION_{0}_AS_BASE_TYPE") { throw err; } else { ErrorsList.Add(err); } } public void AddWarning(Errors.CompilerWarning err) { WarningsList.Add(err); } private bool _record_created = false; private bool with_class_name=false; internal bool from_pabc_dll = false; private bool type_section_converting = false; private Dictionary set_intls = new Dictionary(); //(ssyy) Дополнительные ограничения на параметры generic-типа. //Например, возможность объявить указатель на этот тип-параметр. internal Dictionary generic_param_abilities = new Dictionary(); private GenericParameterAbilities get_type_abilities(type_node t) { GenericParameterAbilities gpa; if (generic_param_abilities.TryGetValue(t, out gpa)) return gpa; gpa = new GenericParameterAbilities(); generic_param_abilities.Add(t, gpa); return gpa; } protected virtual void internal_reset() { PascalABCCompiler.SystemLibrary.SystemLibInitializer.initialization_properties init_properties = new PascalABCCompiler.SystemLibrary.SystemLibInitializer.initialization_properties(); init_properties.break_executor = make_break_node; init_properties.continue_executor = make_continue_node; init_properties.exit_executor = make_exit_node; _system_unit = SystemLibrary.SystemLibInitializer.make_system_unit(convertion_data_and_alghoritms.symbol_table, init_properties); SystemLibrary.SystemLibrary.system_unit = _system_unit; generic_convertions.reset_generics(); generic_convertions.visitor = this; #region MikhailoMMX, реинициализация класса OpenMP OpenMP.InternalReset(); #endregion ResetSelfFields(); } // Добавили, чтобы можно было использовать его для потомков syntax_tree_visitor EVA protected void ResetSelfFields() { _record_created = false; RefTypesForCheckPointersTypeForDotNetFramework.Clear(); reset_for_interface(); _is_interface_part = false; with_class_name = false; disable_order_independ = false; generic_param_abilities.Clear(); current_converted_method_not_in_class_defined = false; assign_is_converting = false; inherited_from_partials_list.Clear(); motivation_keeper.reset(); SystemLibrary.SystemLibInitializer.NeedsToRestore.Clear(); type_section_converting = false; ThrowCompilationError = true; lambdaProcessingState = LambdaProcessingState.None; //lroman // MikhailoMMX, реинициализация для OpenMP CurrentParallelPosition = ParallelPosition.Outside; } public syntax_tree_visitor(bool mainConverterInitialization = true) { // объекты ниже создаем только для паскалевского визитора, чтобы они оставались в единственном экземпляре EVA if (mainConverterInitialization) { convertion_data_and_alghoritms = new convertion_data_and_alghoritms(this); ret = new returner(this); context = new compilation_context(convertion_data_and_alghoritms, this); contextChanger = new ContextChanger(context); internal_reset(); } } private void release_system_module() { SystemUnitAssigned = false; SystemLibrary.SystemLibInitializer.format_function = null; SystemLibrary.SystemLibInitializer.read_procedure = null; SystemLibrary.SystemLibInitializer.write_procedure = null; SystemLibrary.SystemLibInitializer.writeln_procedure = null; SystemLibrary.SystemLibInitializer.readln_procedure = null; SystemLibrary.SystemLibInitializer.TextFileType = null; SystemLibrary.SystemLibInitializer.TextFileInitProcedure = null; SystemLibrary.SystemLibInitializer.BinaryFileType = null; SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = null; SystemLibrary.SystemLibInitializer.PointerOutputType = null; SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = null; SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = null; SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = null; SystemLibrary.SystemLibInitializer.TypedFileType = null; SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = null; SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = null; SystemLibrary.SystemLibInitializer.ShortStringType = null; SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = null; SystemLibrary.SystemLibInitializer.TypedSetType = null; SystemLibrary.SystemLibInitializer.SetUnionProcedure = null; SystemLibrary.SystemLibInitializer.SetIntersectProcedure = null; SystemLibrary.SystemLibInitializer.SetSubtractProcedure = null; SystemLibrary.SystemLibInitializer.InSetProcedure = null; SystemLibrary.SystemLibInitializer.CreateSetProcedure = null; SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = null; //SystemLibrary.SystemLibInitializer.IncludeProcedure = null; //SystemLibrary.SystemLibInitializer.ExcludeProcedure = null; SystemLibrary.SystemLibInitializer.DiapasonType = null; SystemLibrary.SystemLibInitializer.CreateDiapason = null; SystemLibrary.SystemLibInitializer.CreateObjDiapason = null; SystemLibrary.SystemLibInitializer.CompareSetEquals = null; SystemLibrary.SystemLibInitializer.CompareSetInEquals = null; SystemLibrary.SystemLibInitializer.CompareSetLess = null; SystemLibrary.SystemLibInitializer.CompareSetLessEqual = null; SystemLibrary.SystemLibInitializer.CompareSetGreater = null; SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = null; SystemLibrary.SystemLibInitializer.IncProcedure = null; SystemLibrary.SystemLibInitializer.DecProcedure = null; SystemLibrary.SystemLibInitializer.SuccFunction = null; SystemLibrary.SystemLibInitializer.PredFunction = null; SystemLibrary.SystemLibInitializer.OrdFunction = null; SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = null; SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = null; SystemLibrary.SystemLibInitializer.AssignSetProcedure = null; SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = null; SystemLibrary.SystemLibInitializer.ClipProcedure = null; SystemLibrary.SystemLibInitializer.ClipFunction = null; SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = null; SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = null; SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = null; SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = null; SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = null; SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = null; SystemLibrary.SystemLibInitializer.SetLengthProcedure = null; SystemLibrary.SystemLibInitializer.read_short_string_procedure = null; SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = null; SystemLibrary.SystemLibInitializer.InsertProcedure = null; SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = null; SystemLibrary.SystemLibInitializer.DeleteProcedure = null; SystemLibrary.SystemLibInitializer.LowFunction = null; SystemLibrary.SystemLibInitializer.HighFunction = null; SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = null; SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = null; SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = null; SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = null; SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = null; SystemLibrary.SystemLibInitializer.PointerToStringFunction = null; SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = null; SystemLibrary.SystemLibInitializer.PointerOutputConstructor = null; SystemLibrary.SystemLibInitializer.StrProcedure = null; SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = null; SystemLibrary.SystemLibInitializer.AssertProcedure = null; SystemLibrary.SystemLibInitializer.CheckRangeFunction = null; SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = null; SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = null; SystemLibrary.SystemLibInitializer.ArrayCopyFunction = null; SystemLibrary.SystemLibInitializer.ObjectType = null; SystemLibrary.SystemLibInitializer.StringType = null; SystemLibrary.SystemLibInitializer.ConfigVariable = null; SystemLibrary.SystemLibInitializer.PascalABCVersion = null; } internal bool SystemUnitAssigned = false; public static void init_system_module(common_unit_node psystem_unit) { SystemLibrary.SystemLibInitializer.format_function = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.format_procedure_name); SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_procedure_name); SystemLibrary.SystemLibInitializer.write_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.write_procedure_name); SystemLibrary.SystemLibInitializer.writeln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.writeln_procedure_name); SystemLibrary.SystemLibInitializer.print_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.print_procedure_name); SystemLibrary.SystemLibInitializer.println_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.println_procedure_name); SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.readln_procedure_name); SystemLibrary.SystemLibInitializer.TextFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.text_file_name_type_name); SystemLibrary.SystemLibInitializer.TextFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TextFileInitProcedureName); SystemLibrary.SystemLibInitializer.BinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileTypeName); SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AbstractBinaryFileTypeName); SystemLibrary.SystemLibInitializer.PointerOutputType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PointerOutputTypeName); SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileReadProcedureName); SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileInitProcedureName); SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.StringDefaultPropertySetProcedureName); SystemLibrary.SystemLibInitializer.TypedFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileTypeName); SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileInitProcedureName); SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileReadProcedureName); SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortString); SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.GetCharInShortString); SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.SetCharInShortString); //SystemLibrary.SystemLibInitializer.ShortStringType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ShortStringTypeName); //SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ShortStringTypeInitProcedure); SystemLibrary.SystemLibInitializer.TypedSetType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_name); SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitProcedure); SystemLibrary.SystemLibInitializer.SetUnionProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.union_of_set); SystemLibrary.SystemLibInitializer.SetIntersectProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.intersect_of_set); SystemLibrary.SystemLibInitializer.SetSubtractProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.subtract_of_set); SystemLibrary.SystemLibInitializer.InSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.in_set); SystemLibrary.SystemLibInitializer.CreateSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateSetProcedure); //SystemLibrary.SystemLibInitializer.IncludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.IncludeProcedure); //SystemLibrary.SystemLibInitializer.ExcludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ExcludeProcedure); SystemLibrary.SystemLibInitializer.DiapasonType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.DiapasonType); SystemLibrary.SystemLibInitializer.CreateDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateDiapason); SystemLibrary.SystemLibInitializer.CreateObjDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateObjDiapason); SystemLibrary.SystemLibInitializer.CompareSetEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetEquals); SystemLibrary.SystemLibInitializer.CompareSetInEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetInEquals); SystemLibrary.SystemLibInitializer.CompareSetLess = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetLess); SystemLibrary.SystemLibInitializer.CompareSetLessEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetLessEqual); SystemLibrary.SystemLibInitializer.CompareSetGreater = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetGreater); SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetGreaterEqual); SystemLibrary.SystemLibInitializer.IncProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.IncProcedure); SystemLibrary.SystemLibInitializer.DecProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.DecProcedure); SystemLibrary.SystemLibInitializer.SuccFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.SuccFunction); SystemLibrary.SystemLibInitializer.PredFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PredFunction); SystemLibrary.SystemLibInitializer.OrdFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.OrdFunction); SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitProcedureWithBounds); SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitWithShortString); SystemLibrary.SystemLibInitializer.AssignSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssignSetProcedure); SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssignSetProcedureWithBounds); SystemLibrary.SystemLibInitializer.ClipProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipProcedure); SystemLibrary.SystemLibInitializer.ClipFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipFunction); SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortStringInSetFunction); SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortStringInSetProcedure); SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_length_for_short_string); SystemLibrary.SystemLibInitializer.SetLengthProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_length_procedure_name); SystemLibrary.SystemLibInitializer.read_short_string_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_short_string); SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_short_string_from_file); SystemLibrary.SystemLibInitializer.InsertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,StringConstants.Insert); SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,StringConstants.InsertInShortString); SystemLibrary.SystemLibInitializer.DeleteProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit,StringConstants.Delete); SystemLibrary.SystemLibInitializer.LowFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit,StringConstants.Low); SystemLibrary.SystemLibInitializer.HighFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit,StringConstants.High); SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUsePointerOnType_proc_name); SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUseTypeForBinaryFiles_proc_name); SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUseTypeForTypedFiles_proc_name); SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.RuntimeDetermineType_func_name); SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.RuntimeInitializeFunction_func_name); SystemLibrary.SystemLibInitializer.PointerToStringFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PointerToStringFunction_func_name); SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.GetRuntimeSizeFunction_func_name); SystemLibrary.SystemLibInitializer.StrProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.StrProcedure_func_name); SystemLibrary.SystemLibInitializer.PascalABCVersion = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PascalABCVersion_func_name); SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ChrUnicodeFunction_func_name); SystemLibrary.SystemLibInitializer.AssertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssertProcedure); SystemLibrary.SystemLibInitializer.CheckRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.check_in_range); SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.check_in_range_char); SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CopyWithSizeFunction); SystemLibrary.SystemLibInitializer.ArrayCopyFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ArrayCopyFunction); SystemLibrary.SystemLibInitializer.ConfigVariable = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.config_variable_name); //SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,SystemLibrary.SystemLibrary.string_type,type_compare.less_type,SemanticTree.basic_function_type.none,true); //SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibrary.string_type,SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,type_compare.greater_type,SemanticTree.basic_function_type.none,true); if (SystemLibrary.SystemLibInitializer.TextFileType.Found) SystemLibrary.SystemLibInitializer.TextFileType.TypeNode.type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file; if (SemanticRulesConstants.GenerateNativeCode) { SystemLibrary.SystemLibInitializer.ObjectType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ObjectType); if (SystemLibrary.SystemLibInitializer.ObjectType.Found) SemanticRulesConstants.ClassBaseType = SystemLibrary.SystemLibInitializer.ObjectType.sym_info as TreeRealization.type_node; SystemLibrary.SystemLibInitializer.StringType = new PascalABCCompiler.SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.StringType); if (SystemLibrary.SystemLibInitializer.StringType.Found) SemanticRulesConstants.StringType = SystemLibrary.SystemLibInitializer.StringType.sym_info as TreeRealization.type_node; } } public static void init_system_module_from_dll(dot_net_unit_node psystem_unit) { SystemLibrary.SystemLibInitializer.format_function = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.format_procedure_name); SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_procedure_name); SystemLibrary.SystemLibInitializer.write_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.write_procedure_name); SystemLibrary.SystemLibInitializer.writeln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.writeln_procedure_name); SystemLibrary.SystemLibInitializer.print_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.print_procedure_name); SystemLibrary.SystemLibInitializer.println_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.println_procedure_name); SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.readln_procedure_name); SystemLibrary.SystemLibInitializer.TextFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.text_file_name_type_name); SystemLibrary.SystemLibInitializer.TextFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TextFileInitProcedureName); SystemLibrary.SystemLibInitializer.BinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileTypeName); SystemLibrary.SystemLibInitializer.AbstractBinaryFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AbstractBinaryFileTypeName); SystemLibrary.SystemLibInitializer.PointerOutputType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PointerOutputTypeName); SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileReadProcedureName); SystemLibrary.SystemLibInitializer.BinaryFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.BinaryFileInitProcedureName); SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.StringDefaultPropertySetProcedureName); SystemLibrary.SystemLibInitializer.TypedFileType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileTypeName); SystemLibrary.SystemLibInitializer.TypedFileInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileInitProcedureName); SystemLibrary.SystemLibInitializer.TypedFileReadProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedFileReadProcedureName); SystemLibrary.SystemLibInitializer.ClipShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortString); SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.GetCharInShortString); SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.SetCharInShortString); //SystemLibrary.SystemLibInitializer.ShortStringType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ShortStringTypeName); //SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ShortStringTypeInitProcedure); SystemLibrary.SystemLibInitializer.TypedSetType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_name); SystemLibrary.SystemLibInitializer.TypedSetInitProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitProcedure); SystemLibrary.SystemLibInitializer.SetUnionProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.union_of_set); SystemLibrary.SystemLibInitializer.SetIntersectProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.intersect_of_set); SystemLibrary.SystemLibInitializer.SetSubtractProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.subtract_of_set); SystemLibrary.SystemLibInitializer.InSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.in_set); SystemLibrary.SystemLibInitializer.CreateSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateSetProcedure); //SystemLibrary.SystemLibInitializer.IncludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.IncludeProcedure); //SystemLibrary.SystemLibInitializer.ExcludeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ExcludeProcedure); SystemLibrary.SystemLibInitializer.DiapasonType = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.DiapasonType); SystemLibrary.SystemLibInitializer.CreateDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateDiapason); SystemLibrary.SystemLibInitializer.CreateObjDiapason = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CreateObjDiapason); SystemLibrary.SystemLibInitializer.CompareSetEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetEquals); SystemLibrary.SystemLibInitializer.CompareSetInEquals = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetInEquals); SystemLibrary.SystemLibInitializer.CompareSetLess = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetLess); SystemLibrary.SystemLibInitializer.CompareSetLessEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetLessEqual); SystemLibrary.SystemLibInitializer.CompareSetGreater = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetGreater); SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CompareSetGreaterEqual); SystemLibrary.SystemLibInitializer.IncProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.IncProcedure); SystemLibrary.SystemLibInitializer.DecProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.DecProcedure); SystemLibrary.SystemLibInitializer.SuccFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.SuccFunction); SystemLibrary.SystemLibInitializer.PredFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PredFunction); SystemLibrary.SystemLibInitializer.OrdFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.OrdFunction); SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitProcedureWithBounds); SystemLibrary.SystemLibInitializer.TypedSetInitWithShortString = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.TypedSetInitWithShortString); SystemLibrary.SystemLibInitializer.AssignSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssignSetProcedure); SystemLibrary.SystemLibInitializer.AssignSetProcedureWithBounds = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssignSetProcedureWithBounds); SystemLibrary.SystemLibInitializer.ClipProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipProcedure); SystemLibrary.SystemLibInitializer.ClipFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipFunction); SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortStringInSetFunction); SystemLibrary.SystemLibInitializer.ClipShortStringInSetProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ClipShortStringInSetProcedure); SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_length_for_short_string); SystemLibrary.SystemLibInitializer.SetLengthProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.set_length_procedure_name); SystemLibrary.SystemLibInitializer.read_short_string_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_short_string); SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.read_short_string_from_file); SystemLibrary.SystemLibInitializer.InsertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.Insert); SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.InsertInShortString); SystemLibrary.SystemLibInitializer.DeleteProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.Delete); SystemLibrary.SystemLibInitializer.LowFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.Low); SystemLibrary.SystemLibInitializer.HighFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.High); SystemLibrary.SystemLibInitializer.CheckCanUsePointerOnTypeProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUsePointerOnType_proc_name); SystemLibrary.SystemLibInitializer.CheckCanUseTypeForBinaryFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUseTypeForBinaryFiles_proc_name); SystemLibrary.SystemLibInitializer.CheckCanUseTypeForTypedFilesProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CheckCanUseTypeForTypedFiles_proc_name); SystemLibrary.SystemLibInitializer.RuntimeDetermineTypeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.RuntimeDetermineType_func_name); SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.RuntimeInitializeFunction_func_name); SystemLibrary.SystemLibInitializer.PointerToStringFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PointerToStringFunction_func_name); SystemLibrary.SystemLibInitializer.GetRuntimeSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.GetRuntimeSizeFunction_func_name); SystemLibrary.SystemLibInitializer.StrProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.StrProcedure_func_name); SystemLibrary.SystemLibInitializer.PascalABCVersion = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.PascalABCVersion_func_name); SystemLibrary.SystemLibInitializer.ChrUnicodeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ChrUnicodeFunction_func_name); SystemLibrary.SystemLibInitializer.AssertProcedure = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.AssertProcedure); SystemLibrary.SystemLibInitializer.CheckRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.check_in_range); SystemLibrary.SystemLibInitializer.CheckCharRangeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.check_in_range_char); SystemLibrary.SystemLibInitializer.CopyWithSizeFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.CopyWithSizeFunction); SystemLibrary.SystemLibInitializer.ArrayCopyFunction = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.ArrayCopyFunction); SystemLibrary.SystemLibInitializer.ConfigVariable = new SystemLibrary.UnitDefinitionItem(psystem_unit, StringConstants.config_variable_name); //AddSpecialOperatorsToSetType(); //SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,SystemLibrary.SystemLibrary.string_type,type_compare.less_type,SemanticTree.basic_function_type.none,true); //SystemLibrary.SystemLibrary.make_type_conversion(SystemLibrary.SystemLibrary.string_type,SystemLibrary.SystemLibInitializer.ShortStringType.sym_info as type_node,type_compare.greater_type,SemanticTree.basic_function_type.none,true); if (SystemLibrary.SystemLibInitializer.TextFileType.Found) SystemLibrary.SystemLibInitializer.TextFileType.TypeNode.type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file; } protected virtual void get_system_module(common_unit_node psystem_unit) { init_system_module(psystem_unit); //esli zapustili v otladke, to vosstanovim mnozhestvo i procedury sozdanija diapasonov, inache ne budet rabotat if (debugging) { List si = SystemLibrary.SystemLibInitializer.CreateDiapason.SymbolInfo; si = SystemLibrary.SystemLibInitializer.CreateObjDiapason.SymbolInfo; si = SystemLibrary.SystemLibInitializer.TypedSetType.SymbolInfo; } //if (SystemLibrary.SystemLibInitializer.TextFileType.Found) // SystemLibrary.SystemLibInitializer.TextFileType.GetTypeNodeSpecials().type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file; SystemUnitAssigned = true; CreateSpecialFields(psystem_unit); } private void get_system_module_from_dll(dot_net_unit_node psystem_unit) { init_system_module_from_dll(psystem_unit); //esli zapustili v otladke, to vosstanovim mnozhestvo i procedury sozdanija diapasonov, inache ne budet rabotat if (debugging) { List si = SystemLibrary.SystemLibInitializer.CreateDiapason.SymbolInfo; si = SystemLibrary.SystemLibInitializer.CreateObjDiapason.SymbolInfo; si = SystemLibrary.SystemLibInitializer.TypedSetType.SymbolInfo; } //if (SystemLibrary.SystemLibInitializer.TextFileType.Found) // SystemLibrary.SystemLibInitializer.TextFileType.GetTypeNodeSpecials().type_special_kind = PascalABCCompiler.SemanticTree.type_special_kind.text_file; SystemUnitAssigned = true; //CreateSpecialFields(psystem_unit); } private void AddSpecialOperatorsToSetType() { if (SystemLibrary.SystemLibInitializer.TypedSetType.NotFound) return; common_type_node tctn = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as common_type_node; tctn.type_special_kind = SemanticTree.type_special_kind.base_set_type; tctn.scope.AddSymbol(StringConstants.plus_name, SystemLibrary.SystemLibInitializer.SetUnionProcedure.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.mul_name, SystemLibrary.SystemLibInitializer.SetIntersectProcedure.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.in_name, SystemLibrary.SystemLibInitializer.InSetProcedure.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.minus_name, SystemLibrary.SystemLibInitializer.SetSubtractProcedure.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.gr_name, SystemLibrary.SystemLibInitializer.CompareSetGreater.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.greq_name, SystemLibrary.SystemLibInitializer.CompareSetGreaterEqual.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.sm_name, SystemLibrary.SystemLibInitializer.CompareSetLess.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.smeq_name, SystemLibrary.SystemLibInitializer.CompareSetLessEqual.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.eq_name, SystemLibrary.SystemLibInitializer.CompareSetEquals.SymbolInfo.FirstOrDefault()); tctn.scope.AddSymbol(StringConstants.noteq_name, SystemLibrary.SystemLibInitializer.CompareSetInEquals.SymbolInfo.FirstOrDefault()); } protected void CreateSpecialFields(common_unit_node psystem_unit) { List sil = psystem_unit.scope.Find(StringConstants.IsConsoleApplicationVariableName); if (sil != null && sil.FirstOrDefault().sym_info is namespace_variable) { namespace_variable_reference nvr = new namespace_variable_reference(sil.FirstOrDefault().sym_info as namespace_variable, null); psystem_unit.IsConsoleApplicationVariableAssignExpr = make_assign_operator(nvr, psystem_unit.IsConsoleApplicationVariableValue, null); } } private void UpdateUnitDefinitionItemForUnit(common_unit_node unit) { if (!from_pabc_dll) { SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(unit, StringConstants.read_procedure_name); var si = SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo; SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(unit, StringConstants.readln_procedure_name); si = SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo; } else { //SystemLibrary.SystemLibInitializer.read_procedure = new SystemLibrary.UnitDefinitionItem(unit, StringConstants.read_procedure_name); //SystemLibrary.SystemLibInitializer.readln_procedure = new SystemLibrary.UnitDefinitionItem(unit, StringConstants.readln_procedure_name); } } /// /// Очистка переменных перед компиляцией интерфейсной или имплементационной части модуля /// private void ResetBeforeModuleCompilation() { context.ResetBeforeModuleCompilation(); } public void Reset() { _system_unit = null; SystemLibrary.SystemLibrary.system_unit = null; //SystemLibrary.SystemLibrary.Reset(); SystemUnitAssigned = false; _compiled_unit = null; _referenced_units = null; current_document = null; using_list.Clear(); //_referenced_units.clear(); ret.reset(); motivation_keeper.reset(); context.reset(); convertion_data_and_alghoritms.reset(); //compiled_type_node.compiled_types.Clear(); internal_reset(); release_system_module(); WaitedRefTypes.Clear(); set_intls.Clear(); NetHelper.NetHelper.reset(); if (ErrorsList != null) ErrorsList.Clear(); from_pabc_dll = false; in_interface_part = false; compiled_type_node[] ctns = new compiled_type_node[compiled_type_node.compiled_types.Values.Count]; compiled_type_node.compiled_types.Values.CopyTo(ctns, 0); null_type_node.reset(); foreach (compiled_type_node ctn in ctns) { ctn.reinit_scope(); ctn.clear_generated_names(); ctn.clear_generated_intersections(); } } public PascalABCCompiler.Errors.SyntaxError ParserError { get { return convertion_data_and_alghoritms.parser_error; } set { convertion_data_and_alghoritms.parser_error = value; } } public HashSet BadNodesInSyntaxTree { get { return convertion_data_and_alghoritms.bad_nodes_in_syntax_tree; } set { convertion_data_and_alghoritms.bad_nodes_in_syntax_tree = value; } } public string CurrentDocument { get { return current_document; } } public SymbolTable.TreeConverterSymbolTable SymbolTable { get { return convertion_data_and_alghoritms.symbol_table; } } public location get_location(SyntaxTree.syntax_tree_node tn) { var tnn = tn; /*while (tnn.source_context == null && tnn.Parent != null) { tnn = tnn.Parent; }*/ var tns = tnn.source_context; if (tns == null) { return null; } string file_name = current_document; if (tns.FileName != null && (file_name == null || file_name != tns.FileName)) file_name = tns.FileName; return new location(tns.begin_position.line_num, tns.begin_position.column_num, tns.end_position.line_num, tns.end_position.column_num, file_name); } public location get_right_location(SyntaxTree.syntax_tree_node tn) { if (tn.source_context == null) { return null; } return new location(tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, current_document); } public location get_location_with_check(SyntaxTree.syntax_tree_node tn) { if (tn == null || tn.source_context == null) { return null; } string file_name = current_document; if (tn.source_context.FileName != null) file_name = tn.source_context.FileName; return new location(tn.source_context.begin_position.line_num, tn.source_context.begin_position.column_num, tn.source_context.end_position.line_num, tn.source_context.end_position.column_num, file_name); } public common_unit_node CompiledUnit { get { return _compiled_unit; } //TODO: Нужен ли set? set { _compiled_unit = value; } } public PascalABCCompiler.TreeRealization.unit_node_list ReferencedUnits { get { return _referenced_units; } set { _referenced_units = value; } } //TODO: Может вынести всю работу с returner-ами в convertion_data_and_alghoritms? //Методы returner-а. //Запрос на построение и получение конвертированного поддерева. //Нежесткая проверка существования узла. private statement_node convert_weak(SyntaxTree.statement st) { if (st == null) { return null; } convertion_data_and_alghoritms.check_node_parser_error(st); //st = prepare_statement(st); statement_node sn = ret.visit(st); //sn.loc=get_location(st); return sn; } private expression_node convert_weak(SyntaxTree.expression expr) { if (expr == null) { return null; } convertion_data_and_alghoritms.check_node_parser_error(expr); //Посмотреть, может вызвать ошибку //ssyy motivation_keeper.reset(); //\ssyy expression_node en = ret.visit(expr); //en.loc=get_location(expr); return en; } private type_node convert_weak(SyntaxTree.type_definition type_def) { if (type_def == null) { return null; } convertion_data_and_alghoritms.check_node_parser_error(type_def); return ret.visit(type_def); } //Жесткая проверка существования узла. Проверка будет осуществлятся только в DEBUG версии. //Будем верить, что в RELEAS-е все будет работать правильно. private semantic_node convert_semantic_strong(SyntaxTree.syntax_tree_node tn) { #if (DEBUG) if (tn == null) { throw new CompilerInternalError("This syntax tree node can not be null."); } #endif convertion_data_and_alghoritms.check_node_parser_error(tn); motivation_keeper.set_motivation_to_expect_semantic_node(); return ret.visit(tn); } public statement_node convert_strong(SyntaxTree.statement st) { #if (DEBUG) if (st == null) { throw new CompilerInternalError("This syntax tree node can not be null."); } #endif #region MikhailoMMX, обработка критических секций OpenMP bool isCritical = false; SyntaxTree.statement st_orig = st; if (OpenMP.LocksFound) if (DirectivesToNodesLinks.ContainsKey(st) && OpenMP.IsCriticalDirective(DirectivesToNodesLinks[st])) { //если перед узлом есть директива omp critical isCritical = true; OpenMP.TryConvertCritical(ref st, this, DirectivesToNodesLinks[st]); OpenMP.DisableDirective(st_orig, DirectivesToNodesLinks); } #endregion convertion_data_and_alghoritms.check_node_parser_error(st); //st = prepare_statement(st); statement_node sn = null; try { sn = ret.visit(st); // SSM 19/01/17 закомментировал две следующие строчки //if (sn == null) // sn = new empty_statement(null); } /*catch (PascalABCCompiler.Errors.Error e) { if (ThrowCompilationError) throw e; else { ErrorsList.Add(e); return new empty_statement(null); } }*/ catch (Exception e) { var s = e.StackTrace; var runMethodInfo = e.TargetSite; //if (ThrowCompilationError) throw e; //else // return new empty_statement(null); } //sn.loc=get_location(st); #region MikhailoMMX, обработка критических секций OpenMP if (isCritical) OpenMP.EnableDirective(st_orig, DirectivesToNodesLinks); #endregion return sn; } public expression_node convert_strong(SyntaxTree.expression expr) { #if DEBUG //var s = expr + "\n"; //System.IO.File.AppendAllText("d:\\bb17.txt", s); #endif #if (DEBUG) if (expr == null) { throw new CompilerInternalError("This syntax tree node can not be null."); } #endif //if (expr.semantic_ex != null) // SSM 3.1.17 - возвращаем кешированное значение // return expr.semantic_ex as expression_node; convertion_data_and_alghoritms.check_node_parser_error(expr); //Посмотреть, может вызвать ошибку //ssyy motivation_keeper.reset(); // Это можно закомментировать - все тесты проходят SSM 2/1/17 //\ssyy expression_node en = ret.visit(expr); //if (lambdaProcessingState == LambdaProcessingState.FinishPhase) // expr.semantic_ex = en; // SSM 3.1.17 кешируем для последующего обращения if (en == null) AddError(get_location(expr), "EXPRESSION_EXPECTED"); //en.loc=get_location(expr); return en; } public type_node convert_strong(SyntaxTree.type_definition type_def) { #if (DEBUG) if (type_def == null) { throw new CompilerInternalError("This syntax tree node can not be null."); } #endif convertion_data_and_alghoritms.check_node_parser_error(type_def); type_node tn; SyntaxTree.function_header fh = (type_def as SyntaxTree.function_header); if (fh != null) { tn = convert_function_type(fh, get_location(type_def), context.get_delegate_type_name(), null); return tn; } else { SyntaxTree.procedure_header ph = (type_def as SyntaxTree.procedure_header); if (ph != null) { tn = convert_function_type(ph, get_location(type_def), context.get_delegate_type_name(), null); return tn; } } if (is_direct_type_decl && !(type_def is SyntaxTree.ref_type)) is_direct_type_decl = false; return ret.visit(type_def); } public addressed_expression convert_address_strong(SyntaxTree.addressed_value av) { #if (DEBUG) if (av == null) { throw new CompilerInternalError("This syntax tree node can not be null."); } #endif convertion_data_and_alghoritms.check_node_parser_error(av); motivation_keeper.set_motivation_to_expect_address(); addressed_expression ae = ret.visit(av); //ae.loc=get_location(av); return ae; } //Возвращение конвертированного поддерева. private void return_value(statement_node stat) { ret.return_value(stat); } private void return_value(expression_node expr) { ret.return_value(expr); } private void return_value(type_node tn) { ret.return_value(tn); } private void return_addressed_value(addressed_expression ae) { ret.return_value(ae); } private void return_semantic_value(semantic_node se) { ret.return_value(se); } public void weak_node_test_and_visit(SyntaxTree.syntax_tree_node tn) { if (tn != null) { convertion_data_and_alghoritms.check_node_parser_error(tn); tn.visit(this); } } public void hard_node_test_and_visit(SyntaxTree.syntax_tree_node tn) { #if (DEBUG) // try // { if (tn == null) { throw new CompilerInternalError("This node can not be null"); } #endif convertion_data_and_alghoritms.check_node_parser_error(tn); if (is_direct_type_decl && !(tn is SyntaxTree.ref_type)) is_direct_type_decl = false; tn.visit(this); /*#if (DEBUG) } catch (Exception e) { if (tn != null) throw new Exception("" + tn.source_context.ToString() + System.Environment.NewLine + e.ToString()); else throw e; } #endif*/ } private void assign_doc_info(definition_node dn, SyntaxTree.syntax_tree_node stn) { string s = null; if (docs != null && docs.TryGetValue(stn, out s) && !string.IsNullOrEmpty(s)) { dn.documentation = s; } return; } //Последний параметер - выходной. Он слдержит список параметров с преобразованиями типов. private function_node find_function(string name, location loc, PascalABCCompiler.TreeRealization.expressions_list parameters) { List sil = context.find(name); if (sil == null) { AddError(new NoFunctionWithThisName(loc)); } if (sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { AddError(new ThisIsNotFunctionName(loc)); } function_node fn = convertion_data_and_alghoritms.select_function(parameters, sil, loc); return fn; } //TODO: Обратить внимание на эту функцию. Ее вызовы не приводят к созданиям узлов преобразования типов. private function_node find_function(string name, location loc, params expression_node[] exprs) { expressions_list exprs_list = new expressions_list(); exprs_list.AddRange(exprs); return find_function(name, loc, exprs_list); } private expression_node find_operator(SyntaxTree.Operators ot, expression_node expr, location loc) { string name = name_reflector.get_name(ot); //#if (DEBUG) if (name == null) { if (ot == PascalABCCompiler.SyntaxTree.Operators.AddressOf) { if (expr.is_addressed == false) { AddError(expr.location, "CAN_NOT_GET_ADDRESS_FROM_EXPRESSION"); } expression_node res = new get_addr_node(expr, loc); return res; } if (ot == PascalABCCompiler.SyntaxTree.Operators.Dereference) { } throw new CompilerInternalError("Invalid operator name"); } //#endif List sil = expr.type.find(name, context.CurrentScope); if (sil == null || sil.FirstOrDefault().sym_info is wrapped_definition_node) { AddError(new OperatorCanNotBeAppliedToThisType(name, expr)); } expressions_list pars = new expressions_list(); pars.AddElement(expr); bool tmp = ThrowCompilationError; ThrowCompilationError = false; function_node fn; fn = convertion_data_and_alghoritms.select_function(pars, sil, loc); ThrowCompilationError = tmp; if (fn == null) { RemoveLastError(); AddError(new OperatorCanNotBeAppliedToThisType(name, expr)); } expr = pars[0]; #if (DEBUG) convertion_data_and_alghoritms.check_operator(fn); #endif expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, expr); return exp_node; } private expression_node find_operator(SyntaxTree.Operators ot, expression_node left, expression_node right, location loc) { string name = name_reflector.get_name(ot); return find_operator(name, left, right, loc); } bool CheckExpressionType(expression_node expr) { if (expr.type == null) { AddError(expr.location, "TYPE_NOT_DEFINED"); return false; } return true; } internal bool one_way_operation(string name) { if (name == StringConstants.plusassign_name) return true; if (name == StringConstants.minusassign_name) return true; if (name == StringConstants.multassign_name) return true; if (name == StringConstants.assign_name) return true; if (name == StringConstants.divassign_name) return true; return false; } public expression_node find_operator(string name, expression_node left, expression_node right, location loc, bool no_search_in_extension_methods = true) { #if (DEBUG) if (name == null) { throw new CompilerInternalError("Invalid operator name"); } #endif // Видимо, это сделано для присваивания, т.к. несимметрично. Но странно - f = nil должно возвращать boolean ! if (right.semantic_node_type == semantic_node_type.null_const_node) { if ( !type_table.is_with_nil_allowed(left.type) && !left.type.IsPointer) AddError(right.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); if (right.conversion_type == null) right = null_const_node.get_const_node_with_type(left.type, (null_const_node)right); } /*if (left.semantic_node_type == semantic_node_type.null_const_node) { if (!type_table.is_with_nil_allowed(right.type) && !right.type.IsPointer) AddError(left.location, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); left = null_const_node.get_const_node_with_type(right.type, (null_const_node)left); }*/ type_node left_type = left.type; type_node right_type = right.type; if (left_type == null && left is enum_const_node) { left_type = SystemLibrary.SystemLibrary.integer_type; left.type = left_type; } if (right_type == null && right is enum_const_node) { right_type = SystemLibrary.SystemLibrary.integer_type; right.type = right_type; } if (left_type.semantic_node_type == semantic_node_type.delegated_method) { delegated_methods dm1 = (delegated_methods)left_type; if (dm1.empty_param_method != null) { if (dm1.empty_param_method.simple_function_node.return_value_type != null) { left_type = dm1.empty_param_method.simple_function_node.return_value_type; } } } if (right_type.semantic_node_type == semantic_node_type.delegated_method && !left_type.IsDelegate && left_type.semantic_node_type != semantic_node_type.delegated_method) { try_convert_typed_expression_to_function_call(ref right); if (name != StringConstants.plusassign_name && name != StringConstants.minusassign_name) try_convert_typed_expression_to_function_call(ref left); right_type = right.type; } if (right_type.semantic_node_type == semantic_node_type.delegated_method && name != StringConstants.plusassign_name && name != StringConstants.minusassign_name) { delegated_methods dm2 = (delegated_methods)right_type; if (dm2.empty_param_method != null) { if (dm2.empty_param_method.simple_function_node.return_value_type != null) { right_type = dm2.empty_param_method.simple_function_node.return_value_type; } } } if (name == "+" && right_type == SystemLibrary.SystemLibrary.char_type && left_type != SystemLibrary.SystemLibrary.string_type) no_search_in_extension_methods = false; List sil = left_type.find_in_type(name, left_type.Scope, null, no_search_in_extension_methods); int added_symbols = -1; List sil2 = null; if (left_type != right_type && !one_way_operation(name)) { //SymbolInfo si2 = right_type.find(name, context.CurrentScope); if (sil != null) sil = new List(sil); if (name == "+" && right_type != SystemLibrary.SystemLibrary.string_type && left_type == SystemLibrary.SystemLibrary.char_type) no_search_in_extension_methods = false; sil2 = right_type.find_in_type(name, right_type.Scope, null, no_search_in_extension_methods); if ((sil != null) && (sil2 != null)) { //Важная проверка. Возможно один и тот же оператор с одними и теми же типами определен в двух разных классах. //Возможно она занимает много времени, но, наверное, от нее нельзя отказаться. List funcs = new List(); foreach(SymbolInfo sic in sil) { if (sic.sym_info.general_node_type != general_node_type.function_node) { BasePCUReader.RestoreSymbols(sil, name); } #if (DEBUG) if (sic.sym_info.general_node_type != general_node_type.function_node) { throw new CompilerInternalError("Expected operator."); } #endif function_node fn = (function_node)sic.sym_info; if (convertion_data_and_alghoritms.is_exist_eq_method_in_list(fn, funcs) == null) { //break; funcs.Add(fn); } } //TODO: Разобраться с зацикливанием. function_node_list fnl = new function_node_list(); foreach(SymbolInfo sic in sil2) { if (sic.sym_info.general_node_type != general_node_type.function_node) { BasePCUReader.RestoreSymbols(sil2, name); } #if (DEBUG) if (sic.sym_info.general_node_type != general_node_type.function_node) { throw new CompilerInternalError("Expected operator."); } #endif fnl.AddElement(((function_node)(sic.sym_info))); } added_symbols = sil.Count() - 1; foreach (function_node fnode in fnl) { function_node eq_func = convertion_data_and_alghoritms.find_eq_method_in_list(fnode, funcs); if (eq_func != null) { //TODO: Проверить правильно ли это будет работать. if (eq_func != fnode)//zachem eto nuzhno voobshe?? { basic_function_node bbfn1 = fnode as basic_function_node; basic_function_node bbfn2 = eq_func as basic_function_node; if ((bbfn1 != null) && (bbfn2 != null)) { if (bbfn1.basic_function_type != bbfn2.basic_function_type) { AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right)); } //sic = sic.Next; continue; } else { if (left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type || left.type.type_special_kind == SemanticTree.type_special_kind.set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.set_type || left.type.type_special_kind == SemanticTree.type_special_kind.base_set_type && right.type.type_special_kind == SemanticTree.type_special_kind.base_set_type || left.type == SystemLibrary.SystemLibrary.string_type && right.type.type_special_kind == SemanticTree.type_special_kind.short_string || right.type == SystemLibrary.SystemLibrary.string_type && left.type.type_special_kind == SemanticTree.type_special_kind.short_string || left.type.type_special_kind == SemanticTree.type_special_kind.short_string && right.type.type_special_kind == SemanticTree.type_special_kind.short_string || left.type.IsDelegate == right.type.IsDelegate) { //if (left.type.find_in_type(name) !=null) } else AddError(new TwoOperatorsCanBeCalled(eq_func, fnode, left, right)); } } } sil.Add(new SymbolInfo(fnode)); } } else { if (sil == null && sil2 != null) { sil = sil2; } } } //if (si == null) { if (left_type.semantic_node_type == semantic_node_type.delegated_method && right_type.semantic_node_type == semantic_node_type.delegated_method) { List saved_sil = sil; List saved_sil2 = sil2; base_function_call bfc = null; if (!(left is typed_expression) && left.type is delegated_methods && name == ":=" && left is local_variable_reference && (left as local_variable_reference).var.type is undefined_type) { //left = convertion_data_and_alghoritms.explicit_convert_type(left, CreateDelegate((left.type as delegated_methods).proper_methods[0].simple_function_node)); left.type = CreateDelegate((left.type as delegated_methods).proper_methods[0].simple_function_node); } else { if (!(left is typed_expression) && !(left.type is delegated_methods)) AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); if (left is typed_expression) bfc = ((left as typed_expression).type as delegated_methods).proper_methods[0]; else bfc = (left.type as delegated_methods).proper_methods[0]; left = convertion_data_and_alghoritms.explicit_convert_type(left, CreateDelegate(bfc.simple_function_node)); } sil = left.type.find_in_type(name); if (!(right is typed_expression) && right.type is delegated_methods) bfc = (right.type as delegated_methods).proper_methods[0]; else bfc = ((right as typed_expression).type as delegated_methods).proper_methods[0]; right = convertion_data_and_alghoritms.explicit_convert_type(right, CreateDelegate(bfc.simple_function_node)); sil2 = right.type.find_in_type(name); if (saved_sil != null && sil != null) { sil.RemoveRange(1, sil.Count() - 1); sil.AddRange(saved_sil); } else saved_sil = sil; if (saved_sil2 != null && sil2 != null) { sil2.RemoveRange(1, sil2.Count() - 1); sil2.AddRange(saved_sil2); } else saved_sil2 = sil2; if (saved_sil == null) { if (!no_search_in_extension_methods) AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); else return find_operator(name, left, right, loc, false); } } else if (left_type.semantic_node_type == semantic_node_type.delegated_method) { } else if (sil != null && left.semantic_node_type == semantic_node_type.delegated_method) { List local_sil = sil; } else if (sil == null) { if (no_search_in_extension_methods) return find_operator(name, left, right, loc, false); else { if (right.type is undefined_type) AddError(right.location, "CAN_NOT_DEDUCE_TYPE_{0}", ""); else AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); } } } // После этой точки right_type и left_type не используются! expressions_list pars = null; function_node fnsel = null; if (sil != null) { foreach (SymbolInfo tmp_si in sil) { if (tmp_si.sym_info is wrapped_definition_node) BasePCUReader.RestoreSymbols(sil, name); } } pars = new expressions_list(); pars.AddElement(left); pars.AddElement(right); bool tmp_throw_error = ThrowCompilationError; ThrowCompilationError = !no_search_in_extension_methods; fnsel = convertion_data_and_alghoritms.select_function(pars, sil, loc); if (!ThrowCompilationError && fnsel == null) { RemoveLastError(); ThrowCompilationError = tmp_throw_error; return find_operator(name, left, right, loc, false); } else ThrowCompilationError = tmp_throw_error; //function_node fnsel=convertion_data_and_alghoritms.select_function(pars,si,loc); CheckSpecialFunctionCall(sil, pars,loc); //TODO: А это зачем? Можно передать в create_simple_function_call pars. left = pars[0]; right = pars[1]; if (fnsel == null) { AddError(new OperatorCanNotBeAppliedToThisTypes(name, left, right, loc)); } if (added_symbols != -1 && sil != null && added_symbols < sil.Count()) sil.RemoveRange(added_symbols + 1, sil.Count() - 1 - added_symbols); if (SystemUnitAssigned && in_check_range_region() && name == StringConstants.assign_name && is_range_checkable(left.type) && is_range_checkable(right.type)) { ordinal_type_interface oti = left.type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (left.type != SystemLibrary.SystemLibrary.char_type && left.type != SystemLibrary.SystemLibrary.uint64_type && !(oti.lower_value is ulong_const_node)) if(!(oti.lower_value is enum_const_node) && !(oti.lower_value is char_const_node)) right = convertion_data_and_alghoritms.convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); else if (oti.lower_value is enum_const_node) { right = convertion_data_and_alghoritms.explicit_convert_type(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CheckRangeFunction.sym_info as common_namespace_function_node, null, convertion_data_and_alghoritms.explicit_convert_type(right,SystemLibrary.SystemLibrary.int64_type), convertion_data_and_alghoritms.explicit_convert_type(oti.lower_value,SystemLibrary.SystemLibrary.int64_type),convertion_data_and_alghoritms.explicit_convert_type(oti.upper_value,SystemLibrary.SystemLibrary.int64_type)),right.type); } else if (oti.lower_value is char_const_node) right = convertion_data_and_alghoritms.create_simple_function_call( SystemLibrary.SystemLibInitializer.CheckCharRangeFunction.sym_info as common_namespace_function_node, null, right, oti.lower_value,oti.upper_value ); } expression_node exp_node = convertion_data_and_alghoritms.create_simple_function_call(fnsel, loc, left, right); return exp_node; } internal bool in_check_range_region() { return false; } internal bool is_range_checkable(type_node tn) { ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null && !tn.IsEnum && tn != SystemLibrary.SystemLibrary.bool_type) return true; return false; } private base_function_call_list convert_functions_to_calls(expression_node obj, List fnl, location loc, bool is_static) { base_function_call_list ret = new base_function_call_list(); foreach (function_node fnode in fnl) { base_function_call bfc = null; switch (fnode.semantic_node_type) { case semantic_node_type.common_namespace_function_node: { common_namespace_function_node cmfn = fnode as common_namespace_function_node; common_namespace_function_call cnfc = new common_namespace_function_call(cmfn, loc); if (cmfn.ConnectedToType != null) cnfc.parameters.AddElement(obj); if (cmfn.is_generic_function && !cmfn.is_generic_function_instance && cmfn.ConnectedToType != null && cmfn.parameters.Count == 1) { expressions_list parameters = new expressions_list(); parameters.AddElement(obj); function_node inst = null; try { inst = generic_convertions.DeduceFunction(cmfn, parameters, true, context, loc); } catch { continue; } cnfc = new common_namespace_function_call((common_namespace_function_node)inst, loc); if (cmfn.ConnectedToType != null) cnfc.parameters.AddElement(obj); } /*if (cmfn.parameters.Count >= 1 && cmfn.parameters[cmfn.parameters.Count - 1].is_params) { convertion_data_and_alghoritms.select_function(cnfc.parameters, new SymbolInfo(cmfn), loc); }*/ bfc = cnfc; break; } case semantic_node_type.basic_function_node: { //Может здесь стоит и выругаться, но я не буду пока этого делать. break; } case semantic_node_type.common_in_function_function_node: { common_in_function_function_node ciffn = fnode as common_in_function_function_node; int depth = convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(ciffn.scope, context.top_function.scope); common_in_function_function_call ciffc = new common_in_function_function_call(ciffn, depth, loc); bfc = ciffc; break; } case semantic_node_type.common_method_node: { common_method_node cmn = fnode as common_method_node; //Если cmn конструктор - то плохо, но его не должно сюда попасть. if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { if (!is_static) { if (obj == null) obj = GetCurrentObjectReference(cmn.cont_type.Scope, cmn, loc);//new this_node(context.converted_type, loc); common_method_call cmc = new common_method_call(cmn, obj, loc); cmc.virtual_call = !inherited_ident_processing; bfc = cmc; } //ssyy!!! Мне сложно понять предназначение данного кода, но, по-видимому, //следует его переписать так. else if (cmn.is_constructor) { if (cmn.parameters.Count == 0) { if (cmn.cont_type.IsAbstract) AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.cont_type.name); ret.Clear(); ret.AddElement(new common_constructor_call(cmn, loc)); return ret; } } } else { if (is_static) { common_static_method_call csmc = new common_static_method_call(cmn, loc); bfc = csmc; } } break; } case semantic_node_type.compiled_function_node: { compiled_function_node cfn = fnode as compiled_function_node; if (cfn.cont_type.Scope == null && cfn is compiled_function_node) (cfn.cont_type as compiled_type_node).init_scope(); if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { //ispravleno ibond //if (is_static) { if (cfn.is_generic_function && !cfn.is_generic_function_instance && cfn.ConnectedToType != null && cfn.parameters.Count == 1) { expressions_list parameters = new expressions_list(); parameters.AddElement(obj); function_node inst = null; try { inst = generic_convertions.DeduceFunction(cfn, parameters, true, context, loc); } catch { continue; } if (inst is common_namespace_function_node) bfc = new common_namespace_function_call((common_namespace_function_node)inst, loc); else if (inst is compiled_function_node) bfc = new compiled_static_method_call((compiled_function_node)inst, loc); else bfc = new compiled_static_method_call(cfn, loc); } else { compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc); bfc = csmc; } if (cfn.ConnectedToType != null) bfc.parameters.AddElement(obj); } } else { if (!is_static) { if (obj == null) obj = GetCurrentObjectReference(cfn.cont_type.Scope, cfn, loc);//new this_node(context.converted_type, loc); compiled_function_call cfc = new compiled_function_call(cfn, obj, loc); cfc.virtual_call = !inherited_ident_processing; bfc = cfc; } } break; } case semantic_node_type.compiled_constructor_node: { //Этот код мы вроде не должны вызывать, но если он все-же вызовется. compiled_constructor_node ccn = fnode as compiled_constructor_node; compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc); bfc = ccc; break; } default: { throw new CompilerInternalError("Undefined method type."); } } if (bfc != null) { ret.AddElement(bfc); } } return ret; } private base_function_call_list create_possible_delegates_list(expression_node obj, List sil, location loc, bool is_static) { if (sil == null) { return new base_function_call_list(); } var fnl = new List(); foreach(SymbolInfo si in sil) { function_node fn = si.sym_info as function_node; if (si.sym_info is compiled_property_node) { fn = (si.sym_info as compiled_property_node).get_function; } else if (si.sym_info is common_property_node) { fn = (si.sym_info as common_property_node).get_function; } if (fn != null && convertion_data_and_alghoritms.find_eq_method_in_list(fn, fnl) == null) { if (!(obj != null && fn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && !fn.is_extension_method)) { if (fn.is_extension_method) { if (obj != null && (fn.parameters[0].type == obj.type || type_table.compare_types(fn.parameters[0].type, obj.type) == type_compare.greater_type)) fnl.Insert(0,fn); else fnl.Add(fn); } else fnl.Add(fn); } } else { } } return convert_functions_to_calls(obj, fnl, loc, is_static); } private base_function_call_list create_possible_delegates_list(expression_node obj, function_node func, location loc, bool is_static) { var fnl = new List(); fnl.Add(func); return convert_functions_to_calls(obj, fnl, loc, is_static); } internal typed_expression make_delegate_wrapper(expression_node obj, List sil, location loc, bool is_static) { base_function_call_list fnl = create_possible_delegates_list(obj, sil, loc, is_static); if (fnl.Count == 0) { if (is_static) { AddError(loc, "EXPECTED_STATIC_METHOD"); } else { if (sil != null && sil.Count != 0 && sil.First().sym_info is basic_function_node) { basic_function_node bfn = sil.First().sym_info as basic_function_node; if (bfn.return_value_type != null) AddError(loc, "USING_{0}_NOT_ALLOWED_IN_THIS_CONTEXT", bfn.name); else AddError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", bfn.name); } else AddError(loc, "EXPECTED_NON_STATIC_METHOD"); } } delegated_methods dm = new delegated_methods(); dm.proper_methods.AddRange(fnl); typed_expression te = new typed_expression(dm, loc); return te; } internal typed_expression make_delegate_wrapper(expression_node obj, function_node func, location loc, bool is_static) { base_function_call_list fnl = create_possible_delegates_list(obj, func, loc, is_static); if (fnl.Count == 0) { if (is_static) { AddError(loc, "EXPECTED_STATIC_METHOD"); } else { AddError(loc, "EXPECTED_NON_STATIC_METHOD"); } } delegated_methods dm = new delegated_methods(); dm.proper_methods.AddRange(fnl); typed_expression te = new typed_expression(dm, loc); return te; } private bool check_name_in_current_scope(string name) { SymbolTable.Scope cscope = context.CurrentScope, name_scope = context.find_first(name).scope; while (cscope is SymbolTable.BlockScope) { if (name_scope == cscope) return true; cscope = cscope.TopScope; } if (cscope is SymbolTable.UnitImplementationScope && name_scope is SymbolTable.UnitInterfaceScope) return cscope.TopScope == name_scope; return cscope == name_scope; } void checkPolymorphicState(definition_node dn,location loc) { } private type_node find_type(string name, location loc) { definition_node di = context.check_name_node_type(name, loc, general_node_type.type_node); type_node tn = (type_node)di; return tn; } //(ssyy) разбил private type_node find_type(SyntaxTree.named_type_reference names, location loc) { definition_node di; SyntaxTree.template_type_reference ttr = names as SyntaxTree.template_type_reference; if (ttr != null) { di = ret.visit(names); type_node tn = di as type_node; if (tn == null) { AddError(loc, "TYPE_REFERENCE_EXPECTED"); } return tn; } List sil = context.find_definition_node(names, loc); if (sil == null && attribute_converted) { names.names[names.names.Count-1].name += "Attribute"; sil = context.find_definition_node(names, loc); } if (sil != null && sil.FirstOrDefault().sym_info != null && sil.FirstOrDefault().sym_info.general_node_type == general_node_type.generic_indicator) { generic_indicator gi = sil.FirstOrDefault().sym_info as generic_indicator; AddError(loc, "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", names.names[names.names.Count - 1].name, gi.generic.generic_params.Count); } if (sil == null || sil.FirstOrDefault().sym_info == null) { check_possible_generic_names(names, loc); } var lastname = names.names[names.names.Count - 1]; syntax_tree_node l = lastname; while (l.source_context == null && l.Parent != null) l = l.Parent; lastname.source_context = l?.source_context; di = context.check_name_node_type(lastname.name, sil?.FirstOrDefault(), get_location(lastname), general_node_type.type_node); if (di == null) return new undefined_type(lastname.name, loc); return (type_node)di; } public void check_possible_generic_names(SyntaxTree.named_type_reference names, location loc) { string tmp = names.names[names.names.Count - 1].name; int num; string generic_name = StringConstants.GetGenericTypeInformation(tmp, out num); List counts; bool found = NetHelper.NetHelper.generics_names.TryGetValue(generic_name.ToLower(), out counts); if (found) { foreach (int k in counts) { names.names[names.names.Count - 1].name = generic_name + StringConstants.generic_params_infix + k.ToString(); List sinfo = context.find_definition_node(names, loc); if (sinfo != null) { names.names[names.names.Count - 1].name = tmp; AddError(loc, "GENERIC_TYPE_{0}_NEEDS_{1}_GENERIC_PARAMETERS", generic_name, k); break; } } names.names[names.names.Count - 1].name = tmp; } } public expression_node make_break_node(location call_location, params expression_node[] parameters) { if (parameters.Length != 0) { return null; } if (context.cycle_stack.Count == 0) { AddError(new BreakStatementWithoutComprehensiveCycle(call_location)); } if (context.in_finally_block()) { AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK"); } statement_node sn = context.cycle_stack.Peek(); switch (sn.semantic_node_type) { case semantic_node_type.while_node: { while_node wn = (while_node)sn; return new while_break_node(wn, call_location); } case semantic_node_type.repeat_node: { repeat_node rn = (repeat_node)sn; return new repeat_break_node(rn, call_location); } case semantic_node_type.for_node: { for_node fn = (for_node)sn; return new for_break_node(fn, call_location); } case semantic_node_type.foreach_node: { foreach_node fn = (foreach_node)sn; return new foreach_break_node(fn, call_location); } } throw new CompilerInternalError("Undefined cycle type"); } public expression_node make_continue_node(location call_location, params expression_node[] parameters) { if (parameters.Length != 0) { return null; } if (context.cycle_stack.Count == 0) { AddError(new ContinueStatementWithoutComprehensiveCycle(call_location)); } if (context.in_finally_block()) { AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK"); } statement_node sn = context.cycle_stack.Peek(); switch (sn.semantic_node_type) { case semantic_node_type.while_node: { while_node wn = (while_node)sn; return new while_continue_node(wn, call_location); } case semantic_node_type.repeat_node: { repeat_node rn = (repeat_node)sn; return new repeat_continue_node(rn, call_location); } case semantic_node_type.for_node: { for_node fn = (for_node)sn; return new for_continue_node(fn, call_location); } case semantic_node_type.foreach_node: { foreach_node fn = (foreach_node)sn; return new foreach_continue_node(fn, call_location); } } throw new CompilerInternalError("Undefined cycle type"); } public expression_node make_exit_node(location call_location, params expression_node[] parameters) { if (parameters.Length != 0) { return null; } if (context.in_finally_block(true)) { AddError(call_location, "EXIT_BREAK_CONTINUE_IN_FINALLY_BLOCK"); } if (!TreeConverter.SemanticRulesConstants.EnableExitProcedure) AddError(new TreeConverter.UndefinedNameReference(StringConstants.exit_procedure_name, call_location)); return new exit_procedure(call_location); } public override void visit(SyntaxTree.inherited_message _inherited_message) { //throw new NotSupportedError(get_location(_inherited_message)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.expression_evaluation: return_value(inherited_message_value_reciving(_inherited_message)); break; //case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break; case motivation.address_receiving: case motivation.semantic_node_reciving: AddError(get_location(_inherited_message), "CAN_NOT_ASSIGN_TO_LEFT_PART"); break; } } private expression_node current_catch_excep; public override void visit(SyntaxTree.try_stmt _try_stmt) { context.enter_code_block_without_bind(); context.enter_exception_handlers(); statement_node try_statements = convert_strong(_try_stmt.stmt_list); context.leave_code_block(); location loc = get_location(_try_stmt); exception_filters_list efl = new exception_filters_list(); SyntaxTree.try_handler_except try_hand_except = _try_stmt.handler as SyntaxTree.try_handler_except; if (try_hand_except != null) { if (try_hand_except.except_block.handlers != null) { int hand_count = try_hand_except.except_block.handlers.handlers.Count; for (int i = 0; i < hand_count; i++) { SyntaxTree.exception_handler eh = try_hand_except.except_block.handlers.handlers[i]; type_node filter_type = convert_strong(eh.type_name); if (!SemanticRulesConstants.GenerateNativeCode && !(filter_type.is_generic_parameter || filter_type == SystemLibrary.SystemLibrary.exception_base_type || type_table.is_derived(SystemLibrary.SystemLibrary.exception_base_type, filter_type))) { AddError(get_location(eh.type_name), "EXCEPTION_TYPE_MUST_BE_SYSTEM_EXCEPTION_OR_DERIVED_FROM_EXCEPTION"); } current_catch_excep = new int_const_node(2,null);//create_constructor_call(filter_type, new expressions_list(), null); local_block_variable_reference lvr = null; statements_list sl = new statements_list(get_location(eh.statements)); convertion_data_and_alghoritms.statement_list_stack_push(sl); context.enter_code_block_without_bind(); if (eh.variable != null) { local_block_variable lbv = context.add_var_definition(eh.variable.name, get_location(eh.variable), filter_type, SemanticTree.polymorphic_state.ps_common, true) as local_block_variable; lvr = new local_block_variable_reference(lbv, lbv.loc); } statement_node stm = convert_strong(eh.statements); context.leave_code_block(); sl = convertion_data_and_alghoritms.statement_list_stack.Pop(); if (sl.statements.Count > 0 || sl.local_variables.Count > 0) { sl.statements.AddElement(stm); stm = sl; } exception_filter ef = new exception_filter(filter_type, lvr, stm, get_location(eh)); efl.AddElement(ef); current_catch_excep = null; } } else { context.enter_code_block_without_bind(); exception_filter ef = new exception_filter(null, null, convert_strong(try_hand_except.except_block.stmt_list), get_location(try_hand_except.except_block.stmt_list)); context.leave_code_block(); efl.AddElement(ef); } if (try_hand_except.except_block.else_stmt_list != null) { context.enter_code_block_without_bind(); statement_node else_stm = convert_strong(try_hand_except.except_block.else_stmt_list); context.leave_code_block(); type_node ftype = SystemLibrary.SystemLibrary.object_type; exception_filter else_ef = new exception_filter(ftype, null, else_stm, else_stm.location); efl.AddElement(else_ef); } } else { type_node filter_type = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(StringConstants.ExceptionName)); expression_node current_catch_excep = create_constructor_call(filter_type, new expressions_list(), null); local_block_variable_reference lvr = null; local_block_variable tmp_var = context.add_var_definition(context.BuildName(generatedNamesManager.GenerateName("$try_temp"), generatedNamesManager), null, SystemLibrary.SystemLibrary.bool_type, null) as local_block_variable; statements_list stm = new statements_list(null); SyntaxTree.try_handler_finally try_hndlr_finally = _try_stmt.handler as SyntaxTree.try_handler_finally; context.enter_code_block_without_bind(); context.enter_finally_block(); statement_node finally_stmt = convert_strong(try_hndlr_finally.stmt_list); context.leave_finally_block(); context.leave_code_block(); stm.statements.AddElement(finally_stmt); basic_function_call bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,null); bfc.parameters.AddElement(new local_block_variable_reference(tmp_var,null)); stm.statements.AddElement(new if_node(bfc,new rethrow_statement_node(null),null,null)); exception_filter ef = new exception_filter(filter_type, lvr, stm, null); //efl.AddElement(ef); bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,null); bfc.parameters.AddElement(new local_block_variable_reference(tmp_var,null)); bfc.parameters.AddElement(new bool_const_node(true,null)); //(try_statements as statements_list).statements.AddElement(bfc); //(try_statements as statements_list).statements.AddElement(new throw_statement_node(current_catch_excep,null)); return_value(new try_block(try_statements, finally_stmt, efl, loc)); context.leave_exception_handlers(); return; } statement_node finally_st = null; SyntaxTree.try_handler_finally try_handler_finally = _try_stmt.handler as SyntaxTree.try_handler_finally; if (try_handler_finally != null) { context.enter_code_block_without_bind(); context.enter_finally_block(); try { finally_st = convert_strong(try_handler_finally.stmt_list); } finally { context.leave_finally_block(); } context.leave_code_block(); } try_block tb = new try_block(try_statements, finally_st, efl, loc); context.leave_exception_handlers(); return_value(tb); } public override void visit(SyntaxTree.try_handler_except _try_handler_except) { throw new NotSupportedError(get_location(_try_handler_except)); } public override void visit(SyntaxTree.try_handler_finally _try_handler_finally) { throw new NotSupportedError(get_location(_try_handler_finally)); } public override void visit(SyntaxTree.try_handler _try_handler) { throw new NotSupportedError(get_location(_try_handler)); } public override void visit(SyntaxTree.exception_block _exception_block) { throw new NotSupportedError(get_location(_exception_block)); } public override void visit(SyntaxTree.exception_handler_list _exception_handler_list) { throw new NotSupportedError(get_location(_exception_handler_list)); } public override void visit(SyntaxTree.exception_ident _exception_ident) { throw new NotSupportedError(get_location(_exception_ident)); } public override void visit(SyntaxTree.exception_handler _exception_handler) { throw new NotSupportedError(get_location(_exception_handler)); } public override void visit(SyntaxTree.known_type_ident _known_type_ident) { if (_known_type_ident.type == PascalABCCompiler.SyntaxTree.known_type.string_type) { var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: return_value(SystemLibrary.SystemLibrary.string_type); break; case motivation.expression_evaluation: return_value(SystemLibrary.SystemLibrary.string_type); break; //case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break; case motivation.semantic_node_reciving: return_semantic_value(SystemLibrary.SystemLibrary.string_type); break; } return; } //throw new NotSupportedError(get_location(_known_type_ident)); } public override void visit(SyntaxTree.file_type _file_type) { if (_file_type.file_of_type != null) { //Типизированый файл type_node el_type = convert_strong(_file_type.file_of_type); check_for_type_allowed(el_type,get_location(_file_type.file_of_type)); check_using_static_class(el_type, get_location(_file_type.file_of_type)); //if (el_type == SystemLibrary.SystemLibrary.void_type) // ErrorsList.Add(new VoidNotValid(get_location(_file_type.file_of_type))); /*if (el_type == SystemLibrary.SystemLibInitializer.TextFileType.sym_info) { //Это текстовый файл!!! return_value(el_type); return; }*/ if (SystemLibrary.SystemLibInitializer.TypedFileType == null || SystemLibrary.SystemLibInitializer.TypedFileInitProcedure == null) AddError(new NotSupportedError(get_location(_file_type))); if (!CanUseThisTypeForTypedFiles(el_type)) AddError(get_location(_file_type.file_of_type), "INVALID_ELEMENT_TYPE_FOR_TYPED_FILE", el_type); return_value(context.create_typed_file_type(el_type, get_location(_file_type))); } else { //Бинарнай файл if (SystemLibrary.SystemLibInitializer.BinaryFileType == null) AddError(new NotSupportedError(get_location(_file_type))); ((type_node)SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info).type_special_kind = SemanticTree.type_special_kind.binary_file; return_value((type_node)SystemLibrary.SystemLibInitializer.BinaryFileType.sym_info); } } private bool CanUseThisTypeForFiles (type_node el_type, bool allow_strings) { if (el_type.is_generic_parameter) { if (SemanticRulesConstants.AllowGenericParametersForFiles) { if (allow_strings) get_type_abilities(el_type).useful_for_binary_files = true; else get_type_abilities(el_type).useful_for_typed_files = true; return true; } else { return false; } } if (el_type.type_special_kind == SemanticTree.type_special_kind.short_string) return true; if (el_type.type_special_kind == SemanticTree.type_special_kind.set_type) { if (el_type.element_type == SystemLibrary.SystemLibrary.byte_type || el_type.element_type == SystemLibrary.SystemLibrary.sbyte_type || el_type.element_type == SystemLibrary.SystemLibrary.bool_type || el_type.element_type.IsEnum) return true; else if (el_type.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type) { if (el_type.element_type.base_type == SystemLibrary.SystemLibrary.byte_type || el_type.element_type.base_type == SystemLibrary.SystemLibrary.sbyte_type || el_type.element_type.base_type == SystemLibrary.SystemLibrary.bool_type || el_type.element_type.base_type.IsEnum) return true; if (el_type.element_type.base_type == SystemLibrary.SystemLibrary.integer_type) { ordinal_type_interface oti = el_type.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (((oti.upper_value as int_const_node).constant_value-(oti.lower_value as int_const_node).constant_value) <= 256) return true; } return false; } return false; } if (el_type.is_value) { generic_instance_type_node gitn = el_type as generic_instance_type_node; if (gitn != null) { List ftypes = gitn.all_field_types; foreach (type_node ftype in ftypes) { if (!CanUseThisTypeForFiles(ftype, allow_strings)) return false; } return true; } if (SystemLibrary.SystemLibrary.CanUseThisTypeForTypedFiles(el_type)) return true; if (el_type is common_type_node) { if (el_type as common_type_node == context.converted_type || (el_type.original_generic != null && el_type.original_generic == context.converted_type)) return false; common_type_node ctn = el_type as common_type_node; foreach (class_field cf in ctn.fields) if (!cf.IsStatic) if (cf.type.type_special_kind != SemanticTree.type_special_kind.short_string && !CanUseThisTypeForFiles(cf.type, allow_strings)) return false; return true; } if (el_type is compiled_type_node) { compiled_type_node ctn = el_type as compiled_type_node; if (!ctn.compiled_type.IsLayoutSequential) return false; System.Reflection.FieldInfo[] fields = ctn.compiled_type.GetFields(); foreach (System.Reflection.FieldInfo fi in fields) if (!fi.IsStatic) if (!CanUseThisTypeForFiles(compiled_type_node.get_type_node(fi.FieldType), allow_strings)) return false; return true; } } if (IsBoundedArray(el_type)) { //это обычный массив bounded_array_interface bai = (bounded_array_interface)el_type.get_internal_interface(internal_interface_kind.bounded_array_interface); return CanUseThisTypeForFiles(bai.element_type, allow_strings); } if (allow_strings && el_type == SystemLibrary.SystemLibrary.string_type) { return true; } return false; } private bool CanUseThisTypeForTypedFiles(type_node el_type) { if (el_type.type_special_kind == SemanticTree.type_special_kind.short_string) return true; return CanUseThisTypeForFiles(el_type, false); } private bool CanUseThisTypeForBinaryFiles(type_node el_type) { if (el_type == SystemLibrary.SystemLibrary.string_type || el_type is short_string_type_node) return true; return CanUseThisTypeForFiles(el_type, true); } internal List get_short_string_lens(type_node tn) { List lst = new List(); if (tn.type_special_kind == SemanticTree.type_special_kind.short_string) { lst.Add((tn as short_string_type_node).Length); } if (tn is common_type_node) { common_type_node ctn = tn as common_type_node; if (ctn.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { lst.AddRange(get_short_string_lens(ctn.element_type)); } else if (ctn.type_special_kind == SemanticTree.type_special_kind.record) { foreach (class_field fld in ctn.fields) lst.AddRange(get_short_string_lens(fld.type)); } } return lst; } internal int get_short_string_size(type_node tn) { if (tn.type_special_kind == SemanticTree.type_special_kind.short_string) { return (tn as short_string_type_node).Length+1; } if (tn is common_type_node) { common_type_node ctn = tn as common_type_node; if (ctn.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { int len = ((ctn.find_first_in_type(StringConstants.internal_array_name).sym_info as class_field).type as simple_array).length; return len*get_short_string_size(ctn.element_type); } else if (ctn.type_special_kind == SemanticTree.type_special_kind.record) { int off = 0; foreach (class_field fld in ctn.fields) off += get_short_string_size(fld.type); return off; } return 0; } return 0; } internal expression_node get_init_call_for_typed_file(var_definition_node vdn, type_node element_type) { location loc = (vdn.type as common_type_node).loc; if (!SystemUnitAssigned) AddError(new NotSupportedError(loc)); //Когда заработает наследование конструкторов надо вставить это /* expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(new typeof_operator(element_type, loc)); base_function_call bfc = create_constructor_call(vdn.type, exl, loc); expression_node expr = find_operator(StringConstants.assign_name, var_ref, bfc, loc); */ type_node tn = vdn.type; vdn.type = SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(var_ref); exl.AddElement(new typeof_operator(element_type, loc)); List lens = get_short_string_lens(element_type); int sz = get_short_string_size(element_type); if (sz > 0) { exl.AddElement(new int_const_node(get_short_string_size(element_type),null)); for (int i=0; i 1) fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedSetInitProcedureWithBounds.SymbolInfo, loc); else fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedSetInitProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray()); vdn.type = tn; return expr; } internal expression_node get_init_call_for_set_as_constr(var_definition_node vdn, expression_node init_value) { location loc = (vdn.type as common_type_node).loc; if (!SystemUnitAssigned) AddError(new NotSupportedError(loc)); //Когда заработает наследование конструкторов надо вставить это /* expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(new typeof_operator(element_type, loc)); base_function_call bfc = create_constructor_call(vdn.type, exl, loc); expression_node expr = find_operator(StringConstants.assign_name, var_ref, bfc, loc); */ type_node tn = vdn.type; vdn.type = SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); //exl.AddElement(var_ref); //exl.AddElement(new typeof_operator(element_type, loc)); if (tn.element_type == SystemLibrary.SystemLibrary.byte_type) { exl.AddElement(new byte_const_node(byte.MinValue,null)); exl.AddElement(new byte_const_node(byte.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.sbyte_type) { exl.AddElement(new sbyte_const_node(sbyte.MinValue,null)); exl.AddElement(new sbyte_const_node(sbyte.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.short_type) { exl.AddElement(new short_const_node(short.MinValue,null)); exl.AddElement(new short_const_node(short.MaxValue,null)); } else if (tn.element_type == SystemLibrary.SystemLibrary.ushort_type) { exl.AddElement(new ushort_const_node(ushort.MinValue,null)); exl.AddElement(new ushort_const_node(ushort.MaxValue,null)); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.element_type.type_special_kind == SemanticTree.type_special_kind.enum_kind) { ordinal_type_interface ii = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; exl.AddElement(ii.lower_value); exl.AddElement(ii.upper_value); } exl.AddElement(init_value); function_node fn = null; if (exl.Count > 1) { fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(default_constructor_name), loc); } else { fn = convertion_data_and_alghoritms.select_function(exl, (SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node).find_in_type(default_constructor_name), loc); } //expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, null, exl.ToArray()); expression_node expr = create_static_method_call_with_params(fn, loc, tn, false, exl); vdn.type = tn; return expr; } internal expression_node get_init_call_for_short_string(var_definition_node vdn) { location loc = (vdn.type as short_string_type_node).loc; type_node tn = vdn.type; //vdn.type = SystemLibrary.SystemLibInitializer.ShortStringType.TypeNode; vdn.type = SystemLibrary.SystemLibrary.string_type; int Length = (tn as short_string_type_node).Length; expression_node var_ref = create_variable_reference(vdn, loc); expressions_list exl = new expressions_list(); exl.AddElement(var_ref); exl.AddElement(new int_const_node(Length, loc)); expression_node expr = null; //if (SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure != null) //convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.ShortStringTypeInitProcedure.SymbolInfo, null, context.converted_type, context.top_function, true); vdn.type = tn; return expr; } public override void visit(SyntaxTree.op_type_node _op_type_node) { throw new NotSupportedError(get_location(_op_type_node)); } public override void visit(SyntaxTree.raise_stmt _raise_stmt) { location loc = get_location(_raise_stmt); if (_raise_stmt.expr == null) { var st = _raise_stmt.Parent; while (st != null && !(st is exception_block)) { st = st.Parent; } //if (current_catch_excep == null) if (st == null) AddError(loc, "RAISE_WITHOUT_PARAMETERS_MUST_BE_IN_CATCH_BLOCK"); return_value(new rethrow_statement_node(loc)); return; } expression_node en = convert_strong(_raise_stmt.expr); if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression); if (!SemanticRulesConstants.GenerateNativeCode && (!(type_table.is_derived(SystemLibrary.SystemLibrary.exception_base_type, en.type))) && (en.type != SystemLibrary.SystemLibrary.exception_base_type)) { AddError(loc, "EXCEPTION_TYPE_MUST_BE_SYSTEM_EXCEPTION_OR_DERIVED_FROM_EXCEPTION"); } if (_raise_stmt.address != null) { AddError(new NotSupportedError(get_location(_raise_stmt.address))); } return_value(new throw_statement_node(en, loc)); } public override void visit(SyntaxTree.token_info _token_info) { throw new NotSupportedError(get_location(_token_info)); } public override void visit(SyntaxTree.initfinal_part _initfinal_part) { } private bool is_format_allowed=false; public override void visit(SyntaxTree.format_expr _format_expr) { if (_format_expr.expr == null || _format_expr.format1 == null) AddError(get_location(_format_expr), "BAD_CONSTRUCTED_FORMAT_EXPRESSION"); //TODO: Добавить проверки. if (!SemanticRulesConstants.AllowUseFormatExprAnywhere && !is_format_allowed) AddError(get_location(_format_expr.expr), "FORMAT_EXPRESSION_CAN_USE_ONLY_IN_THESE_PROCEDURES"); expression_node expr = convert_strong(_format_expr.expr); if (expr is typed_expression) expr = convert_typed_expression_to_function_call(expr as typed_expression); expression_node par1 = convert_strong(_format_expr.format1); par1 = convertion_data_and_alghoritms.convert_type(par1, SystemLibrary.SystemLibrary.integer_type); expression_node par2 = convert_weak(_format_expr.format2); if (par2 != null) { if (expr.type != SystemLibrary.SystemLibrary.double_type && expr.type != SystemLibrary.SystemLibrary.float_type) { AddError(expr.location, "REAL_TYPE_IN_DOUBLE_COLON_EXPRESSION_EXPECTED"); } par2 = convertion_data_and_alghoritms.convert_type(par2, SystemLibrary.SystemLibrary.integer_type); } expressions_list exl = new expressions_list(); exl.AddElement(expr); exl.AddElement(par1); if (par2 != null) { exl.AddElement(par2); } location loc = get_location(_format_expr); if (!SystemUnitAssigned) AddError( new NotSupportedError(loc)); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.format_function.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return_value(ret); } internal bool inherited_ident_processing = false; public override void visit(SyntaxTree.inherited_ident _inherited_ident) { inherited_ident_processing = true; var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: return_addressed_value(inherited_ident_address_reciving(_inherited_ident)); break; case motivation.expression_evaluation: if (string.IsNullOrEmpty(_inherited_ident.name)) { inherited_message msg = new inherited_message(); msg.source_context = _inherited_ident.source_context; return_value(inherited_message_value_reciving(new inherited_message())); } else return_value(inherited_ident_value_reciving(_inherited_ident)); break; //case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break; case motivation.semantic_node_reciving: return_semantic_value(inherited_ident_semantic_reciving(_inherited_ident)); break; } inherited_ident_processing = false; return; } public override void visit(SyntaxTree.property_parameter_list _property_parameter_list) { throw new NotSupportedError(get_location(_property_parameter_list)); } public override void visit(SyntaxTree.property_parameter _property_parameter) { throw new NotSupportedError(get_location(_property_parameter)); } public override void visit(SyntaxTree.property_interface _property_interface) { //throw new NotSupportedError(get_location(_property_interface)); } public override void visit(SyntaxTree.property_array_default _property_array_default) { throw new NotSupportedError(get_location(_property_array_default)); } public override void visit(SyntaxTree.record_type_parts _record_type_parts) { throw new NotSupportedError(get_location(_record_type_parts)); } public override void visit(SyntaxTree.var_def_list_for_record _var_def_list) { throw new NotSupportedError(get_location(_var_def_list)); } public override void visit(SyntaxTree.diapason_expr _diapason_expr) { throw new NotSupportedError(get_location(_diapason_expr)); } public override void visit(SyntaxTree.case_variants _case_variants) { throw new NotSupportedError(get_location(_case_variants)); } public override void visit(SyntaxTree.literal _literal) { throw new NotSupportedError(get_location(_literal)); } public override void visit(SyntaxTree.array_of_const_type_definition _array_of_const_type_definition) { throw new NotSupportedError(get_location(_array_of_const_type_definition)); } public override void visit(SyntaxTree.array_of_named_type_definition _array_of_named_type_definition) { throw new NotSupportedError(get_location(_array_of_named_type_definition)); } public override void visit(SyntaxTree.proc_block _proc_block) { throw new NotSupportedError(get_location(_proc_block)); } private statements_list get_statements_list(statement_node sn) { statements_list snl = sn as statements_list; if (snl != null) { return snl; } snl = new statements_list(null); snl.statements.AddElement(sn); return snl; } private statements_list add_first_statement(statement_node list, statement_node statement) { statements_list snl = get_statements_list(list); snl.statements.AddElementFirst(statement); return snl; } private statements_list add_last_statement(statement_node list, statement_node statement) { statements_list snl = get_statements_list(list); snl.statements.AddElement(statement); return snl; } public override void visit(SyntaxTree.block _block) { var tt = context.converting_block(); List declarations_with_lambdas = new List(); if (/*context.converting_block() != block_type.namespace_block && */_block.defs != null && _block.defs.defs != null) { foreach (var def in _block.defs.defs.Where(d => d is const_definition || d is consts_definitions_list || d is variable_definitions)) { var lambdaSearcher = new LambdaSearcher(def); if (lambdaSearcher.CheckIfContainsLambdas()) { if (context.converting_block() != block_type.namespace_block || !(def is variable_definitions)) AddError(new LambdasNotAllowedInDeclarationsSection(get_location(lambdaSearcher.FoundLambda))); // SSM 6.06.15 - Хочется убрать это. В разделе описаний лямбды нужны - пусть и без замыканий. Если внутри подпрограммы - не нужны, но Вы же запретили везде! else declarations_with_lambdas.Add(def as variable_definitions); } } } int lambda_init_index = 0; foreach (variable_definitions vd in declarations_with_lambdas) { foreach (var_def_statement vds in vd.list) { var lambdaSearcher = new LambdaSearcher(vds); if (lambdaSearcher.CheckIfContainsLambdas() && !(vds.inital_value is function_lambda_definition) && vds.inital_value != null) // SSM 27/10/17 { procedure_definition func = new short_func_definition( SyntaxTreeBuilder.BuildShortFuncDefinition(new formal_parameters(), new procedure_attributes_list(), new method_name("<>lambda_initializer" + lambda_init_index), null, vds.inital_value, null)); vds.inital_value = new method_call(new ident("<>lambda_initializer"+lambda_init_index), new expression_list()); _block.defs.InsertBefore(vd, func); lambda_init_index++; } } } if (context.converting_block() == block_type.function_block && context.converted_func_stack.Count == 1) { if (_block.defs != null) foreach (declaration decl in _block.defs.defs) { if (decl is procedure_definition) { context.has_nested_functions = true; break; } } } weak_node_test_and_visit(_block.defs); if (context.converting_block() == block_type.function_block && context.converted_func_stack.Count == 1) context.has_nested_functions = false; //ssyy добавил генерацию вызова конструктора предка без параметров if (context.converting_block() == block_type.function_block) { common_method_node cmn = context.top_function as common_method_node; if (cmn != null && cmn.is_constructor && !(cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static)) { context.allow_inherited_ctor_call = true; if (_block.program_code != null && _block.program_code.subnodes != null) { //(ssyy) Для записей конструктор предка не вызываем. bool should_ctor_add = context.converted_type.is_class; if (should_ctor_add) { if (_block.program_code.subnodes.Count > 0) { SyntaxTree.procedure_call pc = _block.program_code.subnodes[0] as SyntaxTree.procedure_call; if (pc != null || _block.program_code.subnodes[0] is SyntaxTree.inherited_message) { //SyntaxTree.inherited_ident ii = pc.func_name as SyntaxTree.inherited_ident; //SyntaxTree.method_call mc = pc.func_name as SyntaxTree.method_call; //SyntaxTree.ident id = pc.func_name as SyntaxTree.ident; //if (/*ii != null*/id != null || mc != null /*&& mc.dereferencing_value is SyntaxTree.inherited_ident*/) { //(ssyy) Не уверен, что следующий оператор необходим. convertion_data_and_alghoritms.check_node_parser_error(_block.program_code); var lambdaSearcher = new LambdaSearcher(_block.program_code.subnodes[0]); if (!lambdaSearcher.CheckIfContainsLambdas()) { statement_node inh = convert_strong(_block.program_code.subnodes[0]); compiled_constructor_call c1 = inh as compiled_constructor_call; if (c1 != null && !c1._new_obj_awaited) { should_ctor_add = false; } else { common_constructor_call c2 = inh as common_constructor_call; if (c2 != null && !c2._new_obj_awaited) { should_ctor_add = false; } } } } } } } if (should_ctor_add) { //Пытаемся добавить вызов .ctor() предка... //Для начала проверим, есть ли у предка таковой. bool not_found = true; List sym = context.converted_type.base_type.find_in_type(default_constructor_name, context.CurrentScope); if (sym != null) { foreach (SymbolInfo sym_unit in sym) { if (!not_found) break; compiled_constructor_node ccn = sym_unit.sym_info as compiled_constructor_node; if (ccn != null && ccn.parameters.Count == 0) { not_found = false; } else { common_method_node cnode = sym_unit.sym_info as common_method_node; if (cnode != null && cnode.is_constructor && (cnode.parameters.Count == 0 || cnode.parameters[0].default_value != null)) { not_found = false; } } } } if (not_found) { var l = get_location(_block.program_code); if (l == null) { AddError(cmn.return_value_type.location, "IN_AUTOGENERATED_DEFAULT_CONSTRUCTOR_THE_DEFAULT_CONSTRUCTOR_OF_BASE_CLASS_CANNOT_BE_CALLED_BECAUSE_IS_ABSENT_OR_PRIVATE"); } //У предка нет конструктора по умолчанию AddError(l, "INHERITED_CONSTRUCTOR_CALL_EXPECTED"); } else { //Генерируем вызов .ctor() предка SyntaxTree.inherited_ident ii = new SyntaxTree.inherited_ident(); ii.name = default_constructor_name; _block.program_code.subnodes.Insert(0, new SyntaxTree.procedure_call(ii)); //context.allow_inherited_ctor_call = false; } } } } } //\ssyy //ssyy if (context.converting_block() == block_type.namespace_block) { context.check_predefinition_defined(); } if (lambdaProcessingState == LambdaProcessingState.None && _block.program_code != null) { var lambdaSearcher = new LambdaSearcher(_block.program_code); var lambdaIsFound = lambdaSearcher.CheckIfContainsLambdas(); if ((context.converting_block() == block_type.function_block || context.converting_block() == block_type.namespace_block) && lambdaIsFound) // TODO: Пока обрабатываются только блок функции и основной блок, необходимо обрабатывать случаи появлений лямбд в var_def_statement { if (context.converting_block() == block_type.function_block) { if (context.func_stack.Peek().functions_nodes_list.Count > 0) { AddError(new LambdasNotAllowedWhenNestedSubprogrammesAreUsed(get_location(lambdaSearcher.FoundLambda))); } } lambdaProcessingState = LambdaProcessingState.TypeInferencePhase; visit_program_code(_block.program_code); // Очистили списки goto для меток перед следующим этапом - пока ничего не дало - закомментируем foreach (var l in context._cmn.labels) { l.goto_statements.Clear(); l.comprehensive_code_block = null; } if (context.func_stack.Count > 0) { var fun = context.func_stack.Peek(); foreach (var l in fun.label_nodes_list) { l.goto_statements.Clear(); l.comprehensive_code_block = null; } } // Грубо - удаление мусора при разборе лямбд. Происходит исключение - заголовок разбирается, тело остается пустым - и из-за этого была ошибка #1270. while (context._cmn.functions.Count > 0 && context._cmn.functions[context._cmn.functions.Count-1].function_code == null && context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda") && !context._cmn.functions[context._cmn.functions.Count - 1].name.StartsWith("<>lambda_initializer")) { #if DEBUG //System.IO.File.AppendAllText("aa.txt", context._cmn.functions[context._cmn.functions.Count - 1].name+"\n"); #endif context._cmn.functions[context._cmn.functions.Count - 1].function_code = new statements_list(null); //context._cmn.functions.remove_at(context._cmn.functions.Count - 1); } lambdaProcessingState = LambdaProcessingState.ClosuresProcessingPhase; CapturedVariablesSubstitutionsManager.Substitute(this, _block.defs, _block.program_code, generatedNamesManager); lambdaProcessingState = LambdaProcessingState.FinishPhase; context.code = visit_program_code(_block.program_code); lambdaProcessingState = LambdaProcessingState.None; } else { context.code = visit_program_code(_block.program_code); } } else { context.code = visit_program_code(_block.program_code); } } private statement_node visit_program_code(statement_list program_code) { context.enter_code_block_with_bind(); statement_node sn = convert_strong(program_code); context.leave_code_block(); return sn; } public override void visit(SyntaxTree.diap_expr _diap_expr) { throw new NotSupportedError(get_location(_diap_expr)); } internal SymbolTable.Scope[] build_referenced_units(unit_node_list referenced_units, bool try_get_system_module) { List used_units = new List(); Dictionary assembly_references_dict = new Dictionary(); for (int i = 0; i < referenced_units.Count; i++) { if (referenced_units[i] is dot_net_unit_node) if (!assembly_references_dict.ContainsKey((referenced_units[i] as dot_net_unit_node).dotNetScope._assembly)) assembly_references_dict.Add((referenced_units[i] as dot_net_unit_node).dotNetScope._assembly, referenced_units[i] as dot_net_unit_node); } dot_net_unit_node[] assembly_references = new dot_net_unit_node[assembly_references_dict.Values.Count]; assembly_references_dict.Values.CopyTo(assembly_references, 0); List def_scopes = new List(); if (SemanticRulesConstants.AllowGlobalVisibilityForPABCDll) { for (int i = 0; i < assembly_references.Length; i++) { if (assembly_references[i].dotNetScope.entry_type != null) def_scopes.Add(assembly_references[i].dotNetScope); } } //used_units.Add(_system_unit.scope); for (int i = 0; i < referenced_units.Count; i++) { if (!(referenced_units[i] is dot_net_unit_node)) { if (referenced_units[i] is namespace_unit_node) { namespace_unit_node nun = referenced_units[i] as namespace_unit_node; for (int j = 0; j < assembly_references.Length; j++) { using_namespace_list unl = new using_namespace_list(); unl.AddElement((referenced_units[i] as namespace_unit_node).namespace_name); NetHelper.NetScope ns = new PascalABCCompiler.NetHelper.NetScope(unl, assembly_references[j].dotNetScope._assembly, SymbolTable); used_units.Add(ns); } if (_compiled_unit != null) _compiled_unit.used_namespaces.Add((referenced_units[i] as namespace_unit_node).namespace_name.namespace_name); if (nun.scope != null) used_units.Add(nun.scope); } else { common_unit_node cun = referenced_units[i] as common_unit_node; if (cun != null) { if (try_get_system_module && cun.IsSystemUnit) { get_system_module(cun); for (int j = 0; j < def_scopes.Count; j++) { used_units.Add(new PascalABCCompiler.NetHelper.NetScope(interface_using_list, def_scopes[j]._assembly, SymbolTable)); } } used_units.Add(cun.scope); } else { throw new CompilerInternalError("Unexpected unit type."); } } } else { dot_net_unit_node dun = referenced_units[i] as dot_net_unit_node; if (dun.dotNetScope.entry_type != null && dun.dotNetScope.entry_type.Name == "PABCRtl") { if (try_get_system_module) { from_pabc_dll = true; get_system_module_from_dll(dun); } } } } List fetched_used_units = new List(); Dictionary assm_cache = new Dictionary(); for (int i = 0; i < used_units.Count; i++) { PascalABCCompiler.NetHelper.NetScope net_scope = used_units[i] as PascalABCCompiler.NetHelper.NetScope; if (net_scope != null) { PascalABCCompiler.NetHelper.NetScope existing_scope = null; if (assm_cache.TryGetValue(net_scope.Assembly, out existing_scope)) { /*if (net_scope.used_namespaces) { foreach (using_namespace un in net_scope.used_namespaces) { if (un.namespace_name) } }*/ existing_scope.used_namespaces.AddRange(net_scope.used_namespaces); } else { if (NetHelper.NetHelper.PABCSystemType == null || net_scope.Assembly != NetHelper.NetHelper.PABCSystemType.Assembly) assm_cache.Add(net_scope.Assembly, net_scope); fetched_used_units.Add(net_scope); } } else fetched_used_units.Add(used_units[i]); } used_units = fetched_used_units; //Если компилими implementation то в начало кладем все что было в interface for (int i = 0; i < assembly_references.Length; i++) { used_units.Add(new PascalABCCompiler.NetHelper.NetScope(interface_using_list, (assembly_references[i] as dot_net_unit_node).dotNetScope._assembly, SymbolTable)); } used_units.Add(_system_unit.scope); return used_units.ToArray(); } public void visit_implementation(SyntaxTree.unit_module _unit_module) { if (_unit_module.initialization_part != null) { var lambdaSearcher = new LambdaSearcher(_unit_module.initialization_part); if (lambdaSearcher.CheckIfContainsLambdas()) { AddError(new LambdasNotAllowedInInitializationPartOfModule(get_location(lambdaSearcher.FoundLambda))); } } if (_unit_module.finalization_part != null) { var lambdaSearcher = new LambdaSearcher(_unit_module.finalization_part); if (lambdaSearcher.CheckIfContainsLambdas()) { AddError(new LambdasNotAllowedInFinalizationPartOfModule(get_location(lambdaSearcher.FoundLambda))); } } //using_list.AddRange(implementation_using_list); /*if (_unit_module.implementation_part != null) { weak_node_test_and_visit(_unit_module.implementation_part.using_namespaces); }*/ SymbolTable.Scope[] used_units = build_referenced_units(ReferencedUnits,false); _compiled_unit.implementation_scope = convertion_data_and_alghoritms.symbol_table.CreateUnitImplementationScope(_compiled_unit.scope, used_units); location loc = null; if (_unit_module.unit_name != null) { loc = get_location(_unit_module.unit_name); } common_namespace_node cnsn = context.create_namespace(_unit_module.unit_name.idunit_name.name + StringConstants.ImplementationSectionNamespaceName, _compiled_unit, _compiled_unit.implementation_scope, loc); //cnsn.scope=_compiled_unit.implementation_scope; if (_unit_module.implementation_part != null) { hard_node_test_and_visit(_unit_module.implementation_part); } //weak_node_test_and_visit(_unit_module.initialization_part); context.enter_code_block_without_bind(); statement_node init_statements = convert_weak(_unit_module.initialization_part); context.leave_code_block(); common_namespace_function_node initialization_function = null; context.check_abstracts_implemented(inherited_from_partials_list); if (init_statements != null) { context.check_labels(context.converted_namespace.labels); //(ssyy) Блокируем поставленные метки, чтобы не допустить переход из finalization-секции //context.block_defined_labels(context.converted_namespace.labels); initialization_function = new common_namespace_function_node(StringConstants.initialization_function_name, null, init_statements.location, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateScope(context.converted_namespace.scope)); initialization_function.function_code = init_statements; cnsn.functions.AddElement(initialization_function); _compiled_unit.main_function = initialization_function; context.apply_special_local_vars(_compiled_unit.main_function); } context.enter_code_block_without_bind(); statement_node final_statements = convert_weak(_unit_module.finalization_part); context.leave_code_block(); common_namespace_function_node finalization_function = null; if (final_statements != null) { context.check_labels(context.converted_namespace.labels); finalization_function = new common_namespace_function_node(StringConstants.finalization_function_name, null, final_statements.location, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateScope(context.converted_namespace.scope)); finalization_function.function_code = final_statements; cnsn.functions.AddElement(finalization_function); _compiled_unit.finalization_method = finalization_function; context.apply_special_local_vars(_compiled_unit.finalization_method); } context.check_all_name_unit_defined(_compiled_unit); } public override void visit(SyntaxTree.implementation_node _implementation_node) { if (_implementation_node.implementation_definitions != null && _implementation_node.implementation_definitions.defs != null) { foreach (var def in _implementation_node.implementation_definitions.defs.Where(d => d is const_definition || d is consts_definitions_list || d is variable_definitions)) { var lambdaSearcher = new LambdaSearcher(def); if (lambdaSearcher.CheckIfContainsLambdas()) { AddError(new LambdasNotAllowedInImplementationOfModuleInInit(get_location(lambdaSearcher.FoundLambda))); } } } weak_node_test_and_visit(_implementation_node.implementation_definitions); } bool in_interface_part = false; public override void visit(SyntaxTree.interface_node _interface_node) { if (_interface_node.interface_definitions != null && _interface_node.interface_definitions.defs != null) { foreach (var def in _interface_node.interface_definitions.defs.Where(d => d is const_definition || d is consts_definitions_list || d is variable_definitions)) { var lambdaSearcher = new LambdaSearcher(def); if (lambdaSearcher.CheckIfContainsLambdas()) { AddError(new LambdasNotAllowedInInterfacePartOfModuleInInit(get_location(lambdaSearcher.FoundLambda))); } } } weak_node_test_and_visit(_interface_node.interface_definitions); } public override void visit(SyntaxTree.typecast_node node) { expression_node en = convert_strong(node.expr); location loc = get_location(node); type_node tp = convert_strong(node.type_def); //ssyy if (en.type.semantic_node_type == semantic_node_type.delegated_method) { try_convert_typed_expression_to_function_call(ref en); } //\ssyy if (!SemanticRulesConstants.IsAsForPointers && (tp.IsPointer || en.type.IsPointer)) { if (node.cast_op == PascalABCCompiler.SyntaxTree.op_typecast.is_op) AddError(loc, "OPERATOR_{0}_CAN_NOT_BE_APPLIED_TO_POINTER_TYPE", StringConstants.is_name); else AddError(loc, "OPERATOR_{0}_CAN_NOT_BE_APPLIED_TO_POINTER_TYPE", StringConstants.as_name); } else if (!(type_table.is_derived(en.type, tp) || type_table.is_derived(tp, en.type) || en.type == tp || en.type == SystemLibrary.SystemLibrary.object_type || en.type.IsInterface || tp.IsInterface || tp.is_generic_parameter || en.type.is_generic_parameter) ) { AddError(loc, "EXPECTED_DERIVED_CLASSES"); } if (en.type.IsSealed && tp.IsInterface && /*!en.type.ImplementingInterfaces.Contains(tp)*/ !convertion_data_and_alghoritms.type_or_base_type_implements_interface(en.type,tp) ) { AddError(loc, "CAN_NOT_CONVERT_TYPE_{0}_TO_INTERFACE_{1}", en.type.PrintableName, tp.PrintableName); } if (node.cast_op == PascalABCCompiler.SyntaxTree.op_typecast.is_op) { is_node isn = new is_node(en, tp, loc); return_value(isn); } else { if (tp.is_generic_parameter && !tp.is_class && !(tp.base_type != null && tp.base_type.is_class && tp.base_type != SystemLibrary.SystemLibrary.object_type) && !(tp.base_type != null && tp.base_type.original_generic != null && tp.base_type.original_generic.is_class)) AddError(get_location(node.type_def), "OPERATOR_AS_CAN_NOT_BE_USED_WITH_GENERIC_PARAMETER_{0}_WITHOUT_CLASS_CONSTRAINT", tp.name); if (tp.is_value_type) AddError(get_location(node.type_def), "OPERATOR_AS_MUST_BE_USED_WITCH_A_REFERENCE_TYPE_VALUETYPE{0}", tp.PrintableName); as_node asn = new as_node(en, tp, loc); return_value(asn); } } public override void visit(SyntaxTree.inherited_method_call _inherited_method_call) { throw new NotSupportedError(get_location(_inherited_method_call)); } public override void visit(SyntaxTree.destructor _destructor) { if (_destructor.name == null) { AddError(get_location(_destructor), "DESTRUCTOR_MUST_HAVE_NAME"); } if (context.converting_block() == block_type.type_block) { if (context.converted_type.IsInterface) { AddError(get_location(_destructor), "DESTRUCTOR_IN_INTERFACE"); } if (!context.converted_type.is_class) { AddError(get_location(_destructor), "DESTRUCTOR_NOT_IN_CLASS"); } } else if (!(context.converting_block() == block_type.namespace_block && _destructor.name.class_name != null)) { AddError(get_location(_destructor), "DESTRUCTOR_NOT_IN_CLASS"); } if (_destructor.parameters != null && _destructor.parameters.params_list.Count > 0) { AddError(get_location(_destructor), "DESTRUCTOR_CANNOT_HAVE_PARAMETERS"); } visit_procedure_header(_destructor); } //ssyy изменил этот метод из-за изменения концепции конструкторов public override void visit(SyntaxTree.constructor _constructor) { if (context.converting_block() == block_type.type_block) { if (context.converted_type.IsInterface) { AddError(new ConstructorInInterface(get_location(_constructor))); } /*if (!context.converted_type.is_class) { throw new ConstructorNotInClass(get_location(_constructor)); }*/ } else if (!(context.converting_block() == block_type.namespace_block && _constructor.name != null && _constructor.name.class_name != null)) { AddError(get_location(_constructor), "CONSTRUCTOR_NOT_IN_CLASS"); } convertion_data_and_alghoritms.check_node_parser_error(_constructor.name); if (_constructor.name == null) { SyntaxTree.ident name = new SyntaxTree.ident(default_constructor_name); _constructor.name = new PascalABCCompiler.SyntaxTree.method_name(null, null, name, null); _constructor.name.source_context = _constructor.name.meth_name.source_context = _constructor.source_context; } if (_constructor.name.meth_name.name.ToLower() != default_constructor_name.ToLower()) AddError(get_location(_constructor.name), "CONSTRUCTOR_CAN_HAVE_ONLY_{0}_NAME", default_constructor_name); if ((_constructor.name.class_name == null) && (context.converting_block() != block_type.type_block)) { AddError(get_location(_constructor.name), "ONLY_CONSTRUCTOR_OF_TYPE_ALLOWED"); } foreach (SyntaxTree.procedure_attribute att in _constructor.proc_attributes.proc_attributes) { if (att.attribute_type == SyntaxTree.proc_attribute.attr_virtual) { AddError(get_location(att), "CONSTRUCTOR_CAN_NOT_BE_VIRTUAL"); } else if (att.attribute_type == SyntaxTree.proc_attribute.attr_override) { AddError(get_location(att), "CONSTRUCTOR_CAN_NOT_BE_OVERRIDE"); } else if (att.attribute_type == SyntaxTree.proc_attribute.attr_abstract) { AddError(get_location(att), "CONSTRUCTOR_CANNOT_BE_ABSTRACT"); } } if (_constructor.class_keyword) { SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static); pa.source_context = _constructor.source_context; _constructor.proc_attributes.proc_attributes.Add(pa); } foreach (SyntaxTree.procedure_attribute att in _constructor.proc_attributes.proc_attributes) { if (att.attribute_type == SyntaxTree.proc_attribute.attr_static) { //Это статический конструктор if (_constructor.parameters != null) { AddError(get_location(_constructor.name), "STATIC_CONSTRUCTOR_MUST_BE_PARAMETERLESS"); } _constructor.name.meth_name.name = StringConstants.static_ctor_prefix + _constructor.name.meth_name.name; visit_procedure_header(_constructor); if (context.top_function != null) { common_method_node static_constr = context.top_function as common_method_node; static_constr.is_constructor = true; if (/*context.converted_type.IsPartial && */context.converted_type.static_constr != null)//remove auto generated static constructor from partial class context.converted_type.methods.RemoveElement(context.converted_type.static_constr); static_constr.cont_type.static_constr = context.top_function as common_method_node; } return; } } if (context.converting_block() == block_type.type_block) { //Нужно для генерации унаследованных конструкторов context.converted_type.has_user_defined_constructor = true; //Нужно для генерации конструктора по умолчанию if (_constructor.parameters == null || _constructor.parameters.params_list[0].inital_value != null) { context.converted_type.has_default_constructor = true; } } visit_procedure_header(_constructor); if (context.top_function == null) { return; } common_method_node cmn = context.top_function as common_method_node; if (cmn == null) { throw new CompilerInternalError("Constructor is not common_method_node."); } context.allow_inherited_ctor_call = true; cmn.is_constructor = true; if (cmn.cont_type.is_value_type && cmn.parameters.Count == 0 && (cmn.field_access_level == SemanticTree.field_access_level.fal_private || cmn.field_access_level == SemanticTree.field_access_level.fal_protected)) AddError(cmn.loc, "NON_PUBLIC_RECORD_CONSTRUCTORS_NOT_ALLOWED"); cmn.return_value_type = context.converted_type; } public override void visit(SyntaxTree.file_type_definition _file_type_definition) { throw new NotSupportedError(get_location(_file_type_definition)); } public override void visit(SyntaxTree.nil_const _nil_const) { return_value(new null_const_node(null_type_node.get_type_node(), get_location(_nil_const))); } public override void visit(SyntaxTree.class_predefinition _class_predefinition) { throw new NotSupportedError(get_location(_class_predefinition)); } private bool statement_expected = false; private bool procedure_wait = false; public override void visit(SyntaxTree.procedure_call _procedure_call) { procedure_wait = true; SyntaxTree.method_call mc = null; mc = _procedure_call.func_name as SyntaxTree.method_call; if (mc == null) { SyntaxTree.ident id = _procedure_call.func_name as SyntaxTree.ident; if (id != null) { mc = new SyntaxTree.method_call(); mc.dereferencing_value = id; // дело в том, что это присваивание перенаправляет Parent на method_call, которого нет в синтаксическом дереве. id.Parent = _procedure_call; // fix #891 вернули Parent назад //DarkStar Add //Добавил т.к. нужно для генерации отладочной инфы mc.source_context = id.source_context; } else { SyntaxTree.addressed_value adrv = _procedure_call.func_name as SyntaxTree.addressed_value; if (adrv != null) { mc = new SyntaxTree.method_call(); mc.dereferencing_value = adrv; adrv.Parent = _procedure_call; // fix #891 //DarkStar Add //Добавил т.к. нужно для генерации отладочной инфы mc.source_context = adrv.source_context; } else { AddError(get_location(_procedure_call), "EXPECTED_DELEGATE"); } } } //statement_node sn=convert_strong(_procedure_call.func_name); statement_node sn = convert_strong(mc); //проверяем на случай вызова типа real(a) ... if (/*((sn is base_function_call) && (sn as base_function_call).IsExplicitConversion) || (sn is SemanticTree.IReferenceNode) || (sn is SemanticTree.IGetAddrNode) || (sn is null_const_node) || (sn is simple_array_indexing) || (sn is basic_function_call) || (sn is constant_node) || (sn is class_field_reference)*/ !(sn is base_function_call) && !(sn is exit_procedure) && !(sn is while_break_node) && !(sn is while_continue_node) && !(sn is repeat_break_node) && !(sn is repeat_continue_node) && !(sn is for_break_node) && !(sn is for_continue_node) && !(sn is foreach_break_node) && !(sn is foreach_continue_node) ) AddError(get_location(_procedure_call), "STATEMENT_EXPECTED"); if (sn is base_function_call bfc && bfc.IsExplicitConversion) AddError(get_location(_procedure_call), "STATEMENT_EXPECTED"); return_value(sn); //_procedure_call.func_name.visit(this); } public override void visit(SyntaxTree.variant_record_type _variant_record_type) { throw new NotSupportedError(get_location(_variant_record_type)); } public override void visit(SyntaxTree.variant_types _variant_types) { throw new NotSupportedError(get_location(_variant_types)); } public override void visit(SyntaxTree.variant_type _variant_type) { throw new NotSupportedError(get_location(_variant_type)); } public override void visit(SyntaxTree.variant_list _variant_list) { throw new NotSupportedError(get_location(_variant_list)); } public override void visit(SyntaxTree.variant _variant) { throw new NotSupportedError(get_location(_variant)); } public override void visit(SyntaxTree.string_num_definition node) { location loc = get_location(node); //if (SystemLibrary.SystemLibInitializer.ShortStringType.NotFound) // throw new NotSupportedError(loc); type_node tn = find_type(node.name.name, loc); if (!(tn == SystemLibrary.SystemLibrary.string_type)) AddError(new ExpectedType(SystemLibrary.SystemLibrary.string_type.name, loc)); constant_node cn = convert_strong_to_constant_node(node.num_of_symbols, SystemLibrary.SystemLibrary.integer_type); int length = (cn as int_const_node).constant_value; if (length < 1 || length > 255) AddError(loc, "TYPE_CAN_NOT_HAVE_THIS_SIZE_{0}", SystemLibrary.SystemLibrary.string_type.name); return_value(context.create_short_string_type(length, loc)); } public override void visit(SyntaxTree.literal_const_line _literal_const_line) { //DarkStar Add string s = ""; SyntaxTree.string_const strc; SyntaxTree.sharp_char_const sharpcharconst; SyntaxTree.char_const charconst; SyntaxTree.syntax_tree_node tnf = _literal_const_line.literals[0], tnl = null; for (int i = 0; i < _literal_const_line.literals.Count; i++) { if ((strc = _literal_const_line.literals[i] as SyntaxTree.string_const) != null) s = s + strc.Value; else if ((sharpcharconst = _literal_const_line.literals[i] as SyntaxTree.sharp_char_const) != null) s = s + Convert.ToChar(sharpcharconst.char_num); else if ((charconst = _literal_const_line.literals[i] as SyntaxTree.char_const) != null) s = s + charconst.cconst; if (i == _literal_const_line.literals.Count - 1) tnl = _literal_const_line.literals[i]; } expression_node en = new string_const_node(s, new location(tnf.source_context.begin_position.line_num, tnf.source_context.begin_position.column_num, tnl.source_context.end_position.line_num, tnl.source_context.end_position.column_num, current_document)); return_value(en); } public override void visit(SyntaxTree.sharp_char_const _sharp_char_const) { return_value(new char_const_node(Convert.ToChar(_sharp_char_const.char_num), get_location(_sharp_char_const))); } public override void visit(SyntaxTree.raise_statement _raise_statement) { throw new NotSupportedError(get_location(_raise_statement)); } public override void visit(SyntaxTree.char_const _char_const) { expression_node en = new char_const_node(_char_const.cconst, get_location(_char_const)); return_value(en); } private bool check_if_has_enum_consts(SyntaxTree.enum_type_definition _enum_type_definition) { bool has_val = false; foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators) { if (en.value != null) { has_val = true; } else if (has_val) AddError(get_location(en), "ALL_ENUM_CONSTANTS_NEEDED"); } return has_val; } public override void visit(SyntaxTree.enum_type_definition _enum_type_definition) { //SSM 15/01/16 - реализация (integer,integer) // Если кто-то - не named_type_reference с одним ident, то надо идти по ветке типов - это не м.б.перечисление bool is_tuple_type = false; foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators) { if (!((en.name is named_type_reference) && (en.name as named_type_reference).names.Count()==1)) { is_tuple_type = true; break; } } bool is_enum = false; if (!is_tuple_type) // Значит, все - идентификаторы и сказать пока ничего нельзя foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators) { SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent; var si = context.CurrentScope.Find(id.name); if ((si==null) || !(si.FirstOrDefault().sym_info is type_node)) { if (si != null && si.FirstOrDefault().sym_info is constant_definition_node) { constant_definition_node ncd = si.FirstOrDefault().sym_info as constant_definition_node; if (_enum_type_definition.source_context != null && ncd.type.location != null && ncd.type.location.begin_line_num == _enum_type_definition.source_context.begin_position.line_num && ncd.type.location.begin_column_num == _enum_type_definition.source_context.begin_position.column_num && ncd.type.location.file_name == _enum_type_definition.source_context.FileName) { return_value(ncd.type); return; } } is_enum = true; break; } } if (!is_enum) // Значит, это определение типа { var lt = new List(); for (var iii=0; iii<_enum_type_definition.enumerators.enumerators.Count(); iii++) { var en = _enum_type_definition.enumerators.enumerators[iii]; var name = en.name; if (en.value != null) AddError(get_location(en.value), "TUPLE_TYPE_ERROR"); lt.Add(name); } if (lt.Count > 7) AddError(get_location(_enum_type_definition), "TUPLE_TYPE_ELEMENTS_COUNT_MUST_BE_LESSEQUAL_7"); var l = new List(); l.Add(new ident("?System")); // System не должно быть найдено в пользовательском коде l.Add(new ident("Tuple")); var tp = new template_param_list(lt); // значит, это Tuple - создать его, обойти и выйти var ttr = new SyntaxTree.template_type_reference(new named_type_reference(l), tp, _enum_type_definition.source_context); visit(ttr); return; } //end SSM // Если мы здесь - значит, это перечислимый тип //throw new NotSupportedError(get_location(_enum_type_definition)); //ivan added int num = 0; List cnsts = new List(); check_if_has_enum_consts(_enum_type_definition); foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators) { SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent; // это - точно идентификаторы constant_definition_node cdn = context.add_const_definition(id.name, get_location(id)); if (en.value == null) cdn.const_value = new enum_const_node(num++, null, get_location(id)); else { constant_node cn = convert_strong_to_constant_node(en.value, SystemLibrary.SystemLibrary.integer_type); if (cn is basic_function_call_as_constant bfcc && bfcc.method_call.function_node.compile_time_executor != null) { cn = convert_strong_to_constant_node(bfcc.method_call.function_node.compile_time_executor(bfcc.location, bfcc.method_call.parameters.ToArray()), SystemLibrary.SystemLibrary.integer_type); } check_for_strong_constant(cn,get_location(en.value)); cdn.const_value = new enum_const_node((cn as int_const_node).constant_value,null,get_location(id)); } cnsts.Add(cdn); } common_type_node ctn = context.create_enum_type(null, get_location(_enum_type_definition), generatedNamesManager); //_enum_type_definition.values num = 0; foreach (constant_definition_node cdn in cnsts) { cdn.const_value.type = ctn; } int i = 0; foreach (SyntaxTree.enumerator en in _enum_type_definition.enumerators.enumerators) { SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent; constant_definition_node cdn = context.add_const_definition(id.name, get_location(id)); if (en.value == null) cdn.const_value = new enum_const_node(num++, null, get_location(id)); else { cdn.const_value = cnsts[i].const_value; } cdn.const_value.type = ctn; i++; } internal_interface ii = SystemLibrary.SystemLibrary.integer_type.get_internal_interface(internal_interface_kind.ordinal_interface); ordinal_type_interface oti_old = (ordinal_type_interface)ii; enum_const_node lower_value = new enum_const_node(0, ctn, ctn.loc); enum_const_node upper_value = new enum_const_node(ctn.const_defs.Count - 1, ctn, ctn.loc); ordinal_type_interface oti_new = new ordinal_type_interface(oti_old.inc_method, oti_old.dec_method, oti_old.inc_value_method, oti_old.dec_value_method, oti_old.lower_eq_method, oti_old.greater_eq_method, oti_old.lower_method, oti_old.greater_method, lower_value, upper_value, oti_old.value_to_int, oti_old.ordinal_type_to_int); ctn.add_internal_interface(oti_new); //foreach (constant_definition_node cdn in cnsts) // cdn.const_value.type = ctn; //context.leave_block(); context.leave_record(); return_value(ctn); } public override void visit(SyntaxTree.record_type _record_type) { } public override void visit(SyntaxTree.record_const node) { if (is_typed_const_def) { record_constant rc = new record_constant(node.rec_consts, get_location(node)); rc.SetType(new RecordConstType(rc.location)); return_value(rc); } else { record_initializer ri = new record_initializer(node.rec_consts, get_location(node)); ri.type = new RecordConstType(ri.location); return_value(ri); } } public override void visit(SyntaxTree.record_const_definition _record_const_definition) { throw new NotSupportedError(get_location(_record_const_definition)); } public override void visit(SyntaxTree.set_type_definition _set_type_definition) { // PABCSystem.NewSet // var ntr = new named_type_reference(new List { new ident("PABCSystem"), new ident("NewSet") }); type_node el_type = convert_strong(_set_type_definition.of_type); if (el_type.type_special_kind == SemanticTree.type_special_kind.diap_type) { if (el_type is common_type_node ctn) el_type = ctn.base_type; } /* Не буду это делать! * if (el_type == SystemLibrary.SystemLibrary.byte_type || el_type == SystemLibrary.SystemLibrary.sbyte_type || el_type == SystemLibrary.SystemLibrary.short_type || el_type == SystemLibrary.SystemLibrary.ushort_type ) el_type = SystemLibrary.SystemLibrary.integer_type; */ var el_sem_type = new SyntaxTree.semantic_type_node(el_type, _set_type_definition.of_type.source_context); var tpr = new template_param_list(el_sem_type); var ttr = new SyntaxTree.template_type_reference(ntr, tpr); ProcessNode(ttr); /*if (SystemLibrary.SystemLibInitializer.TypedSetType == null || SystemLibrary.SystemLibInitializer.CreateSetProcedure == null) AddError(new NotSupportedError(get_location(_set_type_definition))); type_node el_type = convert_strong(_set_type_definition.of_type); if (el_type.IsPointer) AddError(get_location(_set_type_definition.of_type), "POINTERS_IN_SETS_NOT_ALLOWED"); //if (el_type == SystemLibrary.SystemLibrary.void_type) // AddError(new VoidNotValid(get_location(_set_type_definition.of_type))); check_for_type_allowed(el_type, get_location(_set_type_definition.of_type)); check_using_static_class(el_type, get_location(_set_type_definition.of_type)); return_value(context.create_set_type(el_type, get_location(_set_type_definition)));*/ } public override void visit(SyntaxTree.known_type_definition _known_type_definition) { throw new NotSupportedError(get_location(_known_type_definition)); } public override void visit(SyntaxTree.default_indexer_property_node _default_indexer_property_node) { throw new NotSupportedError(get_location(_default_indexer_property_node)); } public override void visit(SyntaxTree.class_definition _class_definition) { if (_class_definition.keyword == class_keyword.Record && _class_definition.Parent is var_def_statement) // безымянная запись { // SSM 27.02.12 - всё это перенес в синтаксический визитор UnnamedRecordsCheckVisitor /*if (_class_definition.class_parents != null && _class_definition.class_parents.Count>0) AddError(new SimpleSemanticError(get_location(_class_definition), "UNNAMED_RECORD_CANNOT_IMPLEMENT_INTERFACE")); var pds = _class_definition.DescendantNodes().OfType(); if (pds.Count() > 0) AddError(new SimpleSemanticError(get_location(pds.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_METHODS")); var sps = _class_definition.DescendantNodes().OfType(); if (sps.Count() > 0) AddError(new SimpleSemanticError(get_location(sps.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_PROPERTIES")); var cds = _class_definition.DescendantNodes().OfType(); if (cds.Count() > 0) AddError(new SimpleSemanticError(get_location(cds.First()), "UNNAMED_RECORD_CANNOT_CONTAIN_CONSTRUCTORS")); if (_class_definition.body.class_def_blocks.First().access_mod.access_level != access_modifer.public_modifer) { var f = _class_definition.body.class_def_blocks.First(); var loc = get_location(f); if (loc == null) loc = get_location(_class_definition); AddError(new SimpleSemanticError(loc, "UNNAMED_RECORD_CAN_CONTAIN_ONLY_ONE_PUBLIC_VISIBILITY_SECTION")); } if (_class_definition.body.class_def_blocks.Count > 1) { var el1 = _class_definition.body.class_def_blocks.ElementAt(1); var loc = get_location(el1.access_mod); if (loc == null) loc = get_location(_class_definition); AddError(new SimpleSemanticError(loc, "UNNAMED_RECORD_CANNOT_CONTAIN_SEVERAL_VISIBILITY_SECTIONS")); }*/ } if (_class_definition.attribute != class_attribute.None && _class_definition.body == null) AddError(new SimpleSemanticError(get_location(_class_definition), "CLASS_ATTRIBUTE_NOT_ALLOWED_IN_CLASS_PREDEFINTIONS")); if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed) { context.converted_type.SetIsSealed(true); if (_class_definition.keyword == SyntaxTree.class_keyword.Interface || _class_definition.keyword == SyntaxTree.class_keyword.TemplateInterface) AddError(new SimpleSemanticError(get_location(_class_definition), "INTERFACE_CANNOT_BE_SEALED")); } if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Auto) == SyntaxTree.class_attribute.Auto) { if (_class_definition.keyword == SyntaxTree.class_keyword.Interface || _class_definition.keyword == SyntaxTree.class_keyword.TemplateInterface) AddError(new SimpleSemanticError(get_location(_class_definition), "INTERFACE_CANNOT_BE_AUTO")); } if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Abstract) == SyntaxTree.class_attribute.Abstract && (_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed) AddError(get_location(_class_definition), "ABSTRACT_CLASS_CANNOT_BE_SEALED"); if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Abstract) == SyntaxTree.class_attribute.Abstract) { if (_class_definition.keyword != SyntaxTree.class_keyword.Class) AddError(get_location(_class_definition), "ATTRIBUTE_{0}_NOT_ALLOWED", "abstract"); context.converted_type.SetIsAbstract(true, null); // Причина null, в ошибке и так будет видно что abstract и sealed стоят рядом } if ((_class_definition.attribute & class_attribute.Static) == class_attribute.Static) { if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Abstract) == SyntaxTree.class_attribute.Abstract) AddError(get_location(_class_definition), "ATTRIBUTE_{0}_NOT_ALLOWED", "abstract"); if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Sealed) == SyntaxTree.class_attribute.Sealed) AddError(get_location(_class_definition), "ATTRIBUTE_{0}_NOT_ALLOWED", "sealed"); if ((_class_definition.attribute & PascalABCCompiler.SyntaxTree.class_attribute.Auto) == SyntaxTree.class_attribute.Auto) AddError(get_location(_class_definition), "ATTRIBUTE_{0}_NOT_ALLOWED", "auto"); if (_class_definition.keyword != SyntaxTree.class_keyword.Class) AddError(get_location(_class_definition), "ONLY_CLASS_CAN_BE_STATIC"); if (context.converted_type.is_generic_type_definition) AddError(get_location(_class_definition), "STATIC_CLASS_CANNOT_BE_GENERIC"); context.converted_type.SetIsStatic(true); context.converted_type.SetIsSealed(true); context.converted_type.SetIsAbstract(true, null); // Причина null, потому что причины нет, класс статический а не абстрактный } common_type_node converted_type; //TODO Выглядит странно - в каком это случае семантический узел записи создаётся с задержкой? if (_class_definition.keyword==PascalABCCompiler.SyntaxTree.class_keyword.Record) { if (_record_created) { _record_created = false; converted_type = context.converted_type; } else { converted_type = context.create_record_type(get_location(_class_definition), record_type_name, generatedNamesManager); if (record_is_generic) { context.create_generic_indicator(converted_type); visit_generic_params(converted_type, _class_definition.template_args.idents); } else { if (_class_definition.template_args != null && _class_definition.template_args.idents != null) { AddError(get_location(_class_definition.template_args), "GENERIC_TYPE_NOT_ALLOWED_HERE"); } } visit_where_list(_class_definition.where_section); } } else converted_type = context.converted_type; // Для записей базовый класс устанавливает на SemanticRules.StructBaseType ещё в context.create_record_type var need_set_base = _class_definition.keyword != PascalABCCompiler.SyntaxTree.class_keyword.Record; // Ограничение шаблонов предка и интерфейсов нельзя проверять // на первом проходе, когда ещё не все предки добавлены в converted_type var need_recheck_where = new List(); if (_class_definition.class_parents != null) { need_recheck_where.Capacity = _class_definition.class_parents.Count; // В случае partial классов можно (и желательно) указывать интерфейсы, которые уже были в предыдущем описании // Поэтому проверять нужно только уникальное среди списка интерфейсов в этом описании var curr_def_interfaces = new List(need_recheck_where.Capacity); // Отключаем проверки where для случая // t1 = ...(t0) context.skip_check_where_sections = true; for (int i = 0; i < _class_definition.class_parents.Count; i++) { var syntax_tn = _class_definition.class_parents[i]; location loc = get_location(syntax_tn); var tn = (type_node)ret.visit(syntax_tn); if (tn.is_generic_type_definition || tn.is_generic_type_instance) need_recheck_where.Add(syntax_tn); if ((tn.original_generic??tn).ForwardDeclarationOnly) AddError(loc, "FORWARD_DECLARATION_{0}_AS_BASE_TYPE", tn.PrintableName); if (tn.is_generic_parameter) AddError(loc, "CAN_NOT_INHERIT_FROM_GENERIC_PARAMETER"); for (var curr = tn; curr!=null; curr=curr.base_type) { curr = curr.original_generic ?? curr; if (curr == converted_type) AddError(loc, "TYPE_{0}_INHERITS_SELF", converted_type.PrintableName); } // Если первый тип в списке - класс-предок if (i==0 && !tn.IsInterface && _class_definition.keyword==PascalABCCompiler.SyntaxTree.class_keyword.Class) { if (tn.IsSealed) AddError(loc, "PARENT_TYPE_IS_SEALED{0}", tn.PrintableName); if (tn == SystemLibrary.SystemLibrary.value_type) AddError(loc, "CAN_NOT_INHERIT_FROM_VALUE_TYPE"); if (tn.IsPointer) AddError(loc, "CAN_NOT_INHERIT_FROM_POINTER"); if (tn.IsDelegate) AddError(loc, "CAN_NOT_INHERIT_FROM_FUNCTION_TYPE"); if (tn == SystemLibrary.SystemLibrary.delegate_base_type || tn == SystemLibrary.SystemLibrary.system_delegate_type) AddError(loc, "CAN_NOT_INHERIT_FROM_DELEGATE_TYPE"); converted_type.SetBaseType(tn); need_set_base = false; if (tn is common_type_node ctn && ctn.IsPartial) inherited_from_partials_list.Add(converted_type); continue; } // type_table.AddInterface проверяет что tn это интерфейс type_table.AddInterface(converted_type, tn, loc); if (curr_def_interfaces.Contains(tn)) AddError(loc, "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", tn.PrintableName); else curr_def_interfaces.Add(tn); } context.skip_check_where_sections = false; } if (need_set_base) { var bt = (converted_type.IsPartial ? converted_type.base_type : null) ?? SemanticRulesConstants.ClassBaseType; converted_type.SetBaseType(bt); } foreach (generic_type_instance_info gti in generic_convertions.get_type_instances(converted_type)) { //TODO Было для #2524, но с generic_convertions.determine_type оно не нужно //if (gti.pseudo_instance.base_type != null && gti.pseudo_instance.base_type.is_generic_type_instance && converted_type.IsPartial) continue; // "t1 = class(i1)" => "t1" реализует "i1" а не "i1" gti.pseudo_instance.SetBaseType(generic_convertions.determine_type(converted_type.base_type, gti.param_types, false)); // Сбрасываем на null, чтобы их вычислило заново, если понадобится gti.pseudo_instance.SetImplementingInterfaces(null); /** gti.pseudo_instance.ImplementingInterfaces.Clear(); foreach (type_node t in converted_type.ImplementingInterfaces) gti.pseudo_instance.ImplementingInterfaces.Add(generic_convertions.determine_type(t, gti.param_types, false)); /**/ } // Проверяем секции where предка/интерфейсов // В самом конце, когда converted_type // уже содержит всю информацию о предке и интерфейсах foreach (var syntax_tn in need_recheck_where) ret.visit(syntax_tn); switch (_class_definition.keyword) { case PascalABCCompiler.SyntaxTree.class_keyword.Class: //if (converted_type.IsPartial) // generic_convertions.remove_type_instances(converted_type); if (converted_type.is_value || converted_type.IsInterface) AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", converted_type.name); converted_type.is_class = true; if (_class_definition.body == null && (_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0)) { if (converted_type.ForwardDeclarationOnly) AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition))); converted_type.ForwardDeclarationOnly = true; context.types_predefined.Add(converted_type); } else { converted_type.ForwardDeclarationOnly = false; if (_class_definition.body == null) { generate_inherit_constructors(); if (!converted_type.has_default_constructor) { generate_default_constructor(); } } if (_class_definition.IsAutoClass()) { // Если снова возникнет ошибка с предками в автоклассах, то не раскомментировать эти строки, а подумать, как разрешить //if (_class_definition.class_parents!=null) // AddError(new AutoClassMustNotHaveParents(get_location(_class_definition))); // добавление членов автоклассов. Не забыть сделать, что от автоклассов нельзя наследовать // Это спорный вопрос. С другой стороны от автоклассов хочется наследовать var cp = _class_definition.class_parents; if (cp != null) foreach (var c in cp.types) { var ff = convert_strong(c); if (!ff.IsInterface) { if (ff is common_type_node ctn) { // разрешить также наследовать автоклассы от классов без полей if (ctn.fields.Count == 0) continue; } AddError(new AutoClassMustNotHaveParentsWithFields(get_location(_class_definition))); } } List names = new List(); List types = new List(); SyntaxTreeBuilder.AddMembersForAutoClass(_class_definition,ref names,ref types); //if (names.Select(s => s.name.ToLower()).Distinct().Count() != names.Count) // Отдельный цикл по синт поддереву для вылавливания events foreach (var l in _class_definition.body.class_def_blocks) { foreach (var m in l.members) { var mm = m as var_def_statement; if (mm != null && mm.is_event) AddError(get_location(mm), "AUTO_CLASS_MUST_NOT_HAVE_EVENTS"); } } for (var i = 0; i < types.Count; i++) { type_node tn = convert_strong(types[i]); if (tn.IsEnum && types[i] is enum_type_definition) AddError(get_location(types[i]), "AUTO_CLASS_MUST_NOT_HAVE_UNNAMED_ENUMS"); if (tn.IsPointer) AddError(get_location(types[i]), "AUTO_CLASS_MUST_NOT_HAVE_POINTERS"); } if (_class_definition.body != null) foreach (class_members cl_mem in _class_definition.body.class_def_blocks) { foreach (declaration decl in cl_mem.members) { if (decl is var_def_statement) { type_definition type = (decl as var_def_statement).vars_type; SyntaxTree.array_type arr = type as SyntaxTree.array_type; if (type is SyntaxTree.class_definition || (arr != null && arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null)) { AddError(get_location(type), "STRUCT_TYPE_DEFINITION_IN_AUTO_CLASS"); } } } } } //if (!SemanticRules.OrderIndependedNames) weak_node_test_and_visit(_class_definition.body); } context.leave_block(); // Обязательно после context.leave_block, потому что там неявно-абстрактные методы помечают свой IsAbstract if (converted_type.IsSealed && converted_type.IsAbstract && !converted_type.IsStatic) { if (converted_type.AbstractReason == null) AddError(get_location(_class_definition), "ABSTRACT_CLASS_CANNOT_BE_SEALED"); else AddError(get_location(_class_definition), converted_type.AbstractReason.Explanation, converted_type.name, converted_type.AbstractReason.ObjName); } break; case PascalABCCompiler.SyntaxTree.class_keyword.Record: if (context.CurrentScope is SymbolTable.BlockScope) { AddError(get_location(_class_definition), "RECORD_CANNOT_BE_DECLARED_IN_BLOCK"); converted_type.internal_is_value = true; context.leave_record(); return_value(converted_type); return; } // "PMyRec = ^MyRec" перед описанием "MyRec" CheckWaitedRefTypes(converted_type); record_type_name = null; record_is_generic = false; converted_type.internal_is_value = true; if (_class_definition.body == null && (_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0)) { if (converted_type.ForwardDeclarationOnly) AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition))); context.types_predefined.Add(converted_type); converted_type.ForwardDeclarationOnly = true; } else { converted_type.ForwardDeclarationOnly = false; weak_node_test_and_visit(_class_definition.body); } /*if (_class_definition.body != null) hard_node_test_and_visit(_class_definition.body); else { converted_type.ForwardDeclarationOnly = true; }*/ /*if (_class_definition.body != null) foreach (SyntaxTree.var_def_statement var in (_class_definition.body.class_def_blocks[0].members)) { hard_node_test_and_visit(var); }*/ context.leave_record(); return_value(converted_type); break; //ssyy owns case PascalABCCompiler.SyntaxTree.class_keyword.Interface: if (converted_type.is_value || !converted_type.IsInterface) { AddError(get_location(_class_definition), "FORWARD_DECLARATION_OF_{0}_MISMATCH_DECLARATION", converted_type.name); } if (SemanticRulesConstants.GenerateNativeCode) converted_type.SetBaseType(SemanticRulesConstants.ClassBaseType); else converted_type.SetBaseType(SystemLibrary.SystemLibrary.object_type); converted_type.IsInterface = true; converted_type.is_class = true; InitInterfaceScope(converted_type); //if (_class_definition.body == null) //{ //throw new NotSupportedError(get_location(_class_definition)); // throw new InterfaceForwardDeclaration(get_location(_class_definition)); //} if (_class_definition.body == null && (_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0)) { if (converted_type.ForwardDeclarationOnly) { AddError(new NameRedefinition(converted_type.name, converted_type.Location, get_location(_class_definition))); } context.types_predefined.Add(converted_type); converted_type.ForwardDeclarationOnly = true; } else { converted_type.ForwardDeclarationOnly = false; weak_node_test_and_visit(_class_definition.body); } //hard_node_test_and_visit(_class_definition.body); context.leave_block(); break; //\ssyy owns default: throw new NotSupportedError(get_location(_class_definition)); } } private void InitInterfaceScope(common_type_node ctn) { List interf_scopes = new List(ctn.ImplementingInterfaces.Count); foreach (type_node tnode in ctn.ImplementingInterfaces) { interf_scopes.Add(tnode.Scope); } (ctn.Scope as SymbolTable.InterfaceScope).TopInterfaceScopeArray = interf_scopes.ToArray(); } private void InitInterfaceScope(common_type_node ctn, List interfaces) { List interf_scopes = new List(interfaces.Count); foreach (type_node tnode in interfaces) { interf_scopes.Add(tnode.Scope); } (ctn.Scope as SymbolTable.InterfaceScope).TopInterfaceScopeArray = interf_scopes.ToArray(); } private void visit_function_realizations(SyntaxTree.declarations _decls) { foreach (SyntaxTree.declaration sd in _decls.defs) { common_namespace_function_node cnfn = context.get_method_to_realize(sd) as common_namespace_function_node; if (cnfn != null) { context.push_function(cnfn); if ((sd as SyntaxTree.procedure_definition).proc_body != null) { hard_node_test_and_visit((sd as SyntaxTree.procedure_definition).proc_body); add_clip_for_set(context.top_function); context.leave_block(); } } } } private void visit_class_member_realizations(SyntaxTree.class_body_list _class_body) { if (context.converted_type.internal_is_value) { context.add_equal_operator_if_need(); context.add_notequal_operator_if_need(); } foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks) { foreach (SyntaxTree.declaration sd in clmem.members) { common_method_node cmn = context.get_method_to_realize(sd) as common_method_node; if (cmn != null) { // frninja 20/05/16 - ставим флаг is_yield_helper if (sd is SyntaxTree.procedure_definition) { cmn.is_yield_helper = (sd as SyntaxTree.procedure_definition).proc_header.is_yield_helper; } // end frninja context.push_function(cmn); if (!cmn.IsStatic) { type_node self_type = cmn.cont_type; if (cmn.cont_type.is_generic_type_definition) self_type = cmn.cont_type.get_instance(cmn.cont_type.generic_params.ConvertAll(o => (type_node)o));// new generic_instance_type_node(self_type, self_type.generic_params.ConvertAll(o => (type_node)o), self_type.base_type, self_type.name, self_type.type_access_level, self_type.comprehensive_namespace, self_type.loc); if (!(cmn.is_constructor && cmn.cont_type.name.StartsWith("<>local_variables_class"))) { local_variable lv = new local_variable(StringConstants.self_word, self_type, cmn, null); cmn.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(lv)); cmn.self_variable = lv; } else { local_variable lv = new local_variable(StringConstants.self_word+"$", self_type, cmn, null); cmn.scope.AddSymbol(StringConstants.self_word+"$", new SymbolInfo(lv)); cmn.self_variable = lv; } } if ((sd as SyntaxTree.procedure_definition).proc_body != null) { hard_node_test_and_visit((sd as SyntaxTree.procedure_definition).proc_body); add_clip_for_set(context.top_function); context.leave_block(); } } } } context.clear_member_bindings(); } public override void visit(SyntaxTree.class_body_list _class_body) { foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks) { //hard_node_test_and_visit(clmem); weak_node_test_and_visit(clmem); } if (SemanticRulesConstants.OrderIndependedMethodNames) { if (!context.converted_type.is_value && !context.converted_type.IsInterface) { generate_inherit_constructors(); } if (!context.converted_type.IsInterface && !context.converted_type.has_default_constructor) { generate_default_constructor(); } if (!context.namespace_converted || context.converted_type.name.IndexOf("<>") != -1) visit_class_member_realizations(_class_body); } if (!SemanticRulesConstants.OrderIndependedMethodNames) { if (!context.converted_type.is_value && !context.converted_type.IsInterface) { generate_inherit_constructors(); } if (!context.converted_type.IsInterface && !context.converted_type.has_default_constructor) { generate_default_constructor(); } } } private bool disable_order_independ; //ssyy public void generate_default_constructor() { if (context.converted_type.IsStatic) return; if (!context.converted_type.is_value) { if (!generic_convertions.type_has_default_ctor(context.converted_type.base_type, true)) { //У предка нет конструктора по умолчанию, //невозможно сгенерировать конструктор по умолчанию. AddError(context.converted_type.loc, "NO_DEFAULT_CONSTRUCTOR_INT_TYPE_{0}", context.converted_type.base_type.name); return; } } SyntaxTree.class_members clmem = new SyntaxTree.class_members(); if (context.converted_type.has_user_defined_constructor && !context.converted_type.is_value_type) { clmem.access_mod = new SyntaxTree.access_modifer_node(SyntaxTree.access_modifer.protected_modifer); } else { clmem.access_mod = new SyntaxTree.access_modifer_node(SyntaxTree.access_modifer.public_modifer); } SyntaxTree.procedure_attributes_list pal = new PascalABCCompiler.SyntaxTree.procedure_attributes_list(); //pal.proc_attributes.Add(new PascalABCCompiler.SyntaxTree.procedure_attribute(SyntaxTree.proc_attribute.attr_overload)); attr_overload - убрал отовсюду! ССМ SyntaxTree.constructor constr = new PascalABCCompiler.SyntaxTree.constructor(); constr.name = new SyntaxTree.method_name(null, null, new PascalABCCompiler.SyntaxTree.ident(default_constructor_name), null); constr.proc_attributes = pal; SyntaxTree.block bl = new SyntaxTree.block(); bl.program_code = new SyntaxTree.statement_list(); bl.program_code.left_logical_bracket = new SyntaxTree.token_info("begin"); bl.program_code.right_logical_bracket = new SyntaxTree.token_info("end"); clmem.members.Add(new SyntaxTree.procedure_definition(constr, bl)); disable_order_independ = true; clmem.visit(this); disable_order_independ = false; } //\ssyy public override void visit(SyntaxTree.access_modifer_node _access_modifer_node) { //ssyy if (context.converted_type != null && context.converted_type.IsInterface) { if (_access_modifer_node.access_level == SyntaxTree.access_modifer.none) { context.set_field_access_level(SemanticTree.field_access_level.fal_public); } else { AddError(get_location(_access_modifer_node), "ACCESS_MODIFER_IN_INTERFACE"); } return; } //\ssyy switch (_access_modifer_node.access_level) { case SyntaxTree.access_modifer.private_modifer: { context.set_field_access_level(SemanticTree.field_access_level.fal_private); break; } case SyntaxTree.access_modifer.protected_modifer: { context.set_field_access_level(SemanticTree.field_access_level.fal_protected); break; } case SyntaxTree.access_modifer.public_modifer: { context.set_field_access_level(SemanticTree.field_access_level.fal_public); break; } case SyntaxTree.access_modifer.internal_modifer: { context.set_field_access_level(SemanticTree.field_access_level.fal_internal); break; } } } public override void visit(SyntaxTree.class_members _class_members) { foreach (var def in _class_members.members.Where(d => d is const_definition || d is consts_definitions_list || d is variable_definitions || d is var_def_statement)) { var lambdaSearcher = new LambdaSearcher(def); if (lambdaSearcher.CheckIfContainsLambdas()) { AddError(new LambdasNotAllowedInFieldsInitialization(get_location(lambdaSearcher.FoundLambda))); } } weak_node_test_and_visit(_class_members.access_mod); foreach (SyntaxTree.declaration sd in _class_members.members) { hard_node_test_and_visit(sd); } } public override void visit(SyntaxTree.index_property _index_property) { throw new NotSupportedError(get_location(_index_property)); } public override void visit(SyntaxTree.simple_property _simple_property) { if (_simple_property.accessors == null) AddError(get_location(_simple_property), "PROPERTYACCESSOR_{0}_OR_{1}_EXPECTED", StringConstants.PascalReadAccessorName, StringConstants.PascalWriteAccessorName); if (_simple_property.property_type == null) AddError(get_location(_simple_property.property_name), "TYPE_NAME_EXPECTED"); string name = _simple_property.property_name.name; type_node expl_interface = null; if (_simple_property.property_name.ln != null) { for (var i = 0; i < _simple_property.property_name.ln.Count - 1; i++) if (_simple_property.property_name.ln[i] is SyntaxTree.template_type_name) AddError(new NameCannotHaveGenericParameters(_simple_property.property_name.ln[i].name, get_location(_simple_property.property_name.ln[i]))); var ntr = new SyntaxTree.named_type_reference(); if (_simple_property.property_name.ln[_simple_property.property_name.ln.Count - 1] is template_type_name) { template_type_reference ttr = new template_type_reference(); ttr.params_list = new template_param_list(); ttr.params_list.source_context = _simple_property.property_name.ln[_simple_property.property_name.ln.Count - 1].source_context; foreach (ident id in (_simple_property.property_name.ln[_simple_property.property_name.ln.Count - 1] as template_type_name).template_args.idents) ttr.params_list.params_list.Add(new named_type_reference(id.name, id.source_context)); for (var i = 0; i < _simple_property.property_name.ln.Count; i++) { ntr.Add(_simple_property.property_name.ln[i]); } ttr.name = ntr; ttr.source_context = _simple_property.property_name.source_context; ntr = ttr; } else for (var i = 0; i < _simple_property.property_name.ln.Count; i++) { ntr.Add(_simple_property.property_name.ln[i]); } type_node tn = find_type(ntr, get_location(_simple_property.property_name)); if (!tn.IsInterface) AddError(get_location(_simple_property.property_name), "EXPECTED_INTERFACE"); name = tn.BaseFullName + "." + name; expl_interface = tn; List sil = expl_interface.find_in_type(_simple_property.property_name.name); if (sil == null) AddError(new MemberIsNotDeclaredInType(_simple_property.property_name, get_location(_simple_property.property_name), expl_interface)); if (!(sil[0].sym_info is property_node)) AddError(get_location(_simple_property.property_name), "EXPECTED_PROPERTY"); } common_property_node pn = context.add_property(name, get_location(_simple_property.property_name)); assign_doc_info(pn, _simple_property); //pn.polymorphic_state=SemanticTree.polymorphic_state.ps_common; //pn.loc=get_location(_simple_property.property_name); if (context.converted_type.IsStatic && _simple_property.attr != SyntaxTree.definition_attribute.Static) AddError(get_location(_simple_property), "STATIC_CLASSES_CANNOT_NON_STATIC_MEMBERS"); if (_simple_property.attr == SyntaxTree.definition_attribute.Static) { if (context.converted_type.IsInterface) AddError(get_location(_simple_property), "INTERFACE_PROPERTIES_CANNOT_BE_STATIC"); pn.polymorphic_state = SemanticTree.polymorphic_state.ps_static; } if (_simple_property.virt_over_none_attr == proc_attribute.attr_virtual || _simple_property.virt_over_none_attr == proc_attribute.attr_override) pn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual; else if (_simple_property.virt_over_none_attr == proc_attribute.attr_abstract) { if (context.converted_type.IsInterface) AddError(get_location(_simple_property), "ATTRIBUTE_{0}_NOT_ALLOWED", "abstract"); context.converted_type.SetIsAbstract(true, new CARAbstractPropertie(_simple_property)); pn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract; } if (context.converted_type.is_value_type) { if (_simple_property.virt_over_none_attr == proc_attribute.attr_virtual) AddError(get_location(_simple_property), "ATTRIBUTE_{0}_NOT_ALLOWED", "virtual"); else if (_simple_property.virt_over_none_attr == proc_attribute.attr_override) AddError(get_location(_simple_property), "ATTRIBUTE_{0}_NOT_ALLOWED", "override"); else if (_simple_property.virt_over_none_attr == proc_attribute.attr_reintroduce) AddError(get_location(_simple_property), "ATTRIBUTE_{0}_NOT_ALLOWED", "reintroduce"); else if (_simple_property.virt_over_none_attr == proc_attribute.attr_abstract) AddError(get_location(_simple_property), "ATTRIBUTE_{0}_NOT_ALLOWED", "abstract"); } parameter_list pal_big = new parameter_list(); //TODO: Спросить у Саши как получить тип параметра - var,const и т.д. if (_simple_property.parameter_list != null) { foreach (SyntaxTree.property_parameter pp in _simple_property.parameter_list.parameters) { parameter_list pal_small = new parameter_list(); foreach (SyntaxTree.ident id in pp.names.idents) { common_parameter cp = new common_parameter(id.name, SemanticTree.parameter_type.value, null, concrete_parameter_type.cpt_none, get_location(id)); pal_small.AddElement(cp); } type_node tn = convert_strong(pp.type); foreach (parameter pr in pal_small) { pr.type = tn; } pal_big.AddRange(pal_small); } } pn.parameters.AddRange(pal_big); pn.internal_property_type = convert_strong(_simple_property.property_type); if (_simple_property.accessors != null) { convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors); List sil = null; //definition_node dn = null; if (_simple_property.accessors.read_accessor != null) { convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.read_accessor); if (_simple_property.accessors.read_accessor.accessor_name == null) { if (!context.converted_type.IsInterface && _simple_property.virt_over_none_attr != proc_attribute.attr_abstract) { AddError(get_location(_simple_property.accessors.read_accessor), "ACCESSOR_NAME_EXPECTED"); } pn.internal_get_function = GenerateGetSetMethodForInterfaceProperty(pn, get_location(_simple_property.accessors.read_accessor), true); } else { if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_simple_property.accessors.read_accessor), "ABSTRACT_PROPERTIES_CANNOT_HAVE_IMPLEMENTATION"); convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.read_accessor.accessor_name); sil = context.converted_type.find_in_type(_simple_property.accessors.read_accessor.accessor_name.name, context.CurrentScope); location loc1 = get_location(_simple_property.accessors.read_accessor.accessor_name); if (sil == null) { //AddError(new UndefinedNameReference(_simple_property.accessors.read_accessor.accessor_name.name, loc1)); AddError(loc1, "NAME_IN_PROPERTY_READ_SECTION_MUST_BE_FIELD_OR_METHOD_NAME"); } /*if (sil.FirstOrDefault().scope != context.CurrentScope) // SSM 22/05/20 { AddError(loc1, "NAME_IN_PROPERTY_READ_SECTION_MUST_BE_FIELD_OR_METHOD_NAME"); }*/ //dn = check_name_node_type(_simple_property.accessors.read_accessor.accessor_name.name, // si, loc1, general_node_type.function_node, general_node_type.variable_node); function_node read_accessor = sil.FirstOrDefault().sym_info as function_node; if (read_accessor != null) { if (!(read_accessor as common_method_node).IsStatic && _simple_property.attr == definition_attribute.Static) AddError(loc1,"STATIC_PROPERTY_MUST_HAVE_STATIC_ACCESSOR"); bool good_func = true; bool one_func = sil.Count() == 1; int si_index = 0; while(si_index < sil.Count()) { good_func = true; if (read_accessor.parameters.Count != pn.parameters.Count) { good_func = false; if (one_func) { AddError(new PropertyAndReadAccessorParamsCountConvergence(read_accessor, pn, loc1)); } } //TODO: Сверять типы параметров - var, const и т.д. else { for (int i1 = 0; good_func && i1 < read_accessor.parameters.Count; i1++) { if (read_accessor.parameters[i1].parameter_type != pn.parameters[i1].parameter_type || read_accessor.parameters[i1].type != pn.parameters[i1].type) { good_func = false; if (one_func) { AddError(loc1, "PROPERTY_{0}_AND_READ_ACCESSOR_{1}_PARAMS_TYPE_CONVERGENCE", pn.name, read_accessor.name); } } } if (read_accessor.return_value_type == null) { good_func = false; if (one_func) { AddError(loc1, "PROPERTY_READ_ACCESSOR_CAN_NOT_BE_PROCEDURE"); } } if (read_accessor.return_value_type != pn.property_type) { good_func = false; if (one_func) { AddError(loc1, "PROPERTY_{0}_AND_READ_ACCESSOR_{1}_RETURN_VALUE_TYPE_CONVERGENCE", pn.name, read_accessor.name); } } if (read_accessor is common_method_node && (read_accessor as common_method_node).is_constructor) { AddError(loc1, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY"); } } if (good_func) { break; } ++si_index; if (si_index < sil.Count()) { read_accessor = sil[si_index].sym_info as function_node; } } if (!good_func) { AddError(loc1, "NO_OVERLOAD_FUNCTION_{0}_USEFUL_FOR_ACCESSOR", read_accessor.name); } read_accessor = GenerateGetMethod(pn, read_accessor as common_method_node, pn.loc); } else { class_field cfield = sil.FirstOrDefault().sym_info as class_field; if (cfield == null) { AddError(loc1, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY"); } if (_simple_property.parameter_list != null) { AddError(loc1, "INDEX_PROPERTY_ACCESSOR_CAN_NOT_BE_VARIABLE"); } if (cfield.type != pn.internal_property_type) { AddError(loc1, "PROPERTY_TYPE_MISMATCH_ACCESSOR_FIELD_TYPE"); } if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", cfield.name); if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state == SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", cfield.name); read_accessor = GenerateGetMethodForField(pn, StringConstants.GetGetAccessorName(pn.name), cfield, loc1); } //Вот здесь уже можем добавить акцессор для чтения. pn.internal_get_function = read_accessor; } if (pn.internal_get_function != null && pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && pn.internal_get_function.polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", pn.internal_get_function.name); if (pn.internal_get_function != null && pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && pn.internal_get_function.polymorphic_state == SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.read_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", pn.internal_get_function.name); } if (_simple_property.accessors.write_accessor != null) { convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.write_accessor); if (_simple_property.accessors.write_accessor.accessor_name == null) { if (!context.converted_type.IsInterface && _simple_property.virt_over_none_attr != proc_attribute.attr_abstract) { AddError(get_location(_simple_property.accessors.write_accessor), "ACCESSOR_NAME_EXPECTED"); } pn.internal_set_function = GenerateGetSetMethodForInterfaceProperty(pn, get_location(_simple_property.accessors.write_accessor), false); } else { if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_simple_property.accessors.write_accessor), "ABSTRACT_PROPERTIES_CANNOT_HAVE_IMPLEMENTATION"); convertion_data_and_alghoritms.check_node_parser_error(_simple_property.accessors.write_accessor.accessor_name); sil = context.converted_type.find_in_type(_simple_property.accessors.write_accessor.accessor_name.name, context.CurrentScope); location loc2 = get_location(_simple_property.accessors.write_accessor.accessor_name); if (sil == null) { //AddError( new UndefinedNameReference(_simple_property.accessors.write_accessor.accessor_name.name, loc2)); AddError(loc2, "NAME_IN_PROPERTY_WRITE_SECTION_MUST_BE_FIELD_OR_METHOD_NAME"); } /*if (sil.FirstOrDefault().scope != context.CurrentScope) // SSM 22/05/20 { AddError(loc2, "NAME_IN_PROPERTY_WRITE_SECTION_MUST_BE_FIELD_OR_METHOD_NAME"); }*/ //dn = check_name_node_type(_simple_property.accessors.write_accessor.accessor_name.name, // si, loc2, general_node_type.function_node, general_node_type.variable_node); function_node write_accessor = sil.FirstOrDefault().sym_info as function_node; if (write_accessor != null) { if (!(write_accessor as common_method_node).IsStatic && _simple_property.attr == definition_attribute.Static) AddError(loc2, "STATIC_PROPERTY_MUST_HAVE_STATIC_ACCESSOR"); bool good_func = true; bool one_func = sil.Count() == 1; int si_index = 0; while (si_index < sil.Count()) { good_func = true; if (write_accessor.parameters.Count != pn.parameters.Count + 1) { good_func = false; if (one_func) { AddError( new PropertyAndWriteAccessorParamsCountConvergence(write_accessor, pn, loc2)); } } else { //TODO: Сверять типы параметров - var, const и т.д. for (int i2 = 0; good_func && i2 < pn.parameters.Count; i2++) { if (write_accessor.parameters[i2].parameter_type != pn.parameters[i2].parameter_type || write_accessor.parameters[i2].type != pn.parameters[i2].type) { good_func = false; if (one_func) { AddError(loc2, "PROPERTY_{0}_AND_WRITE_ACCESSOR_{1}_PARAMS_TYPE_CONVERGENCE", pn.name ,write_accessor.name); } } } if (write_accessor.parameters[write_accessor.parameters.Count - 1].type != pn.property_type || write_accessor.parameters[write_accessor.parameters.Count - 1].parameter_type != PascalABCCompiler.SemanticTree.parameter_type.value) { good_func = false; if (one_func) { AddError(loc2, "PROPERTY_{0}_AND_WRITE_ACCESSOR_LAST_PARAMETER_TYPE_CONVERGENCE", pn.name); } } if (write_accessor.return_value_type != null) { good_func = false; if (one_func) { AddError(loc2, "PROPERTY_WRITE_ACCESSOR_CAN_NOT_BE_FUNCTION"); } } } if (good_func) { break; } ++si_index; if (si_index < sil.Count()) { write_accessor = sil[si_index].sym_info as function_node; } } if (!good_func) { AddError(loc2, "NO_OVERLOAD_FUNCTION_{0}_USEFUL_FOR_ACCESSOR", write_accessor.name); } if (write_accessor is common_method_node && (write_accessor as common_method_node).is_constructor) { AddError(loc2, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY"); } write_accessor = GenerateSetMethod(pn, write_accessor as common_method_node, pn.loc); } else { class_field cfield = sil.FirstOrDefault().sym_info as class_field; if (cfield == null) { AddError(loc2, "ACCESSOR_CAN_BE_FIELD_OR_METHOD_ONLY"); } if (_simple_property.parameter_list != null) { AddError(loc2, "INDEX_PROPERTY_ACCESSOR_CAN_NOT_BE_VARIABLE"); } if (cfield.type != pn.internal_property_type) { AddError(loc2, "PROPERTY_TYPE_MISMATCH_ACCESSOR_FIELD_TYPE"); } if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", cfield.name); if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfield.polymorphic_state == SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", cfield.name); write_accessor = GenerateSetMethodForField(pn, StringConstants.GetSetAccessorName(pn.name), cfield, loc2); } //Вот здесь уже можем добавить акцессор для чтения. pn.internal_set_function = write_accessor; } if (pn.internal_set_function != null && pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static && pn.internal_set_function.polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_MUST_BE_STATIC", pn.internal_set_function.name); if (pn.internal_set_function != null && pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && pn.internal_set_function.polymorphic_state == SemanticTree.polymorphic_state.ps_static) AddError(get_location(_simple_property.accessors.write_accessor.accessor_name), "ACCESSOR_{0}_CANNOT_BE_STATIC", pn.internal_set_function.name); } } make_attributes_for_declaration(_simple_property,pn); if (_simple_property.virt_over_none_attr == proc_attribute.attr_override) context.set_override(pn); else if (expl_interface != null) { context.set_implement(pn, _simple_property.property_name.name, expl_interface); } //TODO: Можно сделать множество свойств по умолчанию. if (_simple_property.array_default != null) { if (pn.parameters.Count == 0) { AddError(pn.loc, "DEFAULT_PROPERTY_MUST_BE_INDEXED"); } if (context.converted_type.default_property_node != null) { AddError(pn.loc, "DUPLICATE_DEFAULT_PROPERTY_IN_CLASS"); } context.converted_type.default_property = pn; } } private function_node GenerateGetMethod(common_property_node cpn, common_method_node accessor, location loc) { string getter_name = "get_" + cpn.name; if (cpn.name.IndexOf('.') != -1) { string[] names = cpn.name.Split('.'); getter_name = names.Take(names.Length - 1).ToArray().JoinIntoString(".") + "get_" + names[names.Length - 1]; } common_method_node cmn = new common_method_node( getter_name, loc, cpn.common_comprehensive_type, cpn.polymorphic_state, cpn.field_access_level, null); cpn.common_comprehensive_type.methods.AddElement(cmn); cmn.return_value_type = cpn.property_type; cmn.is_overload = true; foreach (common_parameter cp in accessor.parameters) { common_parameter new_cp = new common_parameter(cp.name, cp.type, cp.parameter_type, cp.common_function, cp.concrete_parameter_type, cp.default_value, loc); cmn.parameters.AddElement(new_cp); } expression_node meth_call; if (accessor.polymorphic_state == SemanticTree.polymorphic_state.ps_common || accessor.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual) { meth_call = new common_method_call(accessor, new this_node(cpn.common_comprehensive_type, loc), loc); foreach (common_parameter cp in cmn.parameters) { (meth_call as common_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc)); } } else { meth_call = new common_static_method_call(accessor, loc); foreach (common_parameter cp in cmn.parameters) { (meth_call as common_static_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc)); } } cmn.function_code = new return_node(meth_call, loc); cpn.common_comprehensive_type.scope.AddSymbol(getter_name, new SymbolInfo(cmn)); return cmn; } private function_node GenerateSetMethod(common_property_node cpn, common_method_node accessor, location loc) { string setter_name = "set_" + cpn.name; if (cpn.name.IndexOf('.') != -1) { string[] names = cpn.name.Split('.'); setter_name = names.Take(names.Length - 1).ToArray().JoinIntoString(".") + "set_" + names[names.Length - 1]; } common_method_node cmn = new common_method_node( setter_name, loc, cpn.common_comprehensive_type, cpn.polymorphic_state, cpn.field_access_level, null); cpn.common_comprehensive_type.methods.AddElement(cmn); //cmn.return_value_type = cpn.property_type; cmn.is_overload = true; foreach (common_parameter cp in accessor.parameters) { common_parameter new_cp = new common_parameter(cp.name, cp.type, cp.parameter_type, cp.common_function, cp.concrete_parameter_type, cp.default_value, loc); cmn.parameters.AddElement(new_cp); } expression_node meth_call; if (accessor.polymorphic_state == SemanticTree.polymorphic_state.ps_common || accessor.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual) { meth_call = new common_method_call(accessor, new this_node(cpn.common_comprehensive_type, loc), loc); foreach (common_parameter cp in cmn.parameters) { (meth_call as common_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc)); } } else { meth_call = new common_static_method_call(accessor, loc); foreach (common_parameter cp in cmn.parameters) { (meth_call as common_static_method_call).parameters.AddElement(new common_parameter_reference(cp, 0, loc)); } } cmn.function_code = meth_call; cpn.common_comprehensive_type.scope.AddSymbol(setter_name, new SymbolInfo(cmn)); return cmn; } internal function_node GenerateSetMethodForField(common_property_node cpn, string AcessorName, class_field cf, location loc) { List exist_sil = context.find_only_in_namespace(AcessorName); if (exist_sil != null && exist_sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName); } if (exist_sil != null) { foreach (SymbolInfo exist_si in exist_sil) { function_node ff = (function_node)(exist_si.sym_info); if (ff.parameters.Count == 1 && ff.parameters[0].type == cf.type) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName); } } } common_method_node cmn = new common_method_node( AcessorName, loc, /*cf.cont_type,*/ cpn.comprehensive_type as common_type_node, cpn.polymorphic_state, context.get_field_access_level(), null); cpn.common_comprehensive_type.methods.AddElement(cmn); common_parameter cp = new common_parameter( StringConstants.value, cf.type, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, loc); cmn.parameters.AddElement(cp); cmn.is_overload = true; common_parameter_reference cpr = new common_parameter_reference(cp, 0, loc); expression_node var_ref; if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_common) { var_ref = new class_field_reference(cf, new this_node(cf.type, loc), loc); } else { var_ref = new static_class_field_reference(cf, loc); } cmn.function_code = find_operator(StringConstants.assign_name, var_ref, cpr, loc); cf.cont_type.Scope.AddSymbol(AcessorName, new SymbolInfo(cmn)); return cmn; } internal expression_node make_assign_operator(addressed_expression left, expression_node right, location loc) { return find_operator(StringConstants.assign_name, left, right, loc); } internal function_node GenerateGetMethodForField(common_property_node cpn, string AcessorName, class_field cf, location loc) { List exist_sil = context.find_only_in_namespace(AcessorName); if (exist_sil != null && exist_sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName); } if (exist_sil != null) { foreach (SymbolInfo exist_si in exist_sil) { if (((function_node)(exist_si.sym_info)).parameters.Count == 0) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName); } } } common_method_node cmn = new common_method_node( AcessorName, loc, /*cf.cont_type,*/ cpn.comprehensive_type as common_type_node, cpn.polymorphic_state, context.get_field_access_level(), null); cpn.common_comprehensive_type.methods.AddElement(cmn); cmn.return_value_type = cf.type; cmn.is_overload = true; expression_node var_ref; if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_common) { var_ref = new class_field_reference(cf, new this_node(cf.type, loc), loc); } else { var_ref = new static_class_field_reference(cf, loc); } cmn.function_code = new return_node(var_ref, loc); cf.cont_type.Scope.AddSymbol(AcessorName, new SymbolInfo(cmn)); // scope -> Scope SSM 23/05/20 - return cmn; } private function_node GenerateGetSetMethodForInterfaceProperty(common_property_node pn, location loc, bool get_meth) { string AcessorName = (get_meth) ? StringConstants.GetGetAccessorName(pn.name) : StringConstants.GetSetAccessorName(pn.name); List exist_sil = context.find_only_in_namespace(AcessorName); if (exist_sil != null && exist_sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", AcessorName); } common_method_node cmn = new common_method_node( AcessorName, loc, pn.common_comprehensive_type, pn.polymorphic_state, context.get_field_access_level(), null); cmn.is_overload = true; foreach (common_parameter cp in pn.parameters) { common_parameter accp = new common_parameter(cp.name, cp.parameter_type, cmn, cp.concrete_parameter_type, cp.loc); accp.type = cp.type; accp.inital_value = cp.inital_value; accp.intrenal_is_params = cp.intrenal_is_params; accp.is_ret_value = cp.is_ret_value; cmn.parameters.AddElement(accp); } if (get_meth) { cmn.return_value_type = pn.internal_property_type; } else { //foreach (common_parameter par in cmn.parameters) //{ // if (par.name == //} common_parameter accp = new common_parameter(StringConstants.value_in_accessor_name, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null); accp.type = pn.internal_property_type; cmn.parameters.AddElement(accp); } if (exist_sil != null) { foreach (SymbolInfo exist_si in exist_sil) { if (convertion_data_and_alghoritms.function_eq_params(cmn, (function_node)(exist_si.sym_info))) { AddError(loc, "CAN_NOT_GENERATE_ACCESSOR_{0}", cmn.name); } } } pn.common_comprehensive_type.methods.AddElement(cmn); pn.common_comprehensive_type.scope.AddSymbol(AcessorName, new SymbolInfo(cmn)); return cmn; } public override void visit(SyntaxTree.property_accessors _property_accessors) { throw new NotSupportedError(get_location(_property_accessors)); } public override void visit(SyntaxTree.read_accessor_name _read_accessor_name) { throw new NotSupportedError(get_location(_read_accessor_name)); } public override void visit(SyntaxTree.write_accessor_name _write_accessor_name) { throw new NotSupportedError(get_location(_write_accessor_name)); } public override void visit(SyntaxTree.array_const _array_const) { if (_array_const.elements != null) { List elements = new List(); List exprs = new List(); foreach (SyntaxTree.expression expr in _array_const.elements.expressions) { if (is_typed_const_def) elements.Add(convert_strong_to_constant_node(expr)); else exprs.Add(convert_strong(expr)); } if (is_typed_const_def) { array_const arrc = new array_const(elements, get_location(_array_const)); arrc.SetType(new ArrayConstType(elements[0].type, elements.Count, arrc.location)); return_value(arrc); } else { array_initializer arrc = new array_initializer(exprs, get_location(_array_const)); arrc.type = new ArrayConstType(exprs[0].type, exprs.Count, arrc.location); return_value(arrc); } } else { //это пустой инициализатор записи record_constant rc = new record_constant(new List(), get_location(_array_const)); rc.SetType(new RecordConstType(get_location(_array_const))); return_value(rc); } } private expressions_list get_set_initializer(expression_node cnfc) { return set_intls[cnfc]; } private void add_set_initializer(expression_node cnfc, expressions_list exprs) { set_intls[cnfc] = exprs; } private System.Tuple convert_diap_for_new_set(SyntaxTree.diapason_expr _diapason_expr, out type_node elem_type) { expression_node left = convert_strong(_diapason_expr.left); if (left is typed_expression) left = convert_typed_expression_to_function_call(left as typed_expression); expression_node right = convert_strong(_diapason_expr.right); if (right is typed_expression) right = convert_typed_expression_to_function_call(right as typed_expression); internal_interface ii = left.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null) { AddError(new OrdinalTypeExpected(left.location)); } internal_interface iir = right.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (iir == null) { AddError(new OrdinalTypeExpected(right.location)); } type_node_list tnl = new type_node_list(); tnl.AddElement(left.type); tnl.AddElement(right.type); elem_type = convertion_data_and_alghoritms.select_base_type(tnl, true); if (elem_type == SystemLibrary.SystemLibrary.object_type) AddError(new SimpleSemanticError(get_location(_diapason_expr), "BAD_DIAPASON_IN_SET_TYPE")); // До этого момента совпадает с convert_diap_for_set // если элементы - какого то целого типа, то привести к типу integer if (elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !elem_type.IsEnum) { left = convertion_data_and_alghoritms.explicit_convert_type(left, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.explicit_convert_type(right, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type); } return Tuple.Create(left, right); } private expression_node convert_diap_for_set(SyntaxTree.diapason_expr _diapason_expr, out type_node elem_type) { expression_node left = convert_strong(_diapason_expr.left); if (left is typed_expression) left = convert_typed_expression_to_function_call(left as typed_expression); expression_node right = convert_strong(_diapason_expr.right); if (right is typed_expression) right = convert_typed_expression_to_function_call(right as typed_expression); internal_interface ii = left.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null) { AddError(new OrdinalTypeExpected(left.location)); } internal_interface iir = right.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (iir == null) { AddError(new OrdinalTypeExpected(right.location)); } type_node_list tnl = new type_node_list(); tnl.AddElement(left.type); tnl.AddElement(right.type); elem_type = convertion_data_and_alghoritms.select_base_type(tnl,true); if (elem_type == SystemLibrary.SystemLibrary.object_type) AddError(new SimpleSemanticError(get_location(_diapason_expr), "BAD_DIAPASON_IN_SET_TYPE")); expression_node l = convertion_data_and_alghoritms.explicit_convert_type(left, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type); expression_node r = convertion_data_and_alghoritms.explicit_convert_type(right, PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type); if (PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info is common_namespace_function_node) { common_namespace_function_node cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as common_namespace_function_node; if (elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.char_type || elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type || elem_type.IsEnum) cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as common_namespace_function_node; common_namespace_function_call cnfc = new common_namespace_function_call(cnfn, get_location(_diapason_expr)); if (elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !elem_type.IsEnum) { cnfc.parameters.AddElement(l); cnfc.parameters.AddElement(r); } else { cnfc.parameters.AddElement(left); cnfc.parameters.AddElement(right); } return cnfc; } else { compiled_function_node cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as compiled_function_node; if (elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.char_type || elem_type == PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type || elem_type.IsEnum) cnfn = PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as compiled_function_node; compiled_static_method_call cnfc = new compiled_static_method_call(cnfn, get_location(_diapason_expr)); if (elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && elem_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !elem_type.IsEnum) { cnfc.parameters.AddElement(l); cnfc.parameters.AddElement(r); } else { cnfc.parameters.AddElement(left); cnfc.parameters.AddElement(right); } return cnfc; } } public override void visit(SyntaxTree.pascal_set_constant _pascal_set_constant) { // Если хоть одно - diapason_expr, то это множество иначе литеральный массив /*if (_pascal_set_constant.values == null || _pascal_set_constant.values.expressions.Any(ex => ex is SyntaxTree.diapason_expr) ) { // это множество } else { var exl = new expression_list(_pascal_set_constant.values.expressions, _pascal_set_constant.source_context); array_const_new ac = new array_const_new(exl,exl.source_context); visit(ac); return; }*/ // надо разбить на 2 списка констант expressions_list consts = new expressions_list(); expressions_list consts_diap = new expressions_list(); type_node el_type = null; // вывод самого общего типа элемента type_node_list types = new type_node_list(); // этот список - единый. Он нужен только для вывода самого общего типа if (_pascal_set_constant.values != null && _pascal_set_constant.values.expressions != null) foreach (SyntaxTree.expression e in _pascal_set_constant.values.expressions) { if (e is SyntaxTree.nil_const) AddError(new SimpleSemanticError(get_location(e), "NIL_IN_SET_CONSTRUCTOR_NOT_ALLOWED")); else if (e is SyntaxTree.diapason_expr) { var pair = convert_diap_for_new_set((e as SyntaxTree.diapason_expr), out el_type); consts_diap.AddElement(pair.Item1); consts_diap.AddElement(pair.Item2); if (el_type.IsPointer) AddError(new SimpleSemanticError(get_location(e), "POINTERS_IN_SETS_NOT_ALLOWED")); types.AddElement(el_type); } else { expression_node en = convert_strong(e); if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression); if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string) en.type = SystemLibrary.SystemLibrary.string_type; consts.AddElement(en); if (en.type.IsPointer) AddError(new SimpleSemanticError(get_location(e), "POINTERS_IN_SETS_NOT_ALLOWED")); if (en.type.type_special_kind == type_special_kind.diap_type) types.AddElement(en.type.base_type); else types.AddElement(en.type); } } // Константы и типы заполнены // Выводим самый общий тип //type_node ctn = null; if (types.Count > 0) { el_type = convertion_data_and_alghoritms.select_base_type(types, true); // !! if (el_type == null) AddError(new SimpleSemanticError(get_location(_pascal_set_constant), "IMPOSSIBLE_TO_INFER_SET_TYPE")); // Делаю невозможным базовый тип object - не нравится это, и в массивах нет if (el_type == SystemLibrary.SystemLibrary.object_type) AddError(new SimpleSemanticError(get_location(_pascal_set_constant), "IMPOSSIBLE_TO_INFER_SET_TYPE")); // если есть диапазоны, то базовый тип не может быть int64 и проч - только integer!!! if (consts_diap.Count > 0) if (el_type != PascalABCCompiler.SystemLibrary.SystemLibrary.char_type && el_type != PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type && el_type != PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type && !el_type.IsEnum) AddError(new SimpleSemanticError(get_location(_pascal_set_constant), "IMPOSSIBLE_TO_INFER_SET_TYPE")); } // Теперь базовый тип известен (он может быть null), и надо сгенерировать // EmptySet // NSet(consts) или // NSet(Arr(consts), Arr(consts_diap)) // и обойти его // Для el_type, consts и consts_diap надо делать обёртку semantic_type_node // и semantic_addr_value (тут не знаю - это константы вроде, хотя там к expression_node приводится так что всё хорошо) // new semantic_addr_value() var p = _pascal_set_constant; var psc = p.source_context; if (el_type == null) { var dn = new dot_node(new ident("PABCSystem", psc), new ident("EmptySet", psc)); ProcessNode(dn); } else if (consts_diap.Count == 0) { // Это прямо очень хорошо! Просто вызываем NSet(consts) var nset_type = new semantic_type_node(el_type, psc); var dn = new ident("__NewSetCreatorInternal", psc); var td = new semantic_type_node(el_type, psc); var tpl = new template_param_list(new List { td }, psc); var method_name = new ident_with_templateparams(dn, tpl, psc); var m_el = new expression_list(); foreach (var el in consts) m_el.Add(new semantic_addr_value(el, el.location)); // Добавим все обёрнутые константы var mc = new method_call(method_name, m_el, psc); ProcessNode(mc); } else { // Ну теперь самый общий NSet(Arr(consts), Arr(consts_diap)) var nset_type = new semantic_type_node(el_type, psc); var dnNSetInt = new dot_node(new ident("PABCSystem", psc), new ident("__NSetInteger", psc)); var dnNSetChar = new dot_node(new ident("PABCSystem", psc), new ident("__NSetChar", psc)); var dnNSetEnum = new dot_node(new ident("PABCSystem", psc), new ident("__NSetEnum", psc)); var dnNSetBool = new dot_node(new ident("PABCSystem", psc), new ident("__NSetBoolean", psc)); // PABCSystem.Arr нельзя использовать - кидает странную ошибку var dnArr = new dot_node(new ident("PABCSystem", psc), new ident("Arr", psc)); var td = new semantic_type_node(el_type, psc); var tpl = new template_param_list(new List { td }, psc); var method_name_Arr = new ident_with_templateparams(dnArr, tpl, psc); var m_el_Arr1 = new expression_list(); foreach (var el in consts) m_el_Arr1.Add(new semantic_addr_value(el, el.location)); var m_el_Arr2 = new expression_list(); foreach (var el in consts_diap) m_el_Arr2.Add(new semantic_addr_value(el, el.location)); var cnt1 = new expression_list(new int32_const(m_el_Arr1.Count), p.values.source_context); var cnt2 = new expression_list(new int32_const(m_el_Arr2.Count), p.values.source_context); var arr1_init = new SyntaxTree.array_const(m_el_Arr1, p.values.source_context); var arr2_init = new SyntaxTree.array_const(m_el_Arr2, p.values.source_context); var new_arr1 = new new_expr(td, cnt1, true, arr1_init, p.values.source_context); var new_arr2 = new new_expr(td, cnt2, true, arr2_init, p.values.source_context); //var mc1 = new method_call(method_name_Arr, m_el_Arr1, psc); //var mc2 = new method_call(method_name_Arr, m_el_Arr2, psc); var m_el_NSet = new expression_list(); m_el_NSet.Add(new_arr1); m_el_NSet.Add(new_arr2); method_call mc_NSet = null; if (el_type == PascalABCCompiler.SystemLibrary.SystemLibrary.integer_type) mc_NSet = new method_call(dnNSetInt, m_el_NSet, psc); else if (el_type == PascalABCCompiler.SystemLibrary.SystemLibrary.char_type) mc_NSet = new method_call(dnNSetChar, m_el_NSet, psc); else if (el_type.IsEnum) mc_NSet = new method_call(dnNSetEnum, m_el_NSet, psc); else if (el_type == PascalABCCompiler.SystemLibrary.SystemLibrary.bool_type) mc_NSet = new method_call(dnNSetBool, m_el_NSet, psc); else AddError(new SimpleSemanticError(get_location(_pascal_set_constant), "IMPOSSIBLE_TO_INFER_SET_TYPE")); ProcessNode(mc_NSet); } } public override void visit(SyntaxTree.array_const_new acn) { var lst = acn.elements.expressions.Select(ex => { var semex = convert_strong(ex); try_convert_typed_expression_to_function_call(ref semex); return semex; }).ToList(); type_node_list types = new type_node_list(); foreach (var tn in lst.Select(ex => ex.type)) { if (tn.type_special_kind == type_special_kind.diap_type) // SSM 4/12/24 - стирание информации о типе диапазона types.AddElement(tn.base_type); else types.AddElement(tn); } var el_type = convertion_data_and_alghoritms.select_base_type_for_arr_const_new(types, lst, true); var syntax_type = new SyntaxTree.semantic_type_node(el_type); //SyntaxTree.semantic_addr_value sav; var plist = new SyntaxTree.expression_list(new int32_const(acn.elements.Count)); var nn = new SyntaxTree.new_expr(syntax_type, plist, true, new SyntaxTree.array_const(acn.elements, acn.elements.source_context), acn.source_context); visit(nn); } internal List get_function_instances(List sil, List type_pars, string name, location loc, bool stop_on_error) { List tparams = visit_type_list(type_pars); for (int i = 0; i < tparams.Count; i++) { CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_generic_useful(tparams[i], loc); if (err != null) { AddError(err); } } List start = null; if (sil != null) { foreach (SymbolInfo si in sil) { function_node fn = si.sym_info as function_node; if (fn != null) { function_node inst = fn.get_instance(tparams, stop_on_error, loc); if (inst != null) { SymbolInfo s = new SymbolInfo(inst); if (start == null) { start = new List { s }; } else { start.Add(s); } } } } } if (start == null) { AddError(loc, "NO_FUNCTIONS_{0}_CAN_BE_USED_WITH_THIS_SPECIFICATION", name); } return start; } private List get_generic_functions(List funcs, bool stop_on_none, location loc) { List start = null; if (funcs != null) { foreach (SymbolInfo func in funcs) { function_node f = func.sym_info as function_node; if (f != null && f.is_generic_function) { //Проверяем на совпадение bool found = false; if (start != null) { foreach (SymbolInfo fsi in start) { if (fsi == func) break; if (convertion_data_and_alghoritms.function_eq_params(fsi.sym_info as function_node, f)) { found = true; break; } } } if (!found) { if (start == null) { start = new List { func }; } else { start.Add(func); } } } } } if (start == null) { if (stop_on_none) { AddError(loc, "TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS"); } return null; } return start; } private void visit_mc_helper(motivation mot, expression_node expr_node, location loc, expressions_list exprs, string msg, bool check_loop_variable = false) { switch (mot) { case motivation.expression_evaluation: { // SSM 28/11/18 Проверка, что var-параметры не являются параметрами цикла for или foreach if (check_loop_variable) { var fc = expr_node as base_function_call; if (fc != null) // здесь обрезаются такие волшебные функции как exit, у которых базовый тип - expr_node. Для них var-параметры проверяются отдельно (это Inc, Dec, Read) { var fun = fc.function; for (var i = 0; i < fun.parameters.Length; i++) { if (fun.parameters[i].parameter_type == SemanticTree.parameter_type.var) { check_on_loop_variable(exprs[i]); } } } } return_value(expr_node); return; } case motivation.semantic_node_reciving: { return_semantic_value(expr_node); return; } default: { AddError(loc, msg); return; } } } class SymInfoComparer: EqualityComparer { public override bool Equals(SymbolInfo x, SymbolInfo y) { return x.sym_info == y.sym_info; } public override int GetHashCode(SymbolInfo codeh) { return 0; } } internal void visit_method_call(SyntaxTree.method_call _method_call) { // frninja 01/03/16 - for iterator capturing (yield) if (_method_call.dereferencing_value is yield_unknown_ident) { var nodeToVisit = new method_call(ProcessUnknownIdent(_method_call.dereferencing_value as yield_unknown_ident), _method_call.parameters); visit(nodeToVisit); return; } // end frninja //lroman if (_method_call.dereferencing_value is closure_substituting_node) { var nodeToVisit = new method_call(((closure_substituting_node)_method_call.dereferencing_value).substitution, _method_call.parameters); visit(nodeToVisit); return; } if (_method_call.dereferencing_value is dot_node dn && dn.right is operator_name_ident) { AddError(get_location(dn.right), "OPERATIONS_CANNOT_BE_CALLED_USING_THIS_SYNTAX"); } bool proc_wait = procedure_wait; bool lambdas_are_in_parameters = false; //lroman// var syntax_nodes_parameters = _method_call.parameters == null ? new List() : _method_call.parameters.expressions; // SSM 08/05/23 // 1. Проверить, что именованные аргументы идут в конце // 2. Проверить, что нет одинаковых имен в именованных аргументах var foundnamedargs = false; var lst1 = new List(); foreach (var param in syntax_nodes_parameters) { var aa = param as name_assign_expr; if (aa != null) { foundnamedargs = true; if (lst1.Contains(aa.name.name, StringComparer.OrdinalIgnoreCase)) AddError(get_location(aa.name), "NAMED_ARG_{0}_HAS_BEEN_USED_BEFORE", aa.name); else lst1.Add(aa.name.name); } else if (foundnamedargs) AddError(get_location(param), "UNNAMED_ARGS_CANNOT_FOLLOW_NAMED"); } lst1 = null; if (procedure_wait) { procedure_wait = false; } //throw new ArgumentNullException("test"); var mot = motivation_keeper.motivation; motivation_keeper.reset(); expression_node expr_node = null; expressions_list exprs = new expressions_list(); SyntaxTree.ident id = null; List sil = null; type_node to_type = null; SyntaxTree.addressed_value deref_value = _method_call.dereferencing_value; int templ_args_count = 0; //bool needs_generic_type_search = false; SyntaxTree.ident_with_templateparams iwt = deref_value as SyntaxTree.ident_with_templateparams; if (iwt != null) { deref_value = iwt.name; templ_args_count = iwt.template_params.params_list.Count; //needs_generic_type_search = _method_call.parameters.expressions.Count == 1; } SyntaxTree.inherited_ident inh_id = deref_value as SyntaxTree.inherited_ident; if (inh_id != null) { inherited_ident_processing = true; sil = find_in_base(inh_id); if (sil != null) if (sil.FirstOrDefault().sym_info is common_method_node) { if ((sil.FirstOrDefault().sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD"); } else if (sil.FirstOrDefault().sym_info is compiled_function_node) { if ((sil.FirstOrDefault().sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(inh_id), "CANNOT_CALL_ABSTRACT_METHOD"); } id = inh_id; } else { id = deref_value as SyntaxTree.ident; if (id != null && id.name != null && id.name.IndexOf('.') != -1) { var arr = id.name.Split('.'); deref_value = new dot_node(new ident(id.name.Substring(0, id.name.LastIndexOf('.')), id.source_context), new ident(arr[arr.Length-1],id.source_context)); id = null; } if (id != null) { if (templ_args_count != 0) { //Ищем generics sil = context.find(id.name + StringConstants.generic_params_infix + templ_args_count.ToString()); if (sil != null) { sil = new List { new SymbolInfo(get_generic_instance(sil?.FirstOrDefault(), iwt.template_params.params_list)) }; iwt = null; } } if (sil == null) { SyntaxTree.operator_name_ident oni = id as SyntaxTree.operator_name_ident; if (oni != null) { sil = context.find(name_reflector.get_name(oni.operator_type)); } else { sil = context.find(id.name); if (templ_args_count != 0 && sil != null) { SymbolInfo conv = ConvertTypeToInstance(sil?.FirstOrDefault(), iwt.template_params.params_list, get_location(id)); if (conv != null) { sil = new List { conv }; iwt = null; } } if (sil != null && id.name.ToLower() == "reset" && sil.FirstOrDefault().sym_info is common_method_node && (sil.FirstOrDefault().sym_info as common_method_node).cont_type.name.Contains("clyield#") && _method_call.ParametersCount > 0) { sil = context.converted_namespace.find(id.name); } if (sil != null && id.name.ToLower() == "create" && context.converted_type != null && sil.FirstOrDefault().sym_info is common_method_node && (sil.FirstOrDefault().sym_info as common_method_node).is_constructor) { List base_si_list = context.converted_type.base_type.find(id.name); if (base_si_list != null) sil.AddRange(base_si_list); } } } } if (sil == null) { SyntaxTree.dot_node _dot_node = deref_value as SyntaxTree.dot_node; if (_dot_node != null) { bool skip_first_parameter = false; //lroman// bool has_extension_overload = false; semantic_node sn = convert_semantic_strong(_dot_node.left); // SSM 17/07/21 учёт ZeroBasedStrings в семантике срезов строк if (SemanticRulesConstants.ZeroBasedStrings && (sn as expression_node)?.type is compiled_type_node ctn && ctn.compiled_type == typeof(string) && _dot_node.right is ident id0 ) { if (id0.name.ToLower() == "systemslice" || id0.name.ToLower() == "systemslicequestion" || id0.name.ToLower() == "systemsliceassignment" ) id0.name += "0"; // SystemSlice0 } // SSM 04/09/21 учёт ZeroBasedStrings в s[^1] if (SemanticRulesConstants.ZeroBasedStrings && (sn as expression_node)?.type.BaseFullName == "PABCSystem.SystemIndex" && _dot_node.right is ident id1 && id1.name.ToLower() == "reverse" && _method_call.parameters.Count == 1) { var strtn = convert_strong(_method_call.parameters.expressions[0]); if (strtn.type is compiled_type_node strtnc && strtnc.compiled_type == typeof(string)) // Уф { id1.name += "0"; // Reverse0 } } //SyntaxTree.ident id_right = ConvertOperatorNameToIdent(_dot_node.right as SyntaxTree.ident); SyntaxTree.ident id_right = _dot_node.right as SyntaxTree.ident; switch (sn.general_node_type) { case general_node_type.expression: { expression_node exp = (expression_node)sn; if (exp is typed_expression) try_convert_typed_expression_to_function_call(ref exp); location subloc = get_location(id_right); if (exp is typed_expression) AddError(new UndefinedNameReference(id_right.name, subloc)); SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { sil = exp.type.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope); } else { sil = exp.type.find_in_type(id_right.name, context.CurrentScope); // SSM 25.05.23 тут находится div в 1.div(2,3), а не должен // в этом случае sil.sym_info = basic_function_node sil = sil?.FindAll(si => !(si.sym_info is basic_function_node)); // убираю все такие операторы. Может, убираю лишнее if (sil != null && sil.Count == 0) sil = null; sil = sil?.Distinct(new SymInfoComparer()).ToList(); // SSM 16/06/20 - удалил дубли для порядка if (sil != null && sil.FirstOrDefault().sym_info != null && sil.FirstOrDefault().sym_info.semantic_node_type == semantic_node_type.wrap_def) { BasePCUReader.RestoreSymbols(sil, id_right.name); } } if (sil == null) { AddError(new UndefinedNameReference(id_right.name, subloc)); } if (sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(sil.FirstOrDefault().sym_info)); } else { dot_node_as_expression_dot_ident(exp, id_right, motivation.expression_evaluation, _dot_node.left); exp = ret.get_expression(); internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = ii as delegate_internal_interface; sil = new List { new SymbolInfo(dii.invoke_method) }; } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED"); } } List tmp_sil = sil; if (sil != null) { foreach (SymbolInfo si in sil) { if (si.sym_info is common_namespace_function_node) { common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node; if (cnfn.ConnectedToType != null && !cnfn.IsOperator) { exprs.AddElementFirst(exp); skip_first_parameter = true; break; } } if (si.sym_info is compiled_function_node) { compiled_function_node cfn = si.sym_info as compiled_function_node; if (cfn.ConnectedToType != null) { exprs.AddElementFirst(exp); skip_first_parameter = true; if (cfn.is_generic_function) { //generic_convertions.DeduceFunction(cfn, exprs); //si.sym_info = cfn.get_instance(new List(new type_node[] { exp.type }), true, get_location(_method_call)); } break; } } } } if (skip_first_parameter) { List new_sil = new List(); bool has_obj_methods = false; if (sil != null) { foreach (SymbolInfo si in sil) { if (si.sym_info is common_namespace_function_node) { common_namespace_function_node cnfn = si.sym_info as common_namespace_function_node; if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cnfn.ConnectedToType != null) new_sil.Add(si); if (cnfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cnfn.ConnectedToType == null) has_obj_methods = true; } else if (si.sym_info is compiled_function_node) { compiled_function_node cfn = si.sym_info as compiled_function_node; if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static || cfn.ConnectedToType != null) new_sil.Add(si); if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static && cfn.ConnectedToType == null) has_obj_methods = true; } else if (si.sym_info is common_method_node) { common_method_node cfn = si.sym_info as common_method_node; if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) new_sil.Add(si); if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) has_obj_methods = true; } } } if (new_sil.Count() != 0) sil = new_sil; else sil = null; } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion var cen = convert_strong(en); exprs.AddElement(cen); } } expression_node subexpr1 = null; if (to_type != null) { subexpr1 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type); } else { if (iwt != null) { sil = get_generic_functions(sil, true, subloc); sil = get_function_instances(sil, iwt.template_params.params_list, id_right.name, subloc, sil.Count() <= 1); } #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями List spf = null; try { ThrowCompilationError = false; function_node ffn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters); if (ffn == null) { if (skip_first_parameter) { expressions_list ex_list = new expressions_list(); ex_list.AddRange(exprs); ex_list.remove_at(0); // Последний параметр - странный. Глупо искать не в методах расширения если это - метод расширения и мы удаляем затем первый параметр ffn = convertion_data_and_alghoritms.select_function(ex_list, sil, subloc, syntax_nodes_parameters/*,true*/); if (ffn == null) { ThrowCompilationError = true; Errors.Error last_err = LastError(); if (/*last_err is NoFunctionWithSameParametresNum && */ErrorsList.Count > 0) throw LastError(); else throw last_err; } RemoveLastError(); skip_first_parameter = false; exprs = ex_list; ThrowCompilationError = true; } else { ThrowCompilationError = true; throw LastError(); } } ThrowCompilationError = true; int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters != null ? fld.formal_parameters.params_list.Count : 0]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < (fld.formal_parameters != null ? fld.formal_parameters.params_list.Count : 0); k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName, generatedNamesManager); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < (fld.formal_parameters != null ? fld.formal_parameters.params_list.Count:0); k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; if (skip_first_parameter) kk++; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node fn = null; if (!skip_first_parameter /*|| sil.Count() == 1*/) { // exprs.Count = 2; s_n_p = 2; false - не удаляем 1 параметр fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters, false); } else // skip_first_parameter = true { try { ThrowCompilationError = false; // Включая методы расширения // Семантическая разница между exprs.Count и s_n_p.Count равна 1 !!! Только здесь! И вот ее и передавать! // exprs.Count = 3; s_n_p = 2; false - не удаляем 1 параметр // Добавил последний параметр = 1 - это единственное место где длина exprs на 1 больше // Это первый вызов. Будет второй поэтому надо сохранить копию expr до вызова var exprs_copy = exprs.Clone(); fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters, false, 1); if (fn == null && skip_first_parameter) { if (sil.Count() == 1) { ThrowCompilationError = true; throw LastError(); } Errors.Error last_err = LastError(); skip_first_parameter = false; sil = tmp_sil; exprs = exprs_copy; exprs.remove_at(0); // exprs.Count = 2; s_n_p = 2; true - удаляем 1 параметр, пропускаем расширения // Только для методов, исключая методы расширения fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters,true); if (fn == null) { ThrowCompilationError = true; RemoveLastError(); if (last_err is CanNotConvertTypes) { var from_type = (last_err as CanNotConvertTypes).from; foreach (SymbolInfo si in sil) { function_node si_fn = si.sym_info as function_node; if (si_fn != null && si_fn.is_extension_method && si_fn.parameters[0].type == from_type) { throw new NoFunctionWithSameParametresNum(subloc, true, si_fn); } } } throw last_err; } } // Это значит, что нашли метод расширения, но на всякий случай ищем метод поскольку он имеет приоритет else if (fn != null && skip_first_parameter && sil.Count() > 1 && !sil.HasOnlyExtensionMethods()) { var exprs_saved = exprs; // запомнили то что нашли - вдруг здесь не найдем exprs = exprs_copy; // восстановили начальное exprs function_node tmp_fn = fn; exprs.remove_at(0); sil = tmp_sil; // Только для методов, исключая методы расширения fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters,true); // true - удаляем 1 параметр, пропускаем расширения if (fn == null) { fn = tmp_fn; RemoveLastError(); exprs = exprs_saved; // восстановили - т.к. здесь не нашли //exprs.AddElementFirst(exp); } } } catch (Exception ex) { ThrowCompilationError = true; if (skip_first_parameter && !sil.HasOnlyExtensionMethods()) { sil = tmp_sil; exprs.remove_at(0); fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters,true); } else throw ex; } ThrowCompilationError = true; } SemanticTree.IGenericInstance igi = fn as SemanticTree.IGenericInstance; if (igi != null) { //проверяем на соответствие ограничителям int num_err; //CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list( } base_function_call bfc = create_not_static_method_call(fn, exp, get_location(id_right), proc_wait); bfc.parameters.AddRange(exprs); subexpr1 = bfc; } visit_mc_helper(mot, subexpr1, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED",true); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(subexpr1); return; } case motivation.semantic_node_reciving: { return_semantic_value(subexpr1); return; } default: { AddError(subexpr1.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ } case general_node_type.namespace_node: { namespace_node nsn = (namespace_node)sn; if (templ_args_count != 0) { //Ищем generics sil = context.find(id_right.name + StringConstants.generic_params_infix + templ_args_count.ToString()); if (sil != null) { sil = new List { new SymbolInfo(get_generic_instance(sil?.FirstOrDefault(), iwt.template_params.params_list)) }; iwt = null; } } if (sil == null) { SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { sil = nsn.find(name_reflector.get_name(oni_right.operator_type)); } else { sil = nsn.findOnlyInNamespace(id_right.name); if (templ_args_count != 0) { sil = nsn.find(id_right.name + StringConstants.generic_params_infix + templ_args_count.ToString()); if (sil != null) { sil = new List { new SymbolInfo(get_generic_instance(sil?.FirstOrDefault(), iwt.template_params.params_list)) }; iwt = null; } /*SymbolInfo conv = ConvertTypeToInstance(sil?.FirstOrDefault(), iwt.template_params.params_list, get_location(id_right)); if (conv != null) { sil = new List { conv }; iwt = null; }*/ } } } id = id_right; break; } case general_node_type.unit_node: { unit_node un = (unit_node)sn; SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { sil = un.find_only_in_namespace(name_reflector.get_name(oni_right.operator_type)); } else { sil = un.find_only_in_namespace(id_right.name); } id = id_right; break; } case general_node_type.type_node: { type_node tn = (type_node)sn; check_for_type_allowed(tn, get_location(id_right)); SyntaxTree.operator_name_ident oni_right = id_right as SyntaxTree.operator_name_ident; if (oni_right != null) { sil = tn.find_in_type(name_reflector.get_name(oni_right.operator_type), context.CurrentScope); } else { sil = tn.find_in_type(id_right.name, context.CurrentScope);//CurrentScope delete_inherited_constructors(ref sil, tn); delete_extension_methods(ref sil, tn); // SSM 2.2.2016 Пока временно закомментировал - в старом коде этого не было. Из-за этого не работает System.Linq.Enumerable.Select } //definition_node ddn2=check_name_node_type(id_right.name,si,get_location(id_right), // general_node_type.function_node); expression_node exp = null; location subloc = get_location(id_right); if (sil == null) { AddError(new UndefinedNameReference(id_right.name, subloc)); } if (sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(sil.FirstOrDefault().sym_info)); } else { dot_node_as_type_ident(tn, id_right, motivation.expression_evaluation); exp = ret.get_expression(); internal_interface ii = exp.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = ii as delegate_internal_interface; sil = new List { new SymbolInfo(dii.invoke_method) }; } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED"); } } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion exprs.AddElement(convert_strong(en)); } } expression_node subexpr2 = null; if (to_type != null) { subexpr2 = convertion_data_and_alghoritms.explicit_convert_type(exprs[0], to_type); } else { if (iwt != null) { sil = get_generic_functions(sil, true, subloc); sil = get_function_instances(sil, iwt.template_params.params_list, id_right.name, subloc, sil.Count() <= 1); } #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями List spf = null; try { function_node ffn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters); int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } List params_exprs = new List(); foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; if (ffn.parameters[Math.Min(exprCounter, ffn.parameters.Count - 1)].is_params) { LambdaHelper.InferTypesFromVarStmt(ffn.parameters[Math.Min(exprCounter, ffn.parameters.Count - 1)].type.element_type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; if (exprCounter <= ffn.parameters.Count - 1) exprs[exprCounter] = convert_strong(en); else exprs.AddElement(convert_strong(en)); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } else { LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } exprCounter++; } } /*if (params_exprs.Count > 0) { location loc = get_location(_method_call); typeof_operator to = new typeof_operator(params_exprs[0].type, loc); expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(params_exprs.Count, loc)); base_function_call cnfc = retv as base_function_call; foreach (expression_node e in params_exprs) cnfc.parameters.AddElement(e); exprs[exprCounter] = cnfc; }*/ } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; if (skip_first_parameter) { exprCounter++; } expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM var fld_formal_parameters_Count = fld.formal_parameters == null ? 0 : fld.formal_parameters.params_list.Count; object[] realparamstype = new object[fld_formal_parameters_Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld_formal_parameters_Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName, generatedNamesManager); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld_formal_parameters_Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; if (skip_first_parameter) kk++; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters); base_function_call bfc2 = null; if (exp == null) { bfc2 = create_static_method_call(fn, subloc, tn, proc_wait); } else { bfc2 = create_not_static_method_call(fn, exp, subloc, proc_wait); } bfc2.parameters.AddRange(exprs); subexpr2 = bfc2; } visit_mc_helper(mot, subexpr2, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED",true); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(subexpr2); return; } case motivation.semantic_node_reciving: { return_semantic_value(subexpr2); return; } default: { AddError(subexpr2.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ } } } else { SyntaxTree.expression expr = deref_value as SyntaxTree.expression; if (expr != null) { expression_node exp_int = convert_strong(expr); location sloc = get_location(expr); internal_interface ii = exp_int.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(sloc, "EXPECTED_DELEGATE"); } delegate_internal_interface dii = (delegate_internal_interface)ii; sil = new List { new SymbolInfo(dii.invoke_method) }; if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } //lroman// #endregion exprs.AddElement(convert_strong(en)); } } location subloc = sloc; #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями List spf = null; try { function_node ffn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(ffn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fnn = spf[i]; try { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fnn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName, generatedNamesManager); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*compiled_type_node tt; tt = fnn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } // конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } int kk = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion function_node del_func = convertion_data_and_alghoritms.select_function(exprs, sil, sloc, syntax_nodes_parameters); base_function_call bbfc = create_not_static_method_call(del_func, exp_int, sloc, proc_wait); bbfc.parameters.AddRange(exprs); visit_mc_helper(mot, bbfc, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED",true); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bbfc); return; } case motivation.semantic_node_reciving: { return_semantic_value(bbfc); return; } default: { AddError(bbfc.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ } else { throw new CompilerInternalError("Unexpected method name kind"); } } } } //definition_node dn=check_name_node_type(id.name,si,get_location(_method_call),general_node_type.function_node); expression_node exp2 = null; location subloc2 = get_location(id); List sibak = new List(); if (sil != null) sibak.AddRange(sil.GetRange(1, sil.Count() - 1)); if (sil == null) { AddError(new UndefinedNameReference(id.name, subloc2)); } is_format_allowed = false; if (SystemUnitAssigned) { if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(sil) || SystemLibrary.SystemLibInitializer.readln_procedure.Equal(sil)) { expression_node bfcint = make_read_call(sil, _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (sil.FirstOrDefault().sym_info as function_node).name); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ return; } else if (SystemLibrary.SystemLibInitializer.write_procedure.Equal(sil) || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(sil) || SystemLibrary.SystemLibInitializer.print_procedure.Equal(sil) || SystemLibrary.SystemLibInitializer.println_procedure.Equal(sil) || SystemLibrary.SystemLibInitializer.StrProcedure.Equal(sil) ) { is_format_allowed = true; } else if (SystemLibrary.SystemLibInitializer.PascalABCVersion.Equal(sil)) { return_value(new string_const_node(RevisionClass.FullVersion, get_location(_method_call))); return; } else if (SystemLibrary.SystemLibInitializer.ArrayCopyFunction.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind) { location loc = get_location(_method_call); expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ArrayCopyFunction.sym_info as function_node, loc, param0); function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, param0.type, false); en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en); return_value(en); return; } } } else if (SystemLibrary.SystemLibInitializer.SetLengthProcedure.Equal(sil) || SystemLibrary.SystemLibrary.resize_func == sil.FirstOrDefault().sym_info as function_node) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count >= 2) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (!param0.is_addressed) AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.SetLengthForShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(new int_const_node((param0.type as short_string_type_node).Length, null)); visit_mc_helper(mot, cnfn, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ } else if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_kind) { int rank = 1; if (param0.type is compiled_type_node) rank = (param0.type as compiled_type_node).rank; else if (param0.type is common_type_node) rank = (param0.type as common_type_node).rank; if (_method_call.parameters.expressions.Count - 1 != rank) AddError(get_location(_method_call), "{0}_PARAMETERS_EXPECTED", rank + 1); if (rank > 1) { type_node tn = param0.type.element_type; location loc = get_location(_method_call); typeof_operator to = new typeof_operator(tn, loc); List lst = new List(); //размер for (int i = 1; i < _method_call.parameters.expressions.Count; i++) { expression_node expr = convert_strong(_method_call.parameters.expressions[i]); ; expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.integer_type); if (expr is int_const_node && (expr as int_const_node).constant_value < 0) AddError(expr.location, "NEGATIVE_ARRAY_LENGTH_({0})_NOT_ALLOWED", (expr as int_const_node).constant_value); lst.Add(expr); } //это вызов спецфункции expression_node retv = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.NewArrayProcedureDecl, loc, to, new int_const_node(lst.Count, loc)); common_namespace_function_call cnfc = retv as common_namespace_function_call; foreach (expression_node e in lst) cnfc.parameters.AddElement(e); expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.CopyWithSizeFunction.sym_info as function_node, loc, param0, cnfc); function_node fn = convertion_data_and_alghoritms.get_empty_conversion(en.type, retv.type, false); en = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, en); basic_function_call bfc = new basic_function_call(tn.find(StringConstants.assign_name).FirstOrDefault().sym_info as basic_function_node, loc, param0, en); return_value(bfc); return; } } } } else if (SystemLibrary.SystemLibInitializer.InsertProcedure.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3) { //expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); //expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); if (param1.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); param0 = convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.string_type); param2 = convertion_data_and_alghoritms.convert_type(param2, SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.InsertInShortStringProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(param2); cnfn.parameters.AddElement(new int_const_node((param1.type as short_string_type_node).Length, null)); visit_mc_helper(mot, cnfn, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ } } } else if (SystemLibrary.SystemLibInitializer.DeleteProcedure.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 3) { //expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); //expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.short_string) { expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); expression_node param2 = convert_strong(_method_call.parameters.expressions[2]); param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); param2 = convertion_data_and_alghoritms.convert_type(param2, SystemLibrary.SystemLibrary.integer_type); base_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info is common_namespace_function_node) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.DeleteProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); cnfn.parameters.AddElement(param2); visit_mc_helper(mot, cnfn, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(cnfn); return; } default: { AddError(cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ } } } /*else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(sil) || SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 2) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); expression_node param1 = convert_strong(_method_call.parameters.expressions[1]); param1 = convert_if_typed_expression_to_function_call(param1); expressions_list args = new expressions_list(); args.AddElement(param0); args.AddElement(param1); CheckSpecialFunctionCall(sil, args, get_location(_method_call)); expression_node en_cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info is common_namespace_function_node) { common_namespace_function_call cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(sil)) cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); else cnfn = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as common_namespace_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); en_cnfn = cnfn; } else { compiled_static_method_call cnfn = null; if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(sil)) cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.IncludeProcedure.sym_info as compiled_function_node, get_location(_method_call)); else cnfn = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ExcludeProcedure.sym_info as compiled_function_node, get_location(_method_call)); cnfn.parameters.AddElement(param0); cnfn.parameters.AddElement(param1); en_cnfn = cnfn; } visit_mc_helper(mot, en_cnfn, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(en_cnfn); return; } case motivation.semantic_node_reciving: { return_semantic_value(en_cnfn); return; } default: { AddError(en_cnfn.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } } }*/ else if (SystemLibrary.SystemLibInitializer.IncProcedure.Equal(sil)) { expression_node bfcint = make_inc_call(sil?.FirstOrDefault(), _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (sil.FirstOrDefault().sym_info as function_node).name); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ return; } else if (SystemLibrary.SystemLibInitializer.DecProcedure.Equal(sil)) { expression_node bfcint = make_dec_call(sil?.FirstOrDefault(), _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (sil.FirstOrDefault().sym_info as function_node).name); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ return; } else if (SystemLibrary.SystemLibInitializer.SuccFunction.Equal(sil)) { expression_node bfcint = make_succ_call(sil, _method_call.parameters, subloc2); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ return; } else if (SystemLibrary.SystemLibInitializer.PredFunction.Equal(sil)) { expression_node bfcint = make_pred_call(sil, _method_call.parameters, subloc2); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ return; } else if (SystemLibrary.SystemLibInitializer.OrdFunction.Equal(sil)) { expression_node bfcint = make_ord_call(sil, _method_call.parameters, subloc2); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ return; } else if (SystemLibrary.SystemLibInitializer.LowFunction.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), get_location(_method_call)); visit_mc_helper(mot, en, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(en); return; } case motivation.semantic_node_reciving: { return_semantic_value(en); return; } default: { AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ } } } else if (SystemLibrary.SystemLibInitializer.HighFunction.Equal(sil)) { if (_method_call.parameters != null && _method_call.parameters.expressions.Count == 1) { expression_node param0 = convert_strong(_method_call.parameters.expressions[0]); if (param0.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { bounded_array_interface bai = param0.type.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; expression_node en = new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.upper_value), get_location(_method_call)); visit_mc_helper(mot, en, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(en); return; } case motivation.semantic_node_reciving: { return_semantic_value(en); return; } default: { AddError(en.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } } */ } } } else if (sil.FirstOrDefault() == SystemLibrary.SystemLibInitializer.NewProcedure) { expression_node bfcint = make_new_call(sil.FirstOrDefault(), _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (sil.FirstOrDefault().sym_info as function_node).name); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ return; } else if (sil.FirstOrDefault() == SystemLibrary.SystemLibInitializer.DisposeProcedure) { //if (convertion_data_and_alghoritms.select_function(convert_expression_list(_method_call.parameters.expressions), si, subloc2) == SystemLibrary.SystemLibInitializer.DisposeProcedure.sym_info) //{ expression_node bfcint = make_dispose_call(sil.FirstOrDefault(), _method_call.parameters, subloc2); if (!proc_wait) AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", (sil.FirstOrDefault().sym_info as function_node).name); visit_mc_helper(mot, bfcint, get_location(_method_call), exprs, "EXPRESSION_IS_NOT_ADDRESSED"); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(bfcint); return; } case motivation.semantic_node_reciving: { return_semantic_value(bfcint); return; } default: { AddError(bfcint.location, "EXPRESSION_IS_NOT_ADDRESSED"); return; } }*/ return; // } } else if (SystemLibrary.SystemLibInitializer.AssertProcedure.Equal(sil)) { // return_value(new empty_statement(null)); // return; } /*else if (SystemLibrary.SystemLibInitializer.IncProcedure != null && SystemLibrary.SystemLibInitializer.IncProcedure.Equal(si)) { expression_node bfcint = make_inc_call(si, _method_call.parameters, subloc2); }*/ } if (sil.FirstOrDefault().sym_info.general_node_type != general_node_type.function_node) { if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) { to_type = ((type_node)(sil.FirstOrDefault().sym_info)); /*if (to_type == SystemLibrary.SystemLibrary.void_type) { throw new VoidNotValid(subloc2); }*/ check_for_type_allowed(to_type, subloc2); } else { exp2 = ident_value_reciving(sil, id); internal_interface ii = exp2.type.get_internal_interface(internal_interface_kind.delegate_interface); if (ii == null) { AddError(subloc2, "EXPECTED_DELEGATE"); } if (exp2 is nonstatic_event_reference) { nonstatic_event_reference nser = exp2 as nonstatic_event_reference; common_event ce = nser.en as common_event; if (ce != null) exp2 = new class_field_reference(ce.field, new this_node(ce.cont_type, null), null); else AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name); } else if (exp2 is static_event_reference) { static_event_reference nser = exp2 as static_event_reference; common_event ce = nser.en as common_event; if (ce != null) exp2 = new static_class_field_reference(ce.field, null); else if (nser.en is common_namespace_event && _compiled_unit.namespaces.IndexOf((nser.en as common_namespace_event).namespace_node) != -1) exp2 = new namespace_variable_reference((nser.en as common_namespace_event).field, null); else AddError(get_location(_method_call), "EVENT_{0}_MUST_BE_IN_LEFT_PART", nser.en.name); } delegate_internal_interface dii = ii as delegate_internal_interface; sil = new List { new SymbolInfo(dii.invoke_method) }; } } if (to_type != null) { if ((_method_call.parameters == null) || (_method_call.parameters.expressions.Count != 1)) { AddError(get_location(_method_call), "ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED"); } if (proc_wait && to_type.IsDelegate) { var mc = new SyntaxTree.method_call(new SyntaxTree.expression_list()); mc.dereferencing_value = _method_call; procedure_wait = true; visit(mc); return; } } if (_method_call.parameters != null) { foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { bool tmp = is_format_allowed; #region Отмечаем флаг в лямбдах, говорящий о том, что в первый раз будем их "обходить" для вывода типов //lroman// if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode .VisitForInitialMethodCallProcessing; } //lroman// #endregion expression_node sem_en = convert_strong(en); exprs.AddElement(sem_en); is_format_allowed = tmp; } if (SystemLibrary.SystemLibInitializer.AssertProcedure != null && SystemLibrary.SystemLibInitializer.AssertProcedure.Equal(sil) && _method_call.source_context != null) { exprs.AddElement(new string_const_node(_method_call.source_context.FileName, null)); exprs.AddElement(new int_const_node(_method_call.source_context.begin_position.line_num, null)); } } is_format_allowed = false; CheckSpecialFunctionCall(sil, exprs, get_location(_method_call)); sil.RemoveRange(1, sil.Count() - 1); sil.AddRange(sibak); if (to_type != null) { //(ssyy) К вызову функции здесь явно не приводим, т.к. это излишне. expression_node ee = exprs[0]; bool del = to_type is common_type_node && (to_type as common_type_node).IsDelegate; if (!del) try_convert_typed_expression_to_function_call(ref ee); else ee = convert_strong(_method_call.parameters.expressions[0]); expr_node = convertion_data_and_alghoritms.explicit_convert_type(ee, to_type); //expression_node expr = convert_if_typed_expression_to_function_call(exprs[0]); //expr_node = convertion_data_and_alghoritms.explicit_convert_type(expr, to_type); } else { #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_are_in_parameters) { LambdaHelper.processingLambdaParametersForTypeInference++; var sil2 = sil; location mcloc = get_location(_method_call); if (iwt != null) { sil2 = get_generic_functions(sil, true, mcloc); sil2 = get_function_instances(sil2, iwt.template_params.params_list, id.name, mcloc, sil2.Count() <= 1); } // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями List spf = null; SeveralFunctionsCanBeCalled sf_error = null; try { function_node fn = convertion_data_and_alghoritms.select_function(exprs, sil2, subloc2, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; if (fn.parameters.Count <= exprCounter && fn.parameters[fn.parameters.Count - 1].is_params) LambdaHelper.InferTypesFromVarStmt(fn.parameters[fn.parameters.Count - 1].type.element_type, enLambda, this); else if (fn.parameters[exprCounter].is_params) LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type.element_type, enLambda, this); else LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; if (exprs.Count > exprCounter) exprs[exprCounter] = convert_strong(en); else exprs.AddElement(convert_strong(en)); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { sf_error = sf; spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // первый номер правильно инстанцированной. Если потом встретился второй, то тоже ошибка // SSM 4.08.15. Сейчас меняю эту логику. Если будет много кандидатов, но ровно один с совпадающим типом возвращаемого значения, то его и надо выбирать. // не забыть, что аналогичный код есть в create_constructor_call!!!!!!! И еще выше по коду!!! кошмар!!! int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) // цикл по версиям { function_node fn = spf[i]; try // внутренний try регенерирует исключение, а этот гасит { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in _method_call.parameters.expressions) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM var cnt = fld.formal_parameters?.params_list?.Count ?? 0; // SSM 22.06.19 object[] realparamstype = new object[cnt]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < cnt; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; try { LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this); } catch (SimpleSemanticError err) { if (err.ErrorResourceString == "ILLEGAL_LAMBDA_VARIABLE_TYPE" && spf != null) { AddError(new SeveralFunctionsCanBeCalled(sf_error.loc, spf)); } else AddError(err); } fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName, generatedNamesManager); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); // SSM 7/08/15 type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*var tt = fn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < (fld.formal_parameters?.params_list?.Count ?? 0); k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } //--------------- конец цикла по версиям if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(subloc2, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } var kk = 0; foreach (SyntaxTree.expression en in _method_call.parameters.expressions) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; } //lroman// #endregion if (exp2 == null) { location mcloc = get_location(_method_call); if (iwt != null) { sil = get_generic_functions(sil, true, mcloc); sil = get_function_instances(sil, iwt.template_params.params_list, id.name, mcloc, sil.Count() <= 1); } // #2180 - в уникальной ситуации, когда из метода потомка вызывается метод расширения класса-предка добавлять Self (!) // Это значит, что dereferencing_value - это идентификатор и sil состоит только (?) из методов расширения // Надо разделить на две части - для методов расширения добавлять Self. а для не методов - не добавлять // В первом случае окаймить всё try catch и погашать исключение if (_method_call.dereferencing_value is ident) { var silNoExt = sil.Select(s => s.sym_info).Where(s => s is function_node fn && !fn.is_extension_method).ToList(); var silExt = sil.Select(s => s.sym_info).Where(s => s is function_node fn && fn.is_extension_method).ToList(); if (silNoExt.Count > 0) { try { expr_node = convertion_data_and_alghoritms.create_full_function_call(exprs, sil, mcloc, context.converted_type, context.top_function, proc_wait, _method_call.parameters?.expressions); } catch (Exception e) { if (e is CompilationErrorWithLocation && (e as CompilationErrorWithLocation).loc == null) (e as CompilationErrorWithLocation).loc = mcloc; if (silExt.Count == 0) throw; // не проверять в методах расширения, поскольку их нет } } // Сюда мы пришли либо с expr_node != null и тогда в методах расширения искать не надо даже если они есть // либо с expr_node == null и тогда всё будет определяться методами расширения if (silExt.Count > 0 && expr_node == null) { var en0 = convert_strong(new ident("Self",_method_call.dereferencing_value.source_context)); exprs.AddElementFirst(en0); expr_node = convertion_data_and_alghoritms.create_full_function_call(exprs, sil, mcloc, context.converted_type, context.top_function, proc_wait, _method_call.parameters?.expressions); } } else expr_node = convertion_data_and_alghoritms.create_full_function_call(exprs, sil, mcloc, context.converted_type, context.top_function, proc_wait, _method_call.parameters?.expressions); } else { function_node fn = convertion_data_and_alghoritms.select_function(exprs, sil, subloc2, syntax_nodes_parameters); if (!proc_wait && fn.return_value_type == null && exp2 != null && exp2 != null && fn.name == "Invoke") { string del_name = ""; if (exp2 is local_block_variable_reference) del_name = (exp2 as local_block_variable_reference).var.name; else if (exp2 is local_variable_reference) del_name = (exp2 as local_variable_reference).var.name; else if (exp2 is namespace_variable_reference) del_name = (exp2 as namespace_variable_reference).var.name; AddError(subloc2, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", del_name); } base_function_call bbffcc = create_not_static_method_call(fn, exp2, subloc2, proc_wait); bbffcc.parameters.AddRange(exprs); expr_node = bbffcc; } } /*if ((proc_wait==false)&&(expr_node.type==null)) { throw new FunctionExpectedProcedureMeet((function_node)dn,get_location(_method_call)); }*/ visit_mc_helper(mot, expr_node, expr_node.location, exprs, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO",true); return; /*switch (mot) { case motivation.expression_evaluation: { return_value(expr_node); return; } case motivation.semantic_node_reciving: { return_semantic_value(expr_node); return; } case motivation.address_receiving: { AddError(get_location(_method_call), "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); return; } default: { //throw new CompilerInternalError("Can not recive address from method call");//! AddError(get_location(_method_call), "EXPECTED_VARIABLE"); return; } }*/ //throw new CompilerInternalError("Error in creation method call"); } //remove extension methods when static methods called private void delete_extension_methods(ref List sil, type_node tn) { List si_list = new List(); if (sil != null) { foreach (SymbolInfo si in sil) { var fn = si.sym_info as function_node; if (fn != null) { if (fn.is_extension_method) { compiled_function_node cfn = fn as compiled_function_node; if (cfn != null && cfn.cont_type == tn) si_list.Add(si); } else si_list.Add(si); } else si_list.Add(si); /*if (!(fn != null && fn.is_extension_method)) si_list.Add(tmp_si);*/ } sil = si_list; if(si_list.Count == 0) sil = null; } /*tmp_si = si; while (tmp_si != null) { var fn = tmp_si.sym_info as function_node; if (fn != null && fn.is_extension_method) { var b = false; foreach (var x in si_list) { var xn = x.sym_info as function_node; if (convertion_data_and_alghoritms.function_eq_params(fn, xn)) { b = true; break; } } if (!b) si_list.Add(tmp_si); } tmp_si = tmp_si.Next; }*/ } //ssyy //Удаляет конструкторы предков в списке si private void delete_inherited_constructors(ref List si, type_node tn) { int cur_ind = 0; while (si!= null && cur_ind < si.Count()) { type_node comph_type = null; bool is_ctor = false; common_method_node mnode = si[cur_ind].sym_info as common_method_node; if (mnode != null) { comph_type = mnode.cont_type; is_ctor = mnode.is_constructor; } else { compiled_function_node tnode = si[cur_ind].sym_info as compiled_function_node; if (tnode != null) { comph_type = tnode.cont_type; is_ctor = tnode.method_info.IsConstructor; } } //Итак, comph_type - класс, содержащий si.sym_info; //is_ctor - является ли оно конструктором if (is_ctor && comph_type != tn) { //Удаляем si.RemoveAt(cur_ind); } else ++cur_ind; } if (si != null && si.FirstOrDefault() == null) si = null; } //\ssyy //TODO: Возможно следует переписать этот метод в более простой форме. public override void visit(SyntaxTree.method_call _method_call) { visit_method_call(_method_call); inherited_ident_processing = false; } private void ConvertPointersForWrite(expressions_list exprs) { for (int i = 0; i < exprs.Count; ++i) { if (exprs[i].type.IsPointer) { if (SystemLibrary.SystemLibInitializer.PointerOutputConstructor == null) { List sil = (SystemLibrary.SystemLibInitializer.PointerOutputType.sym_info as common_type_node).find_in_type(default_constructor_name); common_method_node cnode = null; int cur_si_ind = 0; do { cnode = sil[cur_si_ind].sym_info as common_method_node; if (cnode.parameters.Count != 1) { cnode = null; ++cur_si_ind; } } while (cnode == null); SystemLibrary.SystemLibInitializer.PointerOutputConstructor = cnode; } common_constructor_call cnc = new common_constructor_call(SystemLibrary.SystemLibInitializer.PointerOutputConstructor as common_method_node, exprs[i].location); //common_namespace_function_call cnfc = new common_namespace_function_call( // SystemLibrary.SystemLibInitializer.PointerToStringFunction.sym_info as common_namespace_function_node, // exprs[i].location); cnc.parameters.AddElement(exprs[i]); exprs[i] = cnc; } } } private void ConvertPointersForWriteFromDll(expressions_list exprs) { for (int i = 0; i < exprs.Count; ++i) { if (exprs[i].type.IsPointer) { if (SystemLibrary.SystemLibInitializer.PointerOutputConstructor == null) { List sil = (SystemLibrary.SystemLibInitializer.PointerOutputType.sym_info as compiled_type_node).find_in_type(default_constructor_name); compiled_constructor_node cnode = null; int cur_si_index = 0; do { cnode = sil[cur_si_index].sym_info as compiled_constructor_node; if (cnode.parameters.Count != 1) { cnode = null; ++cur_si_index; } } while (cnode == null); SystemLibrary.SystemLibInitializer.PointerOutputConstructor = cnode; } compiled_constructor_call cnc = new compiled_constructor_call(SystemLibrary.SystemLibInitializer.PointerOutputConstructor as compiled_constructor_node, exprs[i].location); //common_namespace_function_call cnfc = new common_namespace_function_call( // SystemLibrary.SystemLibInitializer.PointerToStringFunction.sym_info as common_namespace_function_node, // exprs[i].location); cnc.parameters.AddElement(exprs[i]); exprs[i] = cnc; } } } private void CheckSpecialFunctionCall(List sil, expressions_list exprs, location loc) { string FunctionName = ""; if (sil != null && sil.Count > 0 && sil[0].sym_info is function_node) FunctionName = (sil[0].sym_info as function_node).name; if (SystemUnitAssigned) { bool write_proc = SystemLibrary.SystemLibInitializer.write_procedure.Equal(sil); if (write_proc && exprs.Count > 1) { //возможно это запись в типизированый файл if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.typed_file) //да, точно это типизированый файл! { //Проверим типы параметров вызова на совпадение с типом элементов файла type_node element_type = exprs[0].type.element_type; for (int i = 1; i < exprs.Count; i++) convertion_data_and_alghoritms.check_convert_type(exprs[i], element_type, exprs[i].location); if (element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { for (int i = 1; i < exprs.Count; i++) { //common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null); //cmc.parameters.AddElement(exprs[i]); //cmc.parameters.AddElement(new int_const_node((element_type as short_string_type_node).Length,null)); expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(exprs[i], SystemLibrary.SystemLibrary.string_type), new int_const_node((element_type as short_string_type_node).Length, null)); exprs[i] = cmc; } } //if (exprs[i].type != element_type) // throw new ExpectedExprHaveTypeTypedFile(element_type, exprs[i].type, false, get_location(_method_call.parameters.expressions[i])); } else //(ssyy) а может быть, в бинарный! if (exprs[0].type.type_special_kind == SemanticTree.type_special_kind.binary_file) { //(ssyy) действительно, бинарный for (int i = 1; i < exprs.Count; i++) { if (!CanUseThisTypeForBinaryFiles(exprs[i].type)) { AddError(exprs[i].location, "CAN_NOT_WRITE_REFERENCE_DATA_TO_BINARY_FILE"); } } } else { if (SystemLibrary.SystemLibInitializer.write_procedure.sym_info is common_namespace_function_node) ConvertPointersForWrite(exprs); else ConvertPointersForWriteFromDll(exprs); } } else if (write_proc || SystemLibrary.SystemLibInitializer.writeln_procedure.Equal(sil)) { //(ssyy) Преобразуем указатели в строки для вывода write/writeln if (SystemLibrary.SystemLibInitializer.writeln_procedure.sym_info is common_namespace_function_node) ConvertPointersForWrite(exprs); else ConvertPointersForWriteFromDll(exprs); } /*else if (SystemLibrary.SystemLibInitializer.IncludeProcedure.Equal(sil) || SystemLibrary.SystemLibInitializer.ExcludeProcedure.Equal(sil)) { if (exprs.Count != 2) AddError(new NoFunctionWithSameArguments(FunctionName, loc, true)); type_node element_type = exprs[0].type.element_type; if (exprs[0].type.type_special_kind != SemanticTree.type_special_kind.base_set_type && exprs[0].type.type_special_kind != SemanticTree.type_special_kind.set_type) { AddError(new NoFunctionWithSameArguments(FunctionName, loc, true)); } if (element_type != null) convertion_data_and_alghoritms.check_convert_type(exprs[1], element_type, exprs[1].location); else convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[0].location); if (!exprs[0].is_addressed) AddError(new ThisExpressionCanNotBePassedAsVarParameter(exprs[0])); }*/ else if (SystemLibrary.SystemLibInitializer.InSetProcedure.Equal(sil)) { if (exprs.Count != 2) AddError(new NoFunctionWithSameArguments(FunctionName, loc, true)); type_node element_type = exprs[1].type.element_type; if (element_type != null) { //exprs[0] = convertion_data_and_alghoritms.convert_type(exprs[0], element_type, exprs[0].location); convertion_data_and_alghoritms.check_convert_type(exprs[0], element_type, exprs[0].location); } else convertion_data_and_alghoritms.check_convert_type(exprs[0], exprs[1].type, exprs[0].location); } else if (SystemLibrary.SystemLibInitializer.SetUnionProcedure.Equal(sil) || SystemLibrary.SystemLibInitializer.SetIntersectProcedure.Equal(sil) || SystemLibrary.SystemLibInitializer.SetSubtractProcedure.Equal(sil)) { if (exprs.Count != 2) AddError(new NoFunctionWithSameArguments(FunctionName, loc, true)); convertion_data_and_alghoritms.check_convert_type(exprs[1], exprs[0].type, exprs[1].location); } if (sil.FirstOrDefault() == SystemLibrary.SystemLibInitializer.NewProcedure || sil.FirstOrDefault() == SystemLibrary.SystemLibInitializer.DisposeProcedure) { if (exprs[0].type == SystemLibrary.SystemLibrary.pointer_type) AddError(exprs[0].location, "EXPECTED_TYPED_POINTER_IN_PROCEDURE{0}", (sil.FirstOrDefault().sym_info as function_node).name); } } } private expression_node make_new_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) AddError( new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node)); if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (!param0.type.IsPointer || param0.type == SystemLibrary.SystemLibrary.pointer_type) AddError(new NoFunctionWithSameArguments("New", loc, true)); if (!param0.is_addressed) { bool is_pascal_array_ref = false; if (param0.semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)param0; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); param0 = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } if (!is_pascal_array_ref) { AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); } } else AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); } if (param0.type is ref_type_node && !can_evaluate_size((param0.type as ref_type_node).pointed_type)) AddError(loc, "CANNOT_CALL_NEW_BECAUSE_OF_UNDEFINED_SIZE"); function_node fn = si.sym_info as function_node; common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node)); return null; } } private expression_node make_dispose_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node)); return null; } if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (!param0.type.IsPointer || param0.type == SystemLibrary.SystemLibrary.pointer_type) AddError(new NoFunctionWithSameArguments("Dispose", loc, true)); if (!param0.is_addressed) { bool is_pascal_array_ref = false; if (param0.semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)param0; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); param0 = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } if (!is_pascal_array_ref) { AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); return null; } } else { AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); return null; } } function_node fn = si.sym_info as function_node; common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node)); return null; } } private expression_node make_ord_call(List sil, SyntaxTree.expression_list parameters, location loc) { string FunctionName = ""; if (sil != null && sil.Count > 0 && sil[0].sym_info is function_node) FunctionName = (sil[0].sym_info as function_node).name; if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, sil.FirstOrDefault().sym_info as function_node)); return null; } if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression); expressions_list el = new expressions_list(); el.AddElement(param0); function_node fn = null; try { fn = convertion_data_and_alghoritms.select_function(el, sil, loc); } catch (Exception e) { } if (fn != null) { if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } } else if (param0.type.IsEnum || param0.type.type_special_kind == SemanticTree.type_special_kind.diap_type) { el = new expressions_list(); el.AddElement(new int_const_node(1, null)); fn = convertion_data_and_alghoritms.select_function(el, sil, loc); //bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); //bfc.ret_type = param0.type; if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } } else { AddError(new NoFunctionWithSameArguments(FunctionName, loc, false)); return null; } } else { AddError(new NoFunctionWithSameParametresNum(loc, false, sil.FirstOrDefault().sym_info as function_node)); return null; } } private expression_node make_succ_call(List sil, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, sil.FirstOrDefault().sym_info as function_node)); return null; } if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression); basic_function_call bfc = null; int type_flag = 0; expressions_list el = new expressions_list(); el.AddElement(param0); function_node fn = null; try { fn = convertion_data_and_alghoritms.select_function(el,sil,loc); } catch(Exception e) { } if (fn != null) { if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } } if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { el = new expressions_list(); el.AddElement(new int_const_node(1,null)); fn = convertion_data_and_alghoritms.select_function(el,sil,loc); //bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); //bfc.ret_type = param0.type; if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } } else AddError(new NoFunctionWithSameArguments("Succ", loc,false)); bfc.parameters.AddElement(param0); if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1,null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1,null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1,null)); return bfc; } AddError(new NoFunctionWithSameParametresNum(loc,false,sil.FirstOrDefault().sym_info as function_node)); return null; } private expression_node make_pred_call(List sil, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, sil.FirstOrDefault().sym_info as function_node)); return null; } if (parameters.expressions.Count == 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0 is typed_expression) param0 = convert_typed_expression_to_function_call(param0 as typed_expression); basic_function_call bfc = null; int type_flag = 0; expressions_list el = new expressions_list(); el.AddElement(param0); function_node fn = null; try { fn = convertion_data_and_alghoritms.select_function(el,sil,loc); } catch(Exception e) { } if (fn != null) { if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); return cnfc; } } else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { el = new expressions_list(); el.AddElement(new int_const_node(1,null)); fn = convertion_data_and_alghoritms.select_function(el,sil,loc); //bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); //bfc.ret_type = param0.type; if (fn is common_namespace_function_node) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } else { compiled_static_method_call cnfc = new compiled_static_method_call(fn as compiled_function_node, loc); cnfc.parameters.AddElement(param0); cnfc.type = param0.type; return cnfc; } } else AddError(new NoFunctionWithSameArguments("Pred",loc,false)); bfc.parameters.AddElement(param0); if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1,null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1,null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1,null)); return bfc; } AddError(new NoFunctionWithSameParametresNum(loc,false,sil.FirstOrDefault().sym_info as function_node)); return null; } private expression_node make_inc_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) { AddError(new NoFunctionWithSameParametresNum(loc, false, si.sym_info as function_node)); return null; } if (parameters.expressions.Count == 1 || parameters.expressions.Count == 2) { expression_node param0 = convert_strong(parameters.expressions[0]); if (!param0.is_addressed) { bool is_pascal_array_ref = false; if (param0.semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)param0; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); param0 = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } if (!is_pascal_array_ref) { AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); } } else if (param0 is compiled_function_call) { compiled_function_call cfc = param0 as compiled_function_call; if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type && cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function)) { expressions_list exl = new expressions_list(); exl.AddElement(cfc.obj); exl.AddElement(cfc.parameters[0]); basic_function_call bfc2 = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); bfc2.parameters.AddElement(param0); expression_node _param1 = null; if (parameters.expressions.Count == 2) { _param1 = convert_strong(parameters.expressions[1]); } if (_param1 != null) bfc2.parameters.AddElement(convertion_data_and_alghoritms.convert_type(_param1,SystemLibrary.SystemLibrary.integer_type)); else bfc2.parameters.AddElement(new int_const_node(1,null)); expressions_list el = new expressions_list(); el.AddElement(convertion_data_and_alghoritms.convert_type(bfc2,SystemLibrary.SystemLibrary.ushort_type)); function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc); exl.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray())); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return ret; } else { AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); } } else AddError(new ThisExpressionCanNotBePassedAsVarParameter(param0)); } else check_on_loop_variable(param0); expression_node param1 = null; int type_flag = 0; bool is_uint = false; bool is_enum = false; if (parameters.expressions.Count == 2) { param1 = convert_strong(parameters.expressions[1]); //param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type); } basic_function_call ass = null; basic_function_call bfc = null; if (param0.type == SystemLibrary.SystemLibrary.integer_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.char_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.char_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.byte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.byte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.sbyte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.sbyte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.short_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.short_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.ushort_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ushort_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.uint_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.uint_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.uint_add as basic_function_node,loc); type_flag = 2; is_uint = true; } else if (param0.type == SystemLibrary.SystemLibrary.int64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.long_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.long_add as basic_function_node,loc); type_flag = 1; } else if (param0.type == SystemLibrary.SystemLibrary.uint64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ulong_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.ulong_add as basic_function_node,loc); type_flag = 2; } else if (param0.type == SystemLibrary.SystemLibrary.bool_type) { if (param1 == null) { ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); type_flag = 4; } else { basic_function_call mod_expr = new basic_function_call(SystemLibrary.SystemLibrary.int_mod as basic_function_node,loc); mod_expr.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type)); mod_expr.parameters.AddElement(new int_const_node(2,loc)); basic_function_call condition = new basic_function_call(SystemLibrary.SystemLibrary.int_eq as basic_function_node,loc); condition.parameters.AddElement(mod_expr); condition.parameters.AddElement(new int_const_node(0,loc)); basic_function_call not_expr = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); not_expr.parameters.AddElement(param0); question_colon_expression qce = new question_colon_expression(condition, param0, not_expr, loc); ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); ass.parameters.AddElement(param0); ass.parameters.AddElement(qce); type_flag = 5; } } else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_add as basic_function_node,loc); if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type) { type_node bt = param0.type.base_type; if (bt == SystemLibrary.SystemLibrary.int64_type) type_flag = 1; else if (bt == SystemLibrary.SystemLibrary.uint64_type) type_flag = 2; else if (bt == SystemLibrary.SystemLibrary.uint_type) { type_flag =2; is_uint = true; } else if (bt.IsEnum) { is_enum = true; } } else if (param0.type.IsEnum) is_enum = true; } else AddError(new NoFunctionWithSameArguments("Inc",loc,false)); if (type_flag != 5) { if (param1 != null) switch (type_flag) { case 0: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); break; case 3: case 1: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.int64_type); break; case 2: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.uint64_type); break; } if (param0.type != SystemLibrary.SystemLibrary.char_type && !is_enum && param0.type != SystemLibrary.SystemLibrary.bool_type) switch (type_flag) { case 0: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.integer_type)); break; case 3: case 1: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.int64_type)); break; case 2: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.uint64_type)); break; } else bfc.parameters.AddElement(param0); //bfc.parameters.AddElement(param0); if (param1 == null) { if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1, null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1, null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1, null)); } else bfc.parameters.AddElement(param1); ass.parameters.AddElement(param0); if (is_uint) ass.parameters.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.uint_type)); else if (param0.type == SystemLibrary.SystemLibrary.char_type) { expressions_list el = new expressions_list(); el.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.ushort_type)); function_node chr_func = convertion_data_and_alghoritms.select_function(el, SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc); ass.parameters.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray())); } else ass.parameters.AddElement(bfc); } return ass; } AddError(new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node)); return null; } private expression_node make_dec_call(SymbolInfo si, SyntaxTree.expression_list parameters, location loc) { if (parameters == null) throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node); if (parameters.expressions.Count == 1 || parameters.expressions.Count == 2) { expression_node param0 = convert_strong(parameters.expressions[0]); if (!param0.is_addressed) { bool is_pascal_array_ref = false; if (param0.semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)param0; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); param0 = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } if (!is_pascal_array_ref) { throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } } else if (param0 is compiled_function_call) { compiled_function_call cfc = param0 as compiled_function_call; if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type && cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function)) { expressions_list exl = new expressions_list(); exl.AddElement(cfc.obj); exl.AddElement(cfc.parameters[0]); basic_function_call bfc2 = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); bfc2.parameters.AddElement(param0); expression_node _param1 = null; if (parameters.expressions.Count == 2) { _param1 = convert_strong(parameters.expressions[1]); } if (_param1 != null) bfc2.parameters.AddElement(convertion_data_and_alghoritms.convert_type(_param1,SystemLibrary.SystemLibrary.integer_type)); else bfc2.parameters.AddElement(new int_const_node(1,null)); expressions_list el = new expressions_list(); el.AddElement(convertion_data_and_alghoritms.convert_type(bfc2,SystemLibrary.SystemLibrary.ushort_type)); function_node chr_func = convertion_data_and_alghoritms.select_function(el,SystemLibrary.SystemLibInitializer.ChrUnicodeFunction.SymbolInfo, loc); exl.AddElement(convertion_data_and_alghoritms.create_simple_function_call(chr_func, loc, el.ToArray())); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.SymbolInfo, loc); expression_node ret = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, exl.ToArray()); return ret; } else { throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } } else throw new ThisExpressionCanNotBePassedAsVarParameter(param0); } else check_on_loop_variable(param0); expression_node param1 = null; int type_flag = 0; bool is_uint=false; bool is_enum=false; if (parameters.expressions.Count == 2) { param1 = convert_strong(parameters.expressions[1]); param1 = convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type); } basic_function_call ass = null; basic_function_call bfc = null; if (param0.type == SystemLibrary.SystemLibrary.integer_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.char_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.char_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.byte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.byte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.sbyte_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.sbyte_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.short_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.short_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.ushort_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ushort_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); } else if (param0.type == SystemLibrary.SystemLibrary.uint_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.uint_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.uint_sub as basic_function_node,loc); type_flag = 2; is_uint = true; } else if (param0.type == SystemLibrary.SystemLibrary.int64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.long_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.long_sub as basic_function_node,loc); type_flag = 1; } else if (param0.type == SystemLibrary.SystemLibrary.uint64_type) { ass = new basic_function_call(SystemLibrary.SystemLibrary.ulong_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.ulong_sub as basic_function_node,loc); type_flag = 2; } else if (param0.type == SystemLibrary.SystemLibrary.bool_type) { if (param1 == null) { ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); type_flag = 4; } else { basic_function_call mod_expr = new basic_function_call(SystemLibrary.SystemLibrary.int_mod as basic_function_node,loc); mod_expr.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param1,SystemLibrary.SystemLibrary.integer_type)); mod_expr.parameters.AddElement(new int_const_node(2,loc)); basic_function_call condition = new basic_function_call(SystemLibrary.SystemLibrary.int_eq as basic_function_node,loc); condition.parameters.AddElement(mod_expr); condition.parameters.AddElement(new int_const_node(0,loc)); basic_function_call not_expr = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node,loc); not_expr.parameters.AddElement(param0); question_colon_expression qce = new question_colon_expression(condition, param0, not_expr, loc); ass = new basic_function_call(SystemLibrary.SystemLibrary.bool_assign as basic_function_node,loc); ass.parameters.AddElement(param0); ass.parameters.AddElement(qce); type_flag = 5; } } else if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type || param0.type.IsEnum) { ass = new basic_function_call(SystemLibrary.SystemLibrary.int_assign as basic_function_node,loc); bfc = new basic_function_call(SystemLibrary.SystemLibrary.int_sub as basic_function_node,loc); if (param0.type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.diap_type) { type_node bt = param0.type.base_type; if (bt == SystemLibrary.SystemLibrary.int64_type) type_flag = 1; else if (bt == SystemLibrary.SystemLibrary.uint64_type) type_flag = 2; else if (bt == SystemLibrary.SystemLibrary.uint_type) { type_flag =2; is_uint = true; } else if (bt.IsEnum) is_enum = true; } else if (param0.type.IsEnum) is_enum = true; } else throw new NoFunctionWithSameArguments("Dec",loc,false); if (type_flag != 5) { if (param1 != null) switch (type_flag) { case 0: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.integer_type); break; case 3: case 1: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.int64_type); break; case 2: param1 = convertion_data_and_alghoritms.convert_type(param1, SystemLibrary.SystemLibrary.uint64_type); break; } //bfc.parameters.AddElement(param0); if (param0.type != SystemLibrary.SystemLibrary.char_type && !is_enum && param0.type != SystemLibrary.SystemLibrary.bool_type) switch (type_flag) { case 0: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.integer_type)); break; case 3: case 1: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.int64_type)); break; case 2: bfc.parameters.AddElement(convertion_data_and_alghoritms.convert_type(param0, SystemLibrary.SystemLibrary.uint64_type)); break; } else bfc.parameters.AddElement(param0); if (param1 == null) { if (type_flag == 0 || type_flag == 3) bfc.parameters.AddElement(new int_const_node(1, null)); else if (type_flag == 1) bfc.parameters.AddElement(new long_const_node(1, null)); else if (type_flag == 2) bfc.parameters.AddElement(new ulong_const_node(1, null)); } else bfc.parameters.AddElement(param1); ass.parameters.AddElement(param0); if (is_uint) ass.parameters.AddElement(convertion_data_and_alghoritms.convert_type(bfc, SystemLibrary.SystemLibrary.uint_type)); else ass.parameters.AddElement(bfc); } return ass; } throw new NoFunctionWithSameParametresNum(loc,false,si.sym_info as function_node); } private void check_on_loop_variable(expression_node en) { if (context.is_in_cycle() && !SemanticRulesConstants.AllowChangeLoopVariable) if (en.semantic_node_type == semantic_node_type.namespace_variable_reference) { if (context.is_loop_variable((en as namespace_variable_reference).var)) AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } else if (en.semantic_node_type == semantic_node_type.local_variable_reference) { if (context.is_loop_variable((en as local_variable_reference).var)) AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } else if (en.semantic_node_type == semantic_node_type.local_block_variable_reference) { if (context.is_loop_variable((en as local_block_variable_reference).var)) AddError(en.location, "CANNOT_ASSIGN_TO_LOOP_VARIABLE"); } } private expression_node make_read_call(List sil, SyntaxTree.expression_list parameters, location loc) { // вызов read(a,b,c) разбивается на несколько вызовов, последний возвращается узлом, а остальные добавляются здесь в теле expressions_list exl = new expressions_list(); expression_node last_call = null; expressions_list exl = new expressions_list(); expression_node file = null; bool read_from_file = false; bool read_from_text_file = false; bool read_from_typed_file = false; bool read_from_binary_file = false; bool readln_string_file = false; if (parameters != null) // если список параметров не пуст { if (parameters.expressions.Count >= 1) { expression_node param0 = convert_strong(parameters.expressions[0]); if (param0.type != null) { if (SystemLibrary.SystemLibInitializer.TextFileType.Found && param0.type == SystemLibrary.SystemLibInitializer.TextFileType.sym_info) { file = param0; read_from_text_file = true; } if (param0.type.type_special_kind == SemanticTree.type_special_kind.typed_file && parameters.expressions.Count > 1 //это можно внести во внутрь )//и побросать приличные исключения { if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll) { if (sil.SequenceEqual(SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo)) { file = param0; read_from_typed_file = true; } } else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(sil)) { file = param0; read_from_typed_file = true; } } if (param0.type.type_special_kind == SemanticTree.type_special_kind.binary_file && parameters.expressions.Count > 1 //это можно внести во внутрь )//и побросать приличные исключения { if (!SystemLibrary.SystemLibInitializer.read_procedure.FromDll) { if (sil.SequenceEqual(SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo)) { file = param0; read_from_binary_file = true; } } else if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(sil)) { file = param0; read_from_binary_file = true; } } } read_from_file = read_from_text_file || read_from_typed_file || read_from_binary_file; } bool first_iteration = true; foreach (SyntaxTree.expression ex in parameters.expressions) { if (first_iteration && read_from_file) { first_iteration = false; continue; } if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.Count > 0) convertion_data_and_alghoritms.statement_list_stack.Peek().statements.AddElement(last_call); expression_node en = convert_strong(ex); check_on_loop_variable(en); //if (en.type == null) //throw new CanNotRead(en.location); exl.Clear(); if (read_from_file) exl.AddElement(file); if (read_from_typed_file) { if (SystemLibrary.SystemLibInitializer.TypedFileReadProcedure == null) AddError(new NotSupportedError(loc)); if (en.type != file.type.element_type) AddError(new ExpectedExprHaveTypeTypedFile(file.type.element_type, en.type, true, get_location(ex))); bool is_char_getter = false; if (!en.is_addressed) { if (en is compiled_function_call) { compiled_function_call cfc = en as compiled_function_call; if ((cfc.function_node.return_value_type == SystemLibrary.SystemLibrary.char_type && cfc.function_node.cont_type == SystemLibrary.SystemLibrary.string_type && cfc.function_node == cfc.function_node.cont_type.default_property_node.get_function)) { en = new simple_array_indexing((en as compiled_function_call).obj, (en as compiled_function_call).parameters[0], SystemLibrary.SystemLibrary.char_type, en.location); is_char_getter = true; } } } function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), file); //expression_node expr = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.TypedFileReadProcedure.SymbolInfo, loc, context.converted_type, context.top_function, true); expr = convertion_data_and_alghoritms.explicit_convert_type(expr, file.type.element_type); if (is_char_getter) expr = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.StringDefaultPropertySetProcedure.sym_info as function_node, loc, (en as simple_array_indexing).simple_arr_expr, (en as simple_array_indexing).ind_expr, expr); else expr = find_operator(StringConstants.assign_name, en, expr, loc); last_call = expr; } else if (read_from_binary_file) { if (SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure == null) AddError(new NotSupportedError(loc)); if (!CanUseThisTypeForBinaryFiles(en.type)) { AddError(en.location, "CAN_NOT_READ_REFERENCE_DATA_FROM_BINARY_FILE"); } exl.AddElement(new typeof_operator(en.type, loc)); function_node fn = convertion_data_and_alghoritms.select_function(exl,SystemLibrary.SystemLibInitializer.BinaryFileReadProcedure.SymbolInfo, loc); expression_node expr = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); expr = convertion_data_and_alghoritms.explicit_convert_type(expr, en.type); expr = find_operator(StringConstants.assign_name, en, expr, loc); last_call = expr; } else { exl.AddElement(en); try { function_node fn = null; if (en.type.type_special_kind == SemanticTree.type_special_kind.short_string) { exl.AddElement(new int_const_node((en.type as short_string_type_node).Length,null)); if (!read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_procedure.sym_info as function_node,get_location(ex),exl.ToArray()); else last_call = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.read_short_string_from_file_procedure.sym_info as function_node,get_location(ex),exl.ToArray()); } else if (en.type.type_special_kind == SemanticTree.type_special_kind.diap_type) { exl.remove(en); en.type = en.type.base_type; exl.AddElement(en); fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); } else { /// SSM 21/05/16 - read_from_text_file && - bug fix #161 if (read_from_text_file && SystemLibrary.SystemLibInitializer.readln_procedure.Equal(sil) && parameters.expressions.Count == 2 && en.type == SystemLibrary.SystemLibrary.string_type) { fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc); readln_string_file = true; } else fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, get_location(ex), exl.ToArray()); } //last_call = convertion_data_and_alghoritms.create_full_function_call(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc, context.converted_type, context.top_function, true); } catch (NoFunctionWithSameArguments) { AddError(en.location, "CAN_NOT_READ"); } } first_iteration = false; } } if ((parameters == null) || (parameters.expressions.Count == 0)) // read(), readln() { if (SystemLibrary.SystemLibInitializer.read_procedure.Equal(sil)) { if (read_from_file) exl.AddElement(file); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.read_procedure.SymbolInfo, loc); if (read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file); else last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc); } } if (SystemLibrary.SystemLibInitializer.readln_procedure.Equal(sil)) // readln(...) { if (!readln_string_file) { if (last_call != null && convertion_data_and_alghoritms.statement_list_stack.Count > 0) convertion_data_and_alghoritms.statement_list_stack.Peek().statements.AddElement(last_call); exl.Clear(); if (read_from_file) exl.AddElement(file); function_node fn = convertion_data_and_alghoritms.select_function(exl, SystemLibrary.SystemLibInitializer.readln_procedure.SymbolInfo, loc); if (read_from_file) last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc, file); else last_call = convertion_data_and_alghoritms.create_simple_function_call(fn, loc); } } return last_call; } internal expression_node GetCurrentObjectReference(SymbolTable.Scope scope, definition_node dn, location loc) { if (context.WithSection) if (scope != null) if (context.WithVariables.ContainsKey(scope)) return context.WithVariables[scope]; else if (context.WithTypes.Contains(scope)) { switch (dn.semantic_node_type) { case semantic_node_type.class_field: if (!(dn as class_field).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field, loc, null)); break; case semantic_node_type.compiled_variable_definition: if (!(dn as compiled_variable_definition).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field, loc, null)); break; case semantic_node_type.compiled_property_node: case semantic_node_type.common_property_node: if ((dn as property_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticPropertyWithType(dn as property_node, loc, null)); break; case semantic_node_type.compiled_function_node: case semantic_node_type.common_method_node: if ((dn as function_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticMethodWithType((dn as function_node).name, loc)); break; } } if (context.static_variable_converted) { AddError(new CanNotReferenceToNonStaticFromStaticInitializer(dn, loc)); return null; } else if (context.inStaticArea()) { AddError(new CanNotReferenceToNonStaticFromStatic(dn, loc)); return null; } else return new this_node(context.converted_type, loc); } private expression_node create_with_expression(expression_node expr) { location sl = expr.location; switch (expr.semantic_node_type) { case semantic_node_type.common_namespace_function_call: case semantic_node_type.common_in_function_function_call: case semantic_node_type.common_method_call: case semantic_node_type.common_static_method_call: case semantic_node_type.compiled_function_call: case semantic_node_type.compiled_constructor_call: case semantic_node_type.common_constructor_call: case semantic_node_type.compiled_static_method_call: return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(GetTempVariableName(), sl, expr.type, expr), sl); case semantic_node_type.class_field_reference: (expr as class_field_reference).obj = create_with_expression((expr as class_field_reference).obj); return expr; case semantic_node_type.compiled_variable_reference: (expr as compiled_variable_reference).obj = create_with_expression((expr as compiled_variable_reference).obj); return expr; case semantic_node_type.simple_array_indexing: simple_array_indexing sar = expr as simple_array_indexing; sar.simple_arr_expr = create_with_expression(sar.simple_arr_expr); sar.ind_expr = create_with_expression(sar.ind_expr); return sar; case semantic_node_type.deref_node: (expr as dereference_node).deref_expr = create_with_expression((expr as dereference_node).deref_expr); return expr; case semantic_node_type.basic_function_call: return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(GetTempVariableName(), sl, expr.type, expr), sl); case semantic_node_type.as_node: return convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(GetTempVariableName(), sl, expr.type, expr), sl); } return expr; } private string GetTempVariableName() { return generatedNamesManager.GenerateName("$TV", "$"); } public override void visit(SyntaxTree.with_statement _with_statement) { context.WithSection = true; List Withs = new List(); List VarRefs = new List(); List WithTypesList = new List(); statements_list stl = new statements_list(get_location(_with_statement.do_with), null, null); SymbolTable.WithScope WithScope = new SymbolTable.WithScope(SymbolTable, context.CurrentScope, null); convertion_data_and_alghoritms.statement_list_stack_push(stl, WithScope); foreach (SyntaxTree.expression s_expr in _with_statement.do_with.expressions) { //expression_node expr = ret.visit(s_expr); var mot = motivation_keeper.motivation; motivation_keeper.set_motivation_to_expect_semantic_node(); semantic_node sn = ret.visit(s_expr as SyntaxTree.syntax_tree_node); motivation_keeper.reset(); expression_node expr = sn as expression_node; if (expr is null_const_node) AddError(expr.location, "NIL_IN_THIS_CONTEXT_NOT_ALLOWED"); if (expr is typed_expression) expr = convert_typed_expression_to_function_call(expr as typed_expression); if (expr != null) { if (expr.type is generic_instance_type_node) AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH"); variable_reference vr = expr as variable_reference; if (expr.type == null) AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH"); if (expr.type is ref_type_node) AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH"); if (vr == null) { location sl = get_location(s_expr); if (expr.type.type_special_kind != SemanticTree.type_special_kind.record) vr = convertion_data_and_alghoritms.CreateVariableReference(context.add_var_definition(GetTempVariableName(), sl, expr.type, expr), sl); else expr = create_with_expression(expr); } if (vr != null && vr is class_field_reference && vr.type.type_special_kind == SemanticTree.type_special_kind.record) { vr = null; expr = create_with_expression(expr); } if (vr != null) { VarRefs.Add(vr); if (vr.type.Scope == null) { if (vr.type is compiled_type_node) (vr.type as compiled_type_node).scope = new NetHelper.NetTypeScope((vr.type as compiled_type_node).compiled_type, SystemLibrary.SystemLibrary.symtab); else throw new CompilerInternalError("Cannot create With statement because variable reference scope == null"); } //если не нужны локальные перекрытия, здесь нужна проверка Withs.Add(vr.type.Scope); } else { VarRefs.Add(expr); Withs.Add(expr.type.Scope); } } else if (sn is type_node) { type_node tn = sn as type_node; if (tn.IsInterface) AddError(get_location(s_expr), "UNEXPECTED_EXPRESSION_IN_WITH"); Withs.Add(tn.Scope); while (tn != null) { if (tn.Scope == null && tn is compiled_type_node) { (tn as compiled_type_node).init_scope(); } WithTypesList.Add(tn.Scope); tn = tn.base_type; } } else if (sn is compiled_namespace_node) { compiled_namespace_node nn = sn as compiled_namespace_node; Withs.Add(nn.scope); } } WithScope.WithScopes = Withs.ToArray(); Dictionary OldWithVariables = new Dictionary(); foreach (expression_node vr in VarRefs) { if (context.WithVariables.ContainsKey(vr.type.Scope)) { //перекрытие области if (OldWithVariables.ContainsKey(vr.type.Scope)) //Это локальные перекрытия OldWithVariables[vr.type.Scope] = context.WithVariables[vr.type.Scope]; else OldWithVariables.Add(vr.type.Scope, context.WithVariables[vr.type.Scope]); context.WithVariables[vr.type.Scope] = vr; } else { //добавляем текущие with context.WithVariables.Add(vr.type.Scope, vr); } //ivan dobavil dlja bazovyh klassov type_node tn = vr.type.base_type; while (tn != null) { if (tn.Scope == null && tn is compiled_type_node) { (tn as compiled_type_node).init_scope(); } if (tn.Scope != null) if (!context.WithVariables.ContainsKey(tn.Scope)) context.WithVariables.Add(tn.Scope, vr); else { if (OldWithVariables.ContainsKey(tn.Scope)) //Это локальные перекрытия OldWithVariables[tn.Scope] = context.WithVariables[tn.Scope]; else OldWithVariables.Add(tn.Scope, context.WithVariables[tn.Scope]); context.WithVariables[tn.Scope] = vr; } tn = tn.base_type; } } //Ivan dobavil dlja tipov foreach (SymbolTable.Scope sc in WithTypesList) { if (!context.WithTypes.Contains(sc)) context.WithTypes.Push(sc); } stl.statements.AddElement(ret.visit(_with_statement.what_do)); //восстанавливаем перекрытия foreach (SymbolTable.Scope sc in OldWithVariables.Keys) context.WithVariables[sc] = OldWithVariables[sc]; //удаляем текущие with foreach (expression_node vr in VarRefs) { context.WithVariables.Remove(vr.type.Scope); if (!context.WithVariables.ContainsKey(vr.type.Scope) && OldWithVariables.ContainsKey(vr.type.Scope)) { context.WithVariables.Add(vr.type.Scope, OldWithVariables[vr.type.Scope]); OldWithVariables.Remove(vr.type.Scope); } type_node tn = vr.type.base_type; while (tn != null) { if (tn.Scope != null && context.WithVariables.ContainsKey(tn.Scope)) context.WithVariables.Remove(tn.Scope); tn = tn.base_type; } } foreach (SymbolTable.Scope sc in WithTypesList) { context.WithTypes.Pop(); } context.WithSection = context.WithVariables.Count > 0; convertion_data_and_alghoritms.statement_list_stack_pop(); return_value(stl); } public override void visit(SyntaxTree.labeled_statement _labeled_statement) { convertion_data_and_alghoritms.check_node_parser_error(_labeled_statement.label_name); if (_labeled_statement.to_statement is var_statement || _labeled_statement.to_statement is SyntaxTree.assign_var_tuple) { var stmt = new SyntaxTree.labeled_statement(_labeled_statement.label_name,new SyntaxTree.empty_statement()); ReplaceStatementUsingParent(_labeled_statement, new List {stmt, _labeled_statement.to_statement }); ProcessNode(stmt); return; } List sil = context.CurrentScope.FindOnlyInScopeAndBlocks(_labeled_statement.label_name.name); /*if (_labeled_statement.to_statement is SyntaxTree.var_statement || _labeled_statement.to_statement is SyntaxTree.assign_var_tuple) { AddError(get_location(_labeled_statement.label_name), "LABELED_DECLARATION_NOT_ALLOWED"); }*/ if (sil == null) { AddError(new UndefinedNameReference(_labeled_statement.label_name.name, get_location(_labeled_statement.label_name))); } label_node lab = sil.FirstOrDefault().sym_info as label_node; if (lab == null) { AddError(get_location(_labeled_statement.label_name), "IDENT_{0}_IS_NOT_LABEL", _labeled_statement.label_name.name); } // SSM - Patch повторного определения меток в подпрограммах при наличии лямбд if (lambdaProcessingState != LambdaProcessingState.FinishPhase) if (lab.is_defined) { AddError(get_location(_labeled_statement.label_name), "LABEL_{0}_REDEFINED", _labeled_statement.label_name.name); } lab.is_defined = true; lab.comprehensive_code_block = context.block_stack.Peek(); foreach (goto_statement gs in lab.goto_statements) { if (!context.check_can_goto(lab.comprehensive_code_block, gs.comprehensive_code_block) && gs.location != null) { AddError(gs.location, "BLOCKED_LABEL_{0}_GOTO", lab.name); } } convertion_data_and_alghoritms.check_node_parser_error(_labeled_statement.to_statement); statement_node snode = ret.visit((SyntaxTree.statement)_labeled_statement.to_statement); labeled_statement las = new labeled_statement(lab, snode, get_location(_labeled_statement)); ret.return_value((statement_node)las); } public override void visit(SyntaxTree.goto_statement _goto_statement) { List sil = context.CurrentScope.FindOnlyInScopeAndBlocks(_goto_statement.label.name); if (sil == null) { AddError(new UndefinedNameReference(_goto_statement.label.name, get_location(_goto_statement.label))); } label_node lab = sil.FirstOrDefault().sym_info as label_node; if (lab == null) { AddError(get_location(_goto_statement.label), "IDENT_{0}_IS_NOT_LABEL", _goto_statement.label.name); } //if (lab.goto_blocked) //{ // throw new BlockedLabelGoto(_goto_statement.label.name, get_location(_goto_statement.label)); //} goto_statement gs = new goto_statement(lab, get_location(_goto_statement)); gs.comprehensive_code_block = context.block_stack.Peek(); lab.goto_statements.Add(gs); if (lab.comprehensive_code_block != null) { // последнее условие - для goto, которые генерируются в автомате yield, не рассматривать эту ошибку if (!context.check_can_goto(lab.comprehensive_code_block, gs.comprehensive_code_block) && _goto_statement.source_context != null) { AddError(gs.location, "BLOCKED_LABEL_{0}_GOTO", lab.name); } } ret.return_value((statement_node)gs); } public override void visit(SyntaxTree.empty_statement _empty_statement) { return_value(new empty_statement(get_location(_empty_statement))); } private addressed_expression create_class_static_field_reference(type_node tn, definition_node dn, SyntaxTree.ident id_right) { switch (dn.semantic_node_type) { case semantic_node_type.class_field: { class_field cf = (class_field)dn; if (cf.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToNonStaticFieldWithType(cf, get_location(id_right), tn)); } static_class_field_reference scfr = new static_class_field_reference(cf, get_location(id_right)); return scfr; } case semantic_node_type.compiled_variable_definition: { compiled_variable_definition cvd = (compiled_variable_definition)dn; if (cvd.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToNonStaticFieldWithType(cvd, get_location(id_right), tn)); } static_compiled_variable_reference scvr = new static_compiled_variable_reference(cvd, get_location(id_right)); return scvr; } } throw new CompilerInternalError("Error in create static class field reference."); } private addressed_expression create_addressed_with_type_expression(type_node tn, SyntaxTree.ident id_right, SymbolInfo si_right) { definition_node dn = null; if (!internal_is_assign) dn = context.check_name_node_type(id_right.name, si_right, get_location(id_right), general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node); else dn = context.check_name_node_type(id_right.name, si_right, get_location(id_right), general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node,general_node_type.constant_definition); if (dn.general_node_type == general_node_type.constant_definition) AddError(get_location(id_right), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT"); switch (dn.general_node_type) { case general_node_type.variable_node: { return create_class_static_field_reference(tn, dn, id_right); } case general_node_type.property_node: { property_node pn = (property_node)dn; if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToNonStaticPropertyWithType(pn, get_location(id_right), tn)); } static_property_reference pr = new static_property_reference(pn, get_location(id_right)); return pr; } case general_node_type.event_node: { if (dn.semantic_node_type == semantic_node_type.compiled_event) { compiled_event ce = (compiled_event)dn; if (!ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } static_event_reference ser = new static_event_reference(ce, get_location(id_right)); return ser; } else if (dn.semantic_node_type == semantic_node_type.common_event) { common_event ce = (common_event)dn; if (!ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } static_event_reference ser = new static_event_reference(ce, get_location(id_right)); return ser; } else if (dn.semantic_node_type == semantic_node_type.common_namespace_event) { common_namespace_event cne = dn as common_namespace_event; static_event_reference ser = new static_event_reference(cne, get_location(id_right)); return ser; } break; } default : return null; } throw new CompilerInternalError("Invalid right type expression"); } private expressions_list convert_expression_list(List expr_list) { expressions_list exprs = new expressions_list(); foreach (SyntaxTree.expression en in expr_list) exprs.AddElement(convert_strong(en)); return exprs; } private base_function_call create_static_method_call_with_params(function_node fn, location loc, type_node tn, bool procedure_allowed, expressions_list parametrs, bool inherited_call = false) { base_function_call bfc = create_static_method_call(fn, loc, tn, procedure_allowed, inherited_call); bfc.parameters.AddRange(parametrs); return bfc; } private base_function_call create_static_method_call(function_node fn, location loc, type_node tn, bool procedure_allowed, bool inherited_call = false) { if ((!procedure_allowed) && (fn.return_value_type == null)) { AddError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", fn.name); } if (fn.semantic_node_type == semantic_node_type.common_method_node) { common_method_node cmn = (common_method_node)fn; if (cmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { //ssyy изменил if (!cmn.is_constructor) { AddError(new CanNotCallNonStaticMethodWithClass(tn, loc, fn)); } if (cmn.cont_type.IsStatic) AddError(new SimpleSemanticError(loc, "STATIC_CONSTRUCTOR_CALL")); if (cmn.cont_type.IsAbstract && !inherited_call) AddError(new SimpleSemanticError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", cmn.cont_type.name)); common_constructor_call csmc2 = new common_constructor_call(cmn, loc); return csmc2; //if (cmn.pascal_associated_constructor==null) //{ // throw new CanNotCallNonStaticMethodWithClass(tn,loc,fn); //} //common_constructor_call csmc2=new common_constructor_call(cmn.pascal_associated_constructor,loc); //return csmc2; //\ssyy } common_static_method_call csmc = new common_static_method_call(cmn, loc); return csmc; } if (fn.semantic_node_type == semantic_node_type.compiled_function_node) { compiled_function_node cfn = (compiled_function_node)fn; if (cfn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotCallNonStaticMethodWithClass(tn, loc, fn)); } compiled_static_method_call csmc2 = new compiled_static_method_call(cfn, loc); return csmc2; } if (fn.semantic_node_type == semantic_node_type.compiled_constructor_node) { compiled_constructor_node ccn = (compiled_constructor_node)fn; compiled_constructor_call ccc = new compiled_constructor_call(ccn, loc); return ccc; } if (fn.semantic_node_type == semantic_node_type.basic_function_node) { return new basic_function_call(fn as basic_function_node, loc); } if (fn.semantic_node_type == semantic_node_type.common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null) { return new common_namespace_function_call(fn as common_namespace_function_node,loc); } if (fn.semantic_node_type == semantic_node_type.indefinite_definition_node) { return new indefinite_function_call(fn, loc); } throw new CompilerInternalError("Invalid method kind"); } private expression_node create_static_expression(type_node tn, SyntaxTree.ident id_right, List si_right) { definition_node dn = null; if (si_right?.FirstOrDefault().sym_info is common_event && (si_right?.FirstOrDefault().sym_info as common_event).cont_type == tn) dn = context.check_name_node_type(id_right.name, si_right?.FirstOrDefault(), get_location(id_right), general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition, general_node_type.event_node); else dn = context.check_name_node_type(id_right.name, si_right?.FirstOrDefault(), get_location(id_right), general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition); if (si_right != null && si_right.Count > 1 && dn is function_node) foreach (SymbolInfo si in si_right) { if (si.sym_info is var_definition_node) { dn = context.check_name_node_type(id_right.name, si, get_location(id_right), general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition); break; } } switch (dn.general_node_type) { case general_node_type.variable_node: { return create_class_static_field_reference(tn, dn, id_right); } case general_node_type.constant_definition: { constant_definition_node cdn = (constant_definition_node)dn; return cdn.const_value.get_constant_copy(get_location(id_right)); } case general_node_type.function_node: { if (dn is compiled_function_node) { if ((dn as compiled_function_node).ConnectedToType == tn) { if (si_right.Count() > 1) { List temp = new List(); temp = si_right.GetRange(1, si_right.Count() - 1); return create_static_expression(tn, id_right, temp); } else AddError(new UndefinedNameReference(id_right.name, get_location(id_right))); } } else if (dn is common_namespace_function_node) { if ((dn as common_namespace_function_node).ConnectedToType == tn) { if (si_right.Count() > 1) { List temp = new List(); temp = si_right.GetRange(1, si_right.Count() - 1); return create_static_expression(tn, id_right, temp); } else AddError(new UndefinedNameReference(id_right.name, get_location(id_right))); } } if (dn.semantic_node_type == semantic_node_type.indefinite_definition_node) { return new indefinite_reference(dn as indefinite_definition_node, get_location(id_right)); } return make_delegate_wrapper(null, si_right, get_location(id_right), true); } case general_node_type.property_node: { property_node pn = (property_node)dn; if (pn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToNonStaticPropertyWithType(pn, get_location(id_right), tn)); } function_node fn = pn.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(pn, get_location(id_right))); } location lloc = get_location(id_right); check_property_no_params(pn, lloc); return create_static_method_call(fn, lloc, tn, false); } case general_node_type.event_node: { static_event_reference ser = new static_event_reference((event_node)dn, get_location(id_right)); return ser; } } throw new CompilerInternalError("Error in creating static expression."); } private void dot_node_as_type_ident(type_node tn, SyntaxTree.ident id_right, motivation mot) { if (id_right is SyntaxTree.operator_name_ident) AddError(get_location(id_right), "OPERATIONS_CANNOT_BE_CALLED_USING_THIS_SYNTAX"); List si_right = tn.find_in_type(id_right.name, context.CurrentScope); if (si_right == null) { AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), tn)); } switch (mot) { case motivation.address_receiving: { return_addressed_value(create_addressed_with_type_expression(tn, id_right, si_right?.FirstOrDefault())); return; } case motivation.expression_evaluation: { return_value(create_static_expression(tn, id_right, si_right)); return; } case motivation.semantic_node_reciving: { if (si_right.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) return_semantic_value(si_right.FirstOrDefault().sym_info as type_node); else return_semantic_value(create_static_expression(tn, id_right, si_right)); return; } } throw new CompilerInternalError("Invalid motivation"); } private void dot_node_as_namespace_ident(namespace_node nn, SyntaxTree.ident id_right, motivation mot) { List si_right = nn.findOnlyInNamespace(id_right.name); if (si_right == null) { AddError(new MemberIsNotDeclaredInNamespace(id_right, get_location(id_right), nn)); } if (si_right.Count > 0 && si_right[0].sym_info == nn) AddError(new MemberIsNotDeclaredInNamespace(id_right, get_location(id_right), nn)); switch (mot) { case motivation.address_receiving: { return_addressed_value(ident_address_reciving(si_right?.FirstOrDefault(), id_right)); return; } case motivation.expression_evaluation: { return_value(ident_value_reciving(si_right, id_right)); return; } case motivation.semantic_node_reciving: { return_semantic_value(ident_semantic_reciving(si_right, id_right)); return; } } throw new CompilerInternalError("Unsupported motivation"); } private void dot_node_as_unit_ident(common_unit_node cun, SyntaxTree.ident id_right, motivation mot) { dot_node_as_namespace_ident(cun.namespaces[0], id_right, mot); } private void dot_node_as_ident_dot_template_ident(SyntaxTree.ident id_left, SyntaxTree.ident_with_templateparams template_id_right, motivation mot) { List si_left = context.find(id_left.name); SyntaxTree.ident id_right = template_id_right.name as SyntaxTree.ident; if (si_left == null) { AddError(new UndefinedNameReference(id_left.name, get_location(id_left))); } definition_node dn = context.check_name_node_type(id_left.name, si_left?.FirstOrDefault(), get_location(id_left), general_node_type.constant_definition, general_node_type.function_node, general_node_type.namespace_node, general_node_type.property_node, general_node_type.type_node, general_node_type.variable_node, general_node_type.unit_node); switch (dn.general_node_type) { case general_node_type.constant_definition: case general_node_type.function_node: case general_node_type.property_node: case general_node_type.variable_node: { expression_node ex_nd = ident_value_reciving(si_left, id_left); dot_node_as_expression_dot_template_ident(ex_nd, template_id_right, mot, id_left); return; } case general_node_type.namespace_node: { //throw new CompilerInternalError("Unsupported now."); namespace_node nn = dn as namespace_node; dot_node_as_namespace_ident(nn, id_right, mot); return; } case general_node_type.type_node: { type_node tn = dn as type_node; dot_node_as_type_ident(tn, id_right, mot); return; } case general_node_type.unit_node: { //throw new NotSupportedError(get_location(id_left)); dot_node_as_unit_ident((common_unit_node)dn, id_right, mot); return; } } return; } private void dot_node_as_ident_dot_ident(SyntaxTree.ident id_left, SyntaxTree.ident id_right, motivation mot) { List si_left = context.find(id_left.name); if (si_left == null) { AddError(new UndefinedNameReference(id_left.name, get_location(id_left))); } definition_node dn = context.check_name_node_type(id_left.name, si_left?.FirstOrDefault(), get_location(id_left), general_node_type.constant_definition, general_node_type.function_node, general_node_type.namespace_node, general_node_type.property_node, general_node_type.type_node, general_node_type.variable_node, general_node_type.unit_node); switch (dn.general_node_type) { case general_node_type.constant_definition: case general_node_type.function_node: case general_node_type.property_node: case general_node_type.variable_node: { expression_node ex_nd = null; if (id_left is inherited_ident) ex_nd = inherited_ident_value_reciving(id_left as inherited_ident); else ex_nd = ident_value_reciving(si_left, id_left); dot_node_as_expression_dot_ident(ex_nd, id_right, mot, id_left); return; } case general_node_type.namespace_node: { //throw new CompilerInternalError("Unsupported now."); namespace_node nn = dn as namespace_node; dot_node_as_namespace_ident(nn, id_right, mot); return; } case general_node_type.type_node: { type_node tn = dn as type_node; dot_node_as_type_ident(tn, id_right, mot); return; } case general_node_type.unit_node: { //throw new NotSupportedError(get_location(id_left)); dot_node_as_unit_ident((common_unit_node)dn, id_right, mot); return; } } return; } private expression_node convert_if_typed_expression_to_function_call(expression_node expr, bool force = false) { if (expr is typed_expression) return convert_typed_expression_to_function_call(expr as typed_expression, force); return expr; } internal expression_node convert_typed_expression_to_function_call(typed_expression te, bool force=false) { delegated_methods dm = te.type as delegated_methods; if (dm == null) { return te; } base_function_call bfc = dm.empty_param_method; if (bfc == null) { if (force) AddError(new NoFunctionWithSameParametresNum(dm.proper_methods[0].location, true, dm.proper_methods[0].simple_function_node)); return te; } if (bfc.type == null) return te; function_node fn = bfc.simple_function_node; common_namespace_function_node cnfn = fn as common_namespace_function_node; if ((fn.parameters.Count == 1 || cnfn != null && fn.parameters.Count == 2 && cnfn.ConnectedToType != null) && (fn.parameters[fn.parameters.Count - 1].is_params || fn.parameters[fn.parameters.Count - 1].default_value != null) || fn.parameters.Count > 0 && fn.num_of_default_parameters == fn.parameters.Count) { fn = convertion_data_and_alghoritms.select_function(bfc.parameters, new List { new SymbolInfo(fn) }, bfc.location); if (fn.polymorphic_state == SemanticTree.polymorphic_state.ps_static || fn is common_namespace_function_node || fn is basic_function_node) bfc = convertion_data_and_alghoritms.create_simple_function_call(fn, bfc.location, bfc.parameters.ToArray()) as base_function_call; else { expression_node obj = null; if (bfc is common_method_call) obj = (bfc as common_method_call).obj; else if (bfc is compiled_function_call) obj = (bfc as compiled_function_call).obj; bfc = convertion_data_and_alghoritms.create_method_call(fn, bfc.location, obj, bfc.parameters.ToArray()) as base_function_call; } } else { function_node[] empty_param_methods = dm.empty_param_methods; List root_sil = new List { new SymbolInfo(empty_param_methods[0]) }; for (int i = 1; i < empty_param_methods.Length; i++) { root_sil.Add(new SymbolInfo(empty_param_methods[i])); } compiled_function_node cfn = fn as compiled_function_node; if ((fn.parameters.Count == 1 || cfn != null && fn.parameters.Count == 2 && cfn.ConnectedToType != null) && (fn.parameters[fn.parameters.Count - 1].is_params || fn.parameters[fn.parameters.Count - 1].default_value != null)) { fn = convertion_data_and_alghoritms.select_function(bfc.parameters, root_sil, bfc.location); bfc = create_static_method_call_with_params(fn, bfc.location, fn.return_value_type, true, bfc.parameters); } else if (fn.parameters.Count == 1 && cfn != null && cfn.ConnectedToType != null) { fn = convertion_data_and_alghoritms.select_function(bfc.parameters, root_sil, bfc.location); bfc = create_static_method_call_with_params(fn, bfc.location, fn.return_value_type, true, bfc.parameters); } } if (bfc is common_method_call) { common_method_node cmn = (bfc as common_method_call).function_node; if (cmn != null && cmn.is_generic_function && !cmn.is_generic_function_instance && cmn.parameters.Count == 0) { cmn = (common_method_node)generic_convertions.DeduceFunction(cmn, new expressions_list(), true, context, bfc.location); bfc = new common_method_call(cmn, (bfc as common_method_call).obj, bfc.location); } } else if (bfc is common_namespace_function_call) { common_namespace_function_node bcnfn = (bfc as common_namespace_function_call).function_node; if (bcnfn.is_generic_function && !bcnfn.is_generic_function_instance && bcnfn.parameters.Count == 0) { bcnfn = (common_namespace_function_node)generic_convertions.DeduceFunction(bcnfn, new expressions_list(), true, context, bfc.location); bfc = new common_namespace_function_call(bcnfn, bfc.location); } } return bfc; } public void try_convert_typed_expression_to_function_call(ref expression_node en, bool force = false) { if (en.semantic_node_type == semantic_node_type.typed_expression) { en = convert_typed_expression_to_function_call((typed_expression)en, force); } } private addressed_expression create_class_field_reference(expression_node en, definition_node dn, SyntaxTree.ident id_right) { try_convert_typed_expression_to_function_call(ref en); if (dn.semantic_node_type == semantic_node_type.class_field) { class_field cf = (class_field)dn; if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferanceToStaticFieldWithExpression(cf, get_location(id_right), en)); } class_field_reference cfr = new class_field_reference(cf, en, get_location(id_right)); //return_value(cfr); return cfr; } if (dn.semantic_node_type == semantic_node_type.compiled_variable_definition) { compiled_variable_definition cfd = (compiled_variable_definition)dn; if (cfd.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferanceToStaticFieldWithExpression(cfd, get_location(id_right), en)); } compiled_variable_reference cfr2 = new compiled_variable_reference(cfd, en, get_location(id_right)); //return_value(cfr2); return cfr2; } #if (DEBUG) throw new CompilerInternalError("Invalid variable kind"); #endif return null; } private base_function_call create_not_static_method_call(function_node fn, expression_node en, location loc, bool procedure_allowed) { try_convert_typed_expression_to_function_call(ref en); if ((!procedure_allowed) && (fn.return_value_type == null)) { AddError(loc, "FUNCTION_EXPECTED_PROCEDURE_{0}_MEET", fn.name); } if (fn.semantic_node_type == semantic_node_type.common_method_node) { common_method_node cmn = (common_method_node)fn; if (cmn.is_constructor) { AddError(loc, "CAN_NOT_CALL_CONSTRUCTOR_AS_PROCEDURE"); } if (cmn.original_function != null && cmn.original_function is compiled_function_node && (cmn.original_function as compiled_function_node).ConnectedToType != null) { common_static_method_call csmc = new common_static_method_call(cmn, loc); return csmc; } if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotCallStaticMethodWithExpression(en, fn)); } common_method_call cmc = new common_method_call(cmn, en, loc); cmc.virtual_call = !inherited_ident_processing; return cmc; } if (fn.semantic_node_type == semantic_node_type.compiled_function_node) { compiled_function_node cfn = (compiled_function_node)fn; if (cfn.ConnectedToType != null) { compiled_static_method_call csmc = new compiled_static_method_call(cfn, loc); return csmc; } else { if (cfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { if (!cfn.is_extension_method) AddError(new CanNotCallStaticMethodWithExpression(en, fn)); else return new compiled_static_method_call(cfn, loc); } compiled_function_call cfc = new compiled_function_call(cfn, en, loc); cfc.virtual_call = !inherited_ident_processing; return cfc; } } if (fn.semantic_node_type == semantic_node_type.compiled_constructor_node) { AddError(loc, "CAN_NOT_CALL_CONSTRUCTOR_AS_PROCEDURE"); } if (fn.semantic_node_type == semantic_node_type.common_namespace_function_node && (fn as common_namespace_function_node).ConnectedToType != null) { common_namespace_function_call cnfc = new common_namespace_function_call(fn as common_namespace_function_node,loc); //cnfc.parameters.AddElement(en); return cnfc; } if (fn.semantic_node_type == semantic_node_type.indefinite_definition_node) { indefinite_function_call ifc = new indefinite_function_call(fn, loc); return ifc; } throw new CompilerInternalError("Invalid method kind"); } private expression_node expression_value_reciving(SyntaxTree.ident id_right, List sil, expression_node en, bool expected_delegate) { general_node_type[] node_types; if (en is this_node || LambdaHelper.IsCapturedSelf(en)) node_types = new general_node_type[] { general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition, general_node_type.event_node}; else node_types = new general_node_type[] { general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition}; definition_node dn = context.check_name_node_type(id_right.name, sil?.FirstOrDefault(), get_location(id_right), node_types); switch (dn.general_node_type) { /*case general_node_type.constant_defenition: { constant_definition_node cdn=(constant_definition_node)dn; return cdn.const_value; }*/ case general_node_type.variable_node: { return create_class_field_reference(en, dn, id_right); } case general_node_type.function_node: { if (dn.semantic_node_type == semantic_node_type.indefinite_definition_node) { return new indefinite_reference(dn as indefinite_definition_node, get_location(id_right)); } if (expected_delegate && en != null) { function_node tmp_fn = null; bool has_empty_methods = false; bool only_extension_methods = true; if (sil != null) { foreach (SymbolInfo tmp_si in sil) { tmp_fn = tmp_si.sym_info as function_node; if (tmp_fn != null) { if (!tmp_fn.is_extension_method) only_extension_methods = false; else { if (SemanticRulesConstants.AllowMethodCallsWithoutParentheses && (tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null))) has_empty_methods = true; } } } } if (has_empty_methods && only_extension_methods) expected_delegate = false; } if (expected_delegate) { return make_delegate_wrapper(en, sil, get_location(id_right), false); } else { function_node tmp_fn = null; expressions_list pars = new expressions_list(); if (en != null) if(sil != null) foreach(SymbolInfo tmp_si in sil) { tmp_fn = tmp_si.sym_info as function_node; if (tmp_fn != null && tmp_fn.is_extension_method && (tmp_fn.parameters.Count == 1 || tmp_fn.parameters.Count == 2 && (tmp_fn.parameters[1].is_params || tmp_fn.parameters[1].default_value != null))) { pars.AddElement(en); break; } } function_node fn = convertion_data_and_alghoritms.select_function(pars, sil, get_location(id_right)); if (!fn.is_extension_method && fn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) return create_not_static_method_call(fn, en, get_location(id_right), false); else return create_static_method_call_with_params(fn, get_location(id_right), fn.return_value_type, false, pars); } } case general_node_type.property_node: { property_node pn = (property_node)dn; if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(id_right), pn.comprehensive_type)); } function_node fn = pn.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(pn, get_location(id_right))); } location lloc = get_location(id_right); check_property_no_params(pn, lloc); return create_not_static_method_call(fn, en, lloc, false); } case general_node_type.constant_definition: { //throw new ConstMemberCannotBeAccessedWithAnInstanceReference((class_constant_definition)dn, get_location(id_right)); return ((constant_definition_node)dn).const_value.get_constant_copy(get_location(id_right)); } case general_node_type.event_node: { if (dn.semantic_node_type == semantic_node_type.compiled_event) { compiled_event ce = (compiled_event)dn; if (ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right)); return ser; } else if (dn.semantic_node_type == semantic_node_type.common_event) { common_event ce = (common_event)dn; if (ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right)); return ser; } break; } } throw new CompilerInternalError("Invalid class member"); } private addressed_expression address_expression_reciving(SyntaxTree.ident id_right, SymbolInfo si, expression_node en) { if (si != null && si.sym_info != null && si.sym_info.semantic_node_type == semantic_node_type.indefinite_definition_node) { return new indefinite_reference(si.sym_info as indefinite_definition_node, get_location(id_right)); } definition_node dn = null; if (!internal_is_assign) dn = context.check_name_node_type(id_right.name, si, get_location(id_right), general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node); else dn = context.check_name_node_type(id_right.name, si, get_location(id_right), general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node, general_node_type.constant_definition); if (dn.general_node_type == general_node_type.constant_definition) { AddError(get_location(id_right), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT"); } switch (dn.general_node_type) { case general_node_type.variable_node: { return create_class_field_reference(en, dn, id_right); } case general_node_type.property_node: { property_node pn = (property_node)dn; if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(id_right), pn.comprehensive_type)); } try_convert_typed_expression_to_function_call(ref en); non_static_property_reference pr = new non_static_property_reference(pn, en, get_location(id_right)); return pr; } case general_node_type.event_node: { if (dn.semantic_node_type == semantic_node_type.compiled_event) { compiled_event ce = (compiled_event)dn; if (ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right)); return ser; } else if (dn.semantic_node_type == semantic_node_type.common_event) { common_event ce = (common_event)dn; if (ce.is_static) { //throw new NonStaticAndStaticEvevnt(); } nonstatic_event_reference ser = new nonstatic_event_reference(en, ce, get_location(id_right)); return ser; } break; } default : return null; } throw new CompilerInternalError("Undefined expression to address reciving"); } private bool has_property(ref List sil) { int si_index = 0; if (sil != null) { while (si_index < sil.Count()) { if (sil[si_index].sym_info is compiled_property_node || sil[si_index].sym_info is common_property_node) { sil.RemoveRange(0, si_index); return true; } ++si_index; } } return false; } private void dot_node_as_expression_dot_template_ident(expression_node en, SyntaxTree.ident_with_templateparams template_id_right, motivation mot, addressed_value syntax_node) { SyntaxTree.ident id_right = template_id_right.name as ident; if (en is typed_expression) try_convert_typed_expression_to_function_call(ref en); List sil = en.type.find_in_type(id_right.name, context.CurrentScope); if (sil == null) { AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), en.type)); } try_convert_typed_expression_to_function_call(ref en); switch (mot) { case motivation.address_receiving: { return_addressed_value(address_expression_reciving(id_right, sil?.FirstOrDefault(), en)); return; } case motivation.expression_evaluation: { if (can_convert_to_method_call(ref sil)) { //dot_node dnode = new dot_node(syntax_node, template_id_right); template_id_right.name = new dot_node(syntax_node, id_right); method_call mc = new method_call(template_id_right, new expression_list()); mc.visit(this); return; } return_value(expression_value_reciving(id_right, sil, en, true)); return; } case motivation.semantic_node_reciving: { if (sil.FirstOrDefault().sym_info is function_node && (sil.FirstOrDefault().sym_info as function_node).is_extension_method) has_property(ref sil); return_semantic_value(expression_value_reciving(id_right, sil, en, true)); return; } } throw new CompilerInternalError("Invalid motivation."); } private void dot_node_as_expression_dot_ident(expression_node en, SyntaxTree.ident id_right, motivation mot, addressed_value syntax_node) { if (en is typed_expression) try_convert_typed_expression_to_function_call(ref en); if (en is typed_expression) { AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), en.type)); } List sil = en.type.find_in_type(id_right.name, context.CurrentScope); if (en.type.IsEnum && sil != null && sil[0].sym_info is class_constant_definition) // l.A { AddError(get_location(id_right), "ACCESS_TO_ENUM_CONST_THROUGH_OBJECT"); } if (sil == null) { AddError(new MemberIsNotDeclaredInType(id_right, get_location(id_right), en.type)); } try_convert_typed_expression_to_function_call(ref en); switch (mot) { case motivation.address_receiving: { return_addressed_value(address_expression_reciving(id_right, sil?.FirstOrDefault(), en)); return; } case motivation.expression_evaluation: { if (can_convert_to_method_call(ref sil)) { dot_node dnode = new dot_node(syntax_node, id_right); method_call mc = new method_call(dnode, new expression_list()); mc.visit(this); return; } if (sil != null && sil.Count > 1) { List no_extmeth_sil = new List(); foreach (var si in sil) if (si.sym_info is function_node && !(si.sym_info as function_node).is_extension_method) no_extmeth_sil.Add(si); if (no_extmeth_sil.Count > 0) sil = no_extmeth_sil; } return_value(expression_value_reciving(id_right, sil, en, true)); return; } case motivation.semantic_node_reciving: { if (sil.FirstOrDefault().sym_info is function_node && (sil.FirstOrDefault().sym_info as function_node).is_extension_method) has_property(ref sil); return_semantic_value(expression_value_reciving(id_right, sil, en, true)); return; } } throw new CompilerInternalError("Invalid motivation."); } private void dot_node_as_dot_node_dot_ident(SyntaxTree.dot_node left_dot, SyntaxTree.ident id_right, motivation mot) { semantic_node sn = convert_semantic_strong(left_dot); switch (sn.general_node_type) { case general_node_type.expression: { expression_node en = (expression_node)sn; dot_node_as_expression_dot_ident(en, id_right, mot, left_dot); return; } case general_node_type.namespace_node: { namespace_node nn = (namespace_node)sn; dot_node_as_namespace_ident(nn, id_right, mot); return; } case general_node_type.type_node: { type_node tn = (type_node)sn; dot_node_as_type_ident(tn, id_right, mot); return; } case general_node_type.unit_node: { throw new CompilerInternalError("Not supported"); } } throw new CompilerInternalError("Invalid left dot node kind"); } private void dot_node_as_dot_node_dot_template_ident(SyntaxTree.dot_node left_dot, SyntaxTree.ident_with_templateparams template_id_right, motivation mot) { semantic_node sn = convert_semantic_strong(left_dot); ident id_right = template_id_right.name as ident; switch (sn.general_node_type) { case general_node_type.expression: { expression_node en = (expression_node)sn; dot_node_as_expression_dot_template_ident(en, template_id_right, mot, left_dot); return; } case general_node_type.namespace_node: { namespace_node nn = (namespace_node)sn; dot_node_as_namespace_ident(nn, id_right, mot); return; } case general_node_type.type_node: { type_node tn = (type_node)sn; dot_node_as_type_ident(tn, id_right, mot); return; } case general_node_type.unit_node: { throw new CompilerInternalError("Not supported"); } } throw new CompilerInternalError("Invalid left dot node kind"); } private bool can_convert_to_method_call(ref List sil) { List tmp_list = new List(sil); foreach (SymbolInfo tmp_si in tmp_list) { if (tmp_si.sym_info is function_node && !(tmp_si.sym_info as function_node).is_extension_method && (tmp_si.sym_info as function_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static && !(tmp_si.sym_info is common_method_node && (tmp_si.sym_info as common_method_node).is_constructor) && (tmp_si.sym_info as function_node).return_value_type != null && !(tmp_si.sym_info is compiled_constructor_node)) return false; } foreach (SymbolInfo tmp_si in tmp_list) { if (SemanticRulesConstants.AllowMethodCallsWithoutParentheses && tmp_si.sym_info is function_node && (tmp_si.sym_info as function_node).is_extension_method && !has_property(ref sil) || tmp_si.sym_info is common_method_node && (tmp_si.sym_info as common_method_node).is_constructor || tmp_si.sym_info is compiled_constructor_node) return true; } return false; } public override void visit(SyntaxTree.dot_node _dot_node) { var mot = motivation_keeper.motivation; SyntaxTree.ident id_left = _dot_node.left as SyntaxTree.ident; SyntaxTree.ident id_right = _dot_node.right as SyntaxTree.ident; if (_dot_node.right is ident_with_templateparams) id_right = (_dot_node.right as ident_with_templateparams).name as ident; // SSM 18.08.16 - пробуем обработать захват enn.ii в yieldах где enn - поле класса и нуждается в переименовании // Так же ниже делает lroman if (_dot_node.left is yield_unknown_ident) { var yui = (yield_unknown_ident)_dot_node.left; var av = ProcessUnknownIdent(yui); var dn = new dot_node(av, _dot_node.right,yui.source_context); visit(dn); return; } //lroman if (_dot_node.left is closure_substituting_node) { var left = (closure_substituting_node)_dot_node.left; var dotNodeToVisit = new dot_node(left.substitution, _dot_node.right); // Подменить dot_node в этот момент на этапе семантики dotNodeToVisit.Parent = _dot_node.Parent; // SSM 01.06.19 visit(dotNodeToVisit); return; } motivation_keeper.reset(); // SSM перенес сюда сверху - bug fix #263 if (id_left != null) { if (_dot_node.right is ident_with_templateparams) { dot_node_as_ident_dot_template_ident(id_left, _dot_node.right as ident_with_templateparams, mot); return; } if (id_left.name != null && id_left.name.IndexOf('.') != -1) { var arr = id_left.name.Split('.'); var dotNodeToVisit = new dot_node(new ident(id_left.name.Substring(0, id_left.name.LastIndexOf('.')), id_left.source_context), new ident(arr[arr.Length-1],id_left.source_context)); visit(new dot_node(dotNodeToVisit, id_right, _dot_node.source_context)); return; } if (id_left is inherited_ident) inherited_ident_processing = true; dot_node_as_ident_dot_ident(id_left, id_right, mot); inherited_ident_processing = false; return; } else { SyntaxTree.ident_with_templateparams iwt = _dot_node.left as SyntaxTree.ident_with_templateparams; if (iwt != null) { var ret_node = ret.visit((SyntaxTree.syntax_tree_node)iwt); if (ret_node is type_node) { type_node tn = ret.visit((SyntaxTree.syntax_tree_node)iwt) as type_node; dot_node_as_type_ident(tn, id_right, mot); return; } } SyntaxTree.dot_node left_dot = _dot_node.left as SyntaxTree.dot_node; if (left_dot != null) { if (_dot_node.right is ident_with_templateparams) { dot_node_as_dot_node_dot_template_ident(left_dot, _dot_node.right as ident_with_templateparams, mot); return; } dot_node_as_dot_node_dot_ident(left_dot, id_right, mot); return; } expression_node en = convert_strong(_dot_node.left); if (_dot_node.right is ident_with_templateparams) { dot_node_as_expression_dot_template_ident(en, _dot_node.right as ident_with_templateparams, mot, _dot_node.left); return; } dot_node_as_expression_dot_ident(en, id_right, mot, _dot_node.left); return; } } private SyntaxTree.ident ConvertOperatorNameToIdent(SyntaxTree.ident opname) { if (opname is SyntaxTree.operator_name_ident) { SyntaxTree.ident id = new SyntaxTree.ident(name_reflector.get_name((opname as SyntaxTree.operator_name_ident).operator_type)); id.source_context = opname.source_context; return id; } return opname; } private void visit_method_name(SyntaxTree.method_name _method_name) { convertion_data_and_alghoritms.check_node_parser_error(_method_name); convertion_data_and_alghoritms.check_node_parser_error(_method_name.meth_name); common_type_node tp = null; definition_node def_temp = null; SyntaxTree.template_type_name ttn = null; bool is_operator = _method_name.meth_name is SyntaxTree.operator_name_ident; if (is_operator && context.converted_type != null && context.converted_type.IsInterface) AddError(get_location(_method_name), "OPERATORS_IN_INTERFACES_NOT_ALLOWED"); SyntaxTree.Operators op = PascalABCCompiler.SyntaxTree.Operators.Undefined; if(is_operator) op=(_method_name.meth_name as SyntaxTree.operator_name_ident).operator_type; _method_name.meth_name = ConvertOperatorNameToIdent(_method_name.meth_name); bool explicit_impl = false; if ((context.converting_block() != block_type.namespace_block) && (_method_name.class_name != null)) { explicit_impl = true; } if (is_operator && op==SyntaxTree.Operators.AddressOf && SemanticRulesConstants.AddressOfOperatorNonOverloaded) { AddError(get_location(_method_name.meth_name), "NOT_OVERLOADED_OPERATOR"); } bool common_extension_meth = false; if (_method_name.class_name != null) { convertion_data_and_alghoritms.check_node_parser_error(_method_name.class_name); location loc_type_name = get_location(_method_name.class_name); ttn = _method_name.class_name as SyntaxTree.template_type_name; int num_template_args = 0; if (ttn != null) { num_template_args = ttn.template_args.idents.Count; } common_type_node current_conv_type = context.converted_type; def_temp = context.enter_in_type_method(_method_name, _method_name.class_name.name, loc_type_name, num_template_args); if (explicit_impl) { context.converted_type = current_conv_type; if (def_temp is type_node && (def_temp as type_node).IsInterface) { context.converted_explicit_interface_type = def_temp as type_node; List sil = context.converted_explicit_interface_type.find_in_type(_method_name.meth_name.name); if (sil == null) AddError(new UndefinedNameReference(_method_name.meth_name.name, get_location(_method_name.meth_name))); } else AddError(get_location(_method_name.class_name), "EXPECTED_INTERFACE"); } tp = def_temp as common_type_node; template_class tc = def_temp as template_class; //SyntaxTree.template_type_name ttn = _method_name.class_name as SyntaxTree.template_type_name; if (ttn != null && !(def_temp is compiled_type_node)) { int count; if (tp == null) { if (tc != null) { if (tc.is_synonym) { AddError(loc_type_name, "CAN_NOT_DEFINE_METHOD_OF_TEMPLATE_TYPE_SYNONYM"); } SyntaxTree.class_definition cl_def = tc.type_dec.type_def as SyntaxTree.class_definition; count = cl_def.template_args.idents.Count; if (count != ttn.template_args.idents.Count) { AddError(get_location(ttn), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tc.name, count); } for (int i = 0; i < count; ++i) { if (string.Compare(cl_def.template_args.idents[i].name, ttn.template_args.idents[i].name, true) != 0) { AddError(get_location(ttn.template_args.idents[i]), "PARAMETER_{0}_MUST_BE_NAMED_{1}", i + 1, cl_def.template_args.idents[i].name); } } _method_name.class_name = new SyntaxTree.ident(ttn.name); _method_name.class_name.source_context = ttn.source_context; return; } AddError(get_location(ttn), "COULD_NOT_DEFINE_GENERIC_FUNCTION_OF_COMPILED_TYPE"); } if (tp.generic_params == null) { AddError(get_location(ttn), "{0}_IS_NOT_TEMPLATE_CLASS", tp.PrintableName); } count = tp.generic_params.Count; if (count != ttn.template_args.idents.Count) { AddError(get_location(ttn), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tp.PrintableName, count); } for (int i = 0; i < count; ++i) { if (string.Compare(tp.generic_params[i].name, ttn.template_args.idents[i].name, true) != 0) { AddError(get_location(ttn.template_args.idents[i]), "PARAMETER_{0}_MUST_BE_NAMED_{1}", i + 1, tp.generic_params[i].name); } } } else { if (tp != null && tp.is_generic_type_definition) { AddError(get_location(_method_name.class_name), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tp.PrintableName, tp.generic_params.Count); } if (tc != null) { var td = tc.type_dec.type_def as SyntaxTree.class_definition; var cnt = 0; if (td != null) cnt = td.template_args.idents.Count; var td1 = tc.type_dec.type_def as SyntaxTree.template_type_reference; if (td1 != null) cnt = td1.params_list.Count; AddError(get_location(_method_name.class_name), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", tc.name, cnt); } } //(ds)проверяем на компилированный тип if (!(def_temp is compiled_type_node)) { //(ssyy) проверяем на шаблон if (tp == null) { return; } if (tp is compiled_generic_instance_type_node || tp is common_generic_instance_type_node) AddError(get_location(_method_name), "EXTENSION_METHOD_FOR_GENERIC_INSTANCES"); List sil = tp.scope.FindOnlyInScope(_method_name.meth_name.name); if (tp.original_template == null && ((sil == null && this._compiled_unit.namespaces.IndexOf(tp.comprehensive_namespace) == -1) || (sil != null && this._compiled_unit.namespaces.IndexOf(tp.comprehensive_namespace) == -1)) && !explicit_impl) { if (def_temp is common_type_node) { common_extension_meth = true; common_type_node ctn = def_temp as common_type_node; if (sil != null && this._compiled_unit.namespaces.IndexOf(tp.comprehensive_namespace) == -1)//static methods cannot be extension methods { if (current_function_header.class_keyword) AddError(get_location(_method_name), "CANNOT_IMPLEMENT_METHODS_IN_OTHER_MODULE"); } if (ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_wrapper || ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type || ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.base_set_type || ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.binary_file || ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.text_file || ctn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file) AddError(get_location(_method_name), "NO_METHOD_{0}_IN_CLASS_{1}", _method_name.meth_name.name, tp.PrintableName); } else AddError(get_location(_method_name), "NO_METHOD_{0}_IN_CLASS_{1}", _method_name.meth_name.name, tp.PrintableName); } } else if (def_temp as compiled_type_node == SystemLibrary.SystemLibrary.void_type) AddError(get_location(_method_name.class_name), "VOID_NOT_VALID"); } else { if (is_operator && context.converted_type == null && context.converted_template_type == null && !(current_function_header != null && current_function_header.proc_attributes != null && has_extensionmethod_attr(current_function_header.proc_attributes.proc_attributes)) /*&& !(current_function_header != null && current_function_header.template_args != null && current_function_header.template_args.idents.Count > 0)*/) { AddError(get_location(_method_name), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION"); } } convertion_data_and_alghoritms.check_node_parser_error(_method_name.meth_name); location loc_name = get_location(_method_name.meth_name); context.extension_method = common_extension_meth; if (LambdaHelper.IsLambdaName(_method_name.meth_name) && lambdaProcessingState != LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase) //lroman// { if (lambdaProcessingState == LambdaProcessingState.None && context.converting_block() == block_type.namespace_block) { context.create_function(_method_name.meth_name.name, loc_name); } else { var addSymbol = (lambdaProcessingState == LambdaProcessingState.TypeInferencePhase && LambdaHelper.IsAuxiliaryLambdaName(_method_name.meth_name)) || lambdaProcessingState == LambdaProcessingState.FinishPhase; context.create_lambda_function(_method_name.meth_name.name, loc_name, addSymbol, context.CurrentScope); } } else { if (current_function_header != null && current_function_header.proc_attributes != null && has_extensionmethod_attr(current_function_header.proc_attributes.proc_attributes)) context.create_function(_method_name.meth_name.name, loc_name, false); else { if (!explicit_impl) context.create_function(_method_name.meth_name.name, loc_name); else context.create_function(context.converted_explicit_interface_type.BaseFullName+"."+_method_name.meth_name.name, loc_name); } } context.extension_method = false; context.top_function.IsOperator = is_operator; if (ttn != null && def_temp is compiled_type_node) { if (!explicit_impl) visit_generic_params(context.top_function, ttn.template_args.idents); else { List instance_params = new List(); foreach (ident id in ttn.template_args.idents) { SymbolInfo si = context.find_first(id.name); if (si == null) AddError(new UndefinedNameReference(id.name, get_location(id))); if (!(si.sym_info is type_node)) AddError(new ExpectedType(get_location(id))); instance_params.Add(si.sym_info as type_node); } if (!context.converted_explicit_interface_type.IsInterface) AddError(get_location(ttn), "INTERFACE_EXPECTED"); type_node inst_tn = context.converted_explicit_interface_type.get_instance(instance_params); bool found = false; if (context.converted_type.ImplementingInterfaces.Count > 0) { foreach (type_node interf in context.converted_type.ImplementingInterfaces) { if (interf == inst_tn) { found = true; break; } } } if (!found) AddError(get_location(ttn),"CLASS_NOT_IMPLEMENT_THIS_INTERFACE"); } } //context.top_function.IsOperator = _method_name.meth_name is SyntaxTree.operator_name_ident; } public override void visit(SyntaxTree.method_name _method_name) { visit_method_name(_method_name); } private void is_case_variant_intersection_with_another(switch_node sn, int_const_node defined_const, location curloc) { foreach (case_variant_node cv in sn.case_variants) { foreach (int_const_node cn in cv.case_constants) { if (cn.constant_value == defined_const.constant_value) { AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER"); } } foreach (case_range_node cr in cv.case_ranges) { if ((defined_const.constant_value <= cr.high_bound.constant_value) && (defined_const.constant_value >= cr.lower_bound.constant_value)) { AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_DIAPASON"); } } } } private void is_case_range_intersection_with_another(switch_node sn, case_range_node defined_range, location curloc) { foreach (case_variant_node cv in sn.case_variants) { foreach (int_const_node icn in cv.case_constants) { if ((icn.constant_value >= defined_range.lower_bound.constant_value) && (icn.constant_value <= defined_range.high_bound.constant_value)) { AddError(curloc, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_DIAPASON"); } } foreach (case_range_node cr in cv.case_ranges) { if ((cr.lower_bound.constant_value <= defined_range.high_bound.constant_value) && (cr.lower_bound.constant_value >= defined_range.lower_bound.constant_value)) { AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION"); } if ((cr.high_bound.constant_value <= defined_range.high_bound.constant_value) && (cr.high_bound.constant_value >= defined_range.lower_bound.constant_value)) { AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION"); } if ((defined_range.lower_bound.constant_value <= cr.high_bound.constant_value) && (defined_range.lower_bound.constant_value >= cr.lower_bound.constant_value)) { AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION"); } if ((defined_range.high_bound.constant_value <= cr.high_bound.constant_value) && (defined_range.high_bound.constant_value >= cr.lower_bound.constant_value)) { AddError(curloc, "CASE_DIAPASON_VARIANT_INTERSECTION"); } } } } private string_const_node convert_string_const_to_switch(expression_node switch_expr, location loc) { if (switch_expr is string_const_node) return switch_expr as string_const_node; string_const_node scn = null; if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral) scn = new string_const_node((string)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc); if (scn == null) { AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } return scn; } private long_const_node convert_long_const_to_switch(expression_node switch_expr, location loc) { convertion_data_and_alghoritms.convert_type(switch_expr, SystemLibrary.SystemLibrary.int64_type, loc); if (switch_expr is long_const_node) return switch_expr as long_const_node; //switch_expr = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, // loc, switch_expr); long_const_node icn = null;//switch_expr as constant_node; if (switch_expr is byte_const_node) icn = new long_const_node((switch_expr as byte_const_node).constant_value, loc); else if (switch_expr is sbyte_const_node) icn = new long_const_node((long)((switch_expr as sbyte_const_node).constant_value), loc); else if (switch_expr is short_const_node) icn = new long_const_node((long)((switch_expr as short_const_node).constant_value), loc); else if (switch_expr is ushort_const_node) icn = new long_const_node((long)((switch_expr as ushort_const_node).constant_value), loc); else if (switch_expr is uint_const_node) icn = new long_const_node((long)((switch_expr as uint_const_node).constant_value),loc); else if (switch_expr is int_const_node) icn = new long_const_node((long)((switch_expr as int_const_node).constant_value),loc); else if (switch_expr is ulong_const_node) icn = new long_const_node((long)((switch_expr as ulong_const_node).constant_value), loc); else if (switch_expr is enum_const_node) icn = new long_const_node((switch_expr as enum_const_node).constant_value, loc); else if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral) icn = new long_const_node((long)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc); //учти здесь модет быть и long! //-DarkStar Add if (icn == null) { AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } return icn; } private ulong_const_node convert_ulong_const_to_switch(expression_node switch_expr, location loc) { convertion_data_and_alghoritms.convert_type(switch_expr, SystemLibrary.SystemLibrary.uint64_type, loc); if (switch_expr is ulong_const_node) return switch_expr as ulong_const_node; //switch_expr = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, // loc, switch_expr); ulong_const_node icn = null;//switch_expr as constant_node; if (switch_expr is byte_const_node) icn = new ulong_const_node((switch_expr as byte_const_node).constant_value, loc); else if (switch_expr is sbyte_const_node) icn = new ulong_const_node((ulong)((switch_expr as sbyte_const_node).constant_value), loc); else if (switch_expr is short_const_node) icn = new ulong_const_node((ulong)((switch_expr as short_const_node).constant_value), loc); else if (switch_expr is ushort_const_node) icn = new ulong_const_node((ulong)((switch_expr as ushort_const_node).constant_value), loc); else if (switch_expr is int_const_node) icn = new ulong_const_node((ulong)((switch_expr as int_const_node).constant_value),loc); else if (switch_expr is uint_const_node) icn = new ulong_const_node((ulong)((switch_expr as uint_const_node).constant_value), loc); else if (switch_expr is long_const_node) icn = new ulong_const_node((ulong)((switch_expr as long_const_node).constant_value),loc); else if (switch_expr is char_const_node) icn = new ulong_const_node((ulong)((switch_expr as char_const_node).constant_value), loc); else if (switch_expr is enum_const_node) icn = new ulong_const_node((ulong)((switch_expr as enum_const_node).constant_value), loc); else if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral) icn = new ulong_const_node((ulong)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc); //учти здесь модет быть и long! //-DarkStar Add if (icn == null) { AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } return icn; } private int_const_node convert_const_to_switch(expression_node switch_expr, ordinal_type_interface oti, type_node case_expr_type, location loc) { convertion_data_and_alghoritms.convert_type(switch_expr, case_expr_type, loc); if (switch_expr is int_const_node) return switch_expr as int_const_node; //switch_expr = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, // loc, switch_expr); int_const_node icn = null;//switch_expr as constant_node; if (switch_expr is byte_const_node) icn = new int_const_node((switch_expr as byte_const_node).constant_value, loc); else if (switch_expr is sbyte_const_node) icn = new int_const_node(Convert.ToInt32((switch_expr as sbyte_const_node).constant_value), loc); else if (switch_expr is short_const_node) icn = new int_const_node(Convert.ToInt32((switch_expr as short_const_node).constant_value), loc); else if (switch_expr is ushort_const_node) icn = new int_const_node(Convert.ToInt32((switch_expr as ushort_const_node).constant_value), loc); else if (switch_expr is bool_const_node) icn = new int_const_node(Convert.ToInt32((switch_expr as bool_const_node).constant_value), loc); else if (switch_expr is char_const_node) icn = new int_const_node(Convert.ToInt32((switch_expr as char_const_node).constant_value), loc); else if (switch_expr is enum_const_node) icn = new int_const_node((switch_expr as enum_const_node).constant_value, loc); else if (switch_expr is static_compiled_variable_reference && (switch_expr as static_compiled_variable_reference).var.compiled_field.IsLiteral) icn = new int_const_node((int)(switch_expr as static_compiled_variable_reference).var.compiled_field.GetRawConstantValue(), loc); //учти здесь модет быть и long! //-DarkStar Add if (icn == null) { AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } return icn; } //TODO: Добавить приведение типов. public override void visit(SyntaxTree.case_node _case_node) { convertion_data_and_alghoritms.check_node_parser_error(_case_node); switch_node sn = new switch_node(get_location(_case_node)); expression_node en = convert_strong(_case_node.param); if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression); type_node case_expr_type = en.type; internal_interface ii = en.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null) { // Попытка воспользоваться неявным преобразованием if (convertion_data_and_alghoritms.can_convert_type(en, SystemLibrary.SystemLibrary.integer_type)) en = convertion_data_and_alghoritms.convert_type(en, SystemLibrary.SystemLibrary.integer_type); ii = en.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null) if (convertion_data_and_alghoritms.can_convert_type(en, SystemLibrary.SystemLibrary.string_type)) en = convertion_data_and_alghoritms.convert_type(en, SystemLibrary.SystemLibrary.string_type); } if (ii == null && en.type != SystemLibrary.SystemLibrary.string_type) { AddError(new OrdinalOrStringTypeExpected(en.location)); } if (ii != null && en.type != SystemLibrary.SystemLibrary.int64_type && en.type != SystemLibrary.SystemLibrary.uint64_type) { ordinal_type_interface oti = (ordinal_type_interface)ii; en = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, en.location, en); sn.condition = en; foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); case_variant_node sem_cv = new case_variant_node(get_location(cv)); sn.case_variants.AddElement(sem_cv); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { convertion_data_and_alghoritms.check_node_parser_error(expr); SyntaxTree.diapason_expr diap = expr as SyntaxTree.diapason_expr; if (diap == null) { expression_node cn = convert_strong(expr); int_const_node icn = convert_const_to_switch(cn, oti, case_expr_type, get_location(expr)); is_case_variant_intersection_with_another(sn, icn, get_location(expr)); sem_cv.case_constants.AddElement(icn); } else { convertion_data_and_alghoritms.check_node_parser_error(diap.left); expression_node left = convert_strong(diap.left); int_const_node icn_left = convert_const_to_switch(left, oti, case_expr_type, get_location(diap.left)); convertion_data_and_alghoritms.check_node_parser_error(diap.right); expression_node right = convert_strong(diap.right); int_const_node icn_right = convert_const_to_switch(right, oti, case_expr_type, get_location(diap.right)); //ssyy if (icn_left.constant_value > icn_right.constant_value) { AddError(get_location(diap.right), "LEFT_RANGE_GREATER_THEN_RIGHT"); } //\ssyy case_range_node crn = new case_range_node(icn_left, icn_right, get_location(diap)); is_case_range_intersection_with_another(sn, crn, get_location(expr)); sem_cv.case_ranges.AddElement(crn); } } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(cv.exec_if_true); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); sem_cv.case_statement = stmn; //sn.case_variants.AddElement(sem_cv); } context.enter_code_block_with_bind(); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); sn.default_statement = else_statement; return_value(sn); } else if (en.type == SystemLibrary.SystemLibrary.string_type) { if_node main_ifn = null; if_node ifn = null; compiled_function_node str_eq_meth = SystemLibrary.SystemLibrary.string_type.find_first_in_type("=").sym_info as compiled_function_node; Dictionary case_constants = new Dictionary(); foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); location loc = get_location(cv); expression_node eq_node = null; List eq_calls = new List(); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { expression_node cn = convert_strong(expr); if (cn.type == SystemLibrary.SystemLibrary.char_type) cn = convertion_data_and_alghoritms.convert_type(cn, SystemLibrary.SystemLibrary.string_type); if (cn.type != SystemLibrary.SystemLibrary.string_type) AddError(new CanNotConvertTypes(cn, cn.type, SystemLibrary.SystemLibrary.string_type, cn.location)); string_const_node scn = convert_string_const_to_switch(cn, cn.location); if (!case_constants.ContainsKey(scn.constant_value)) case_constants.Add(scn.constant_value, scn.constant_value); else AddError(cn.location, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER"); compiled_static_method_call eq_call = new compiled_static_method_call(str_eq_meth, cn.location); eq_call.parameters.AddElement(en); eq_call.parameters.AddElement(cn); eq_calls.Add(eq_call); } foreach (compiled_static_method_call eq_call in eq_calls) { if (eq_node == null) eq_node = eq_call; else eq_node = new basic_function_call(SystemLibrary.SystemLibrary.bool_or as basic_function_node, null, eq_node, eq_call); } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(cv.exec_if_true); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); if (ifn != null) { ifn.else_body = new if_node(eq_node, stmn, null, loc); ifn = ifn.else_body as if_node; } else ifn = new if_node(eq_node, stmn, null, loc); if (main_ifn == null) main_ifn = ifn; } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(_case_node.else_statement); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); if (ifn == null) { ifn = new if_node(new bool_const_node(false, null), new statements_list(null), null, get_location(_case_node)); main_ifn = ifn; } ifn.else_body = else_statement; return_value(main_ifn); } else if (en.type == SystemLibrary.SystemLibrary.int64_type) { if_node main_ifn = null; if_node ifn = null; basic_function_node int64_eq_meth = SystemLibrary.SystemLibrary.int64_type.find_first_in_type("=", true).sym_info as basic_function_node; Dictionary case_constants = new Dictionary(); foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); location loc = get_location(cv); expression_node eq_node = null; List eq_calls = new List(); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { SyntaxTree.diapason_expr diap = expr as SyntaxTree.diapason_expr; if (diap == null) { expression_node cn = convert_strong(expr); long_const_node scn = convert_long_const_to_switch(cn, cn.location); if (!case_constants.ContainsKey(scn.constant_value)) case_constants.Add(scn.constant_value, scn.constant_value); else AddError(cn.location, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER"); basic_function_call eq_call = new basic_function_call(int64_eq_meth, cn.location); eq_call.parameters.AddElement(en); eq_call.parameters.AddElement(scn); eq_calls.Add(eq_call); } else { expression_node left_cn = convert_strong(diap.left); expression_node right_cn = convert_strong(diap.right); long_const_node left_scn = convert_long_const_to_switch(left_cn, left_cn.location); long_const_node right_scn = convert_long_const_to_switch(right_cn, right_cn.location); if (left_scn.constant_value > right_scn.constant_value) { AddError(get_location(diap.right), "LEFT_RANGE_GREATER_THEN_RIGHT"); } basic_function_node int64_greq_meth = SystemLibrary.SystemLibrary.int64_type.find_first_in_type(">=", true).sym_info as basic_function_node; basic_function_node int64_leq_meth = SystemLibrary.SystemLibrary.int64_type.find_first_in_type("<=", true).sym_info as basic_function_node; basic_function_call greq_call = new basic_function_call(int64_greq_meth, left_cn.location); greq_call.parameters.AddElement(en); greq_call.parameters.AddElement(left_scn); basic_function_call leq_call = new basic_function_call(int64_leq_meth, right_cn.location); leq_call.parameters.AddElement(en); leq_call.parameters.AddElement(right_scn); basic_function_node in_diap_meth = SystemLibrary.SystemLibrary.bool_type.find_first_in_type("and", true).sym_info as basic_function_node; basic_function_call in_diap_call = new basic_function_call(in_diap_meth, left_cn.location); in_diap_call.parameters.AddElement(greq_call); in_diap_call.parameters.AddElement(leq_call); eq_calls.Add(in_diap_call); } } foreach (basic_function_call eq_call in eq_calls) { if (eq_node == null) eq_node = eq_call; else eq_node = new basic_function_call(SystemLibrary.SystemLibrary.bool_or as basic_function_node, null, eq_node, eq_call); } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(cv.exec_if_true); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); if (ifn != null) { ifn.else_body = new if_node(eq_node, stmn, null, loc); ifn = ifn.else_body as if_node; } else ifn = new if_node(eq_node, stmn, null, loc); if (main_ifn == null) main_ifn = ifn; } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(_case_node.else_statement); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); if (ifn == null) { ifn = new if_node(en, new statements_list(null), null, get_location(_case_node)); main_ifn = ifn; } ifn.else_body = else_statement; return_value(main_ifn); } else { if_node main_ifn = null; if_node ifn = null; basic_function_node uint64_eq_meth = SystemLibrary.SystemLibrary.uint64_type.find_first_in_type("=", true).sym_info as basic_function_node; Dictionary case_constants = new Dictionary(); foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); location loc = get_location(cv); expression_node eq_node = null; List eq_calls = new List(); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { SyntaxTree.diapason_expr diap = expr as SyntaxTree.diapason_expr; if (diap == null) { expression_node cn = convert_strong(expr); ulong_const_node scn = convert_ulong_const_to_switch(cn, cn.location); if (!case_constants.ContainsKey(scn.constant_value)) case_constants.Add(scn.constant_value, scn.constant_value); else AddError(cn.location, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER"); basic_function_call eq_call = new basic_function_call(uint64_eq_meth, cn.location); eq_call.parameters.AddElement(en); eq_call.parameters.AddElement(scn); eq_calls.Add(eq_call); } else { expression_node left_cn = convert_strong(diap.left); expression_node right_cn = convert_strong(diap.right); ulong_const_node left_scn = convert_ulong_const_to_switch(left_cn, left_cn.location); ulong_const_node right_scn = convert_ulong_const_to_switch(right_cn, right_cn.location); if (left_scn.constant_value > right_scn.constant_value) { AddError(get_location(diap.right), "LEFT_RANGE_GREATER_THEN_RIGHT"); } basic_function_node uint64_greq_meth = SystemLibrary.SystemLibrary.uint64_type.find_first_in_type(">=", true).sym_info as basic_function_node; basic_function_node uint64_leq_meth = SystemLibrary.SystemLibrary.uint64_type.find_first_in_type("<=", true).sym_info as basic_function_node; basic_function_call greq_call = new basic_function_call(uint64_greq_meth, left_cn.location); greq_call.parameters.AddElement(en); greq_call.parameters.AddElement(left_scn); basic_function_call leq_call = new basic_function_call(uint64_leq_meth, right_cn.location); leq_call.parameters.AddElement(en); leq_call.parameters.AddElement(right_scn); basic_function_node in_diap_meth = SystemLibrary.SystemLibrary.bool_type.find_first_in_type("and", true).sym_info as basic_function_node; basic_function_call in_diap_call = new basic_function_call(in_diap_meth, left_cn.location); in_diap_call.parameters.AddElement(greq_call); in_diap_call.parameters.AddElement(leq_call); eq_calls.Add(in_diap_call); } } foreach (basic_function_call eq_call in eq_calls) { if (eq_node == null) eq_node = eq_call; else eq_node = new basic_function_call(SystemLibrary.SystemLibrary.bool_or as basic_function_node, null, eq_node, eq_call); } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(cv.exec_if_true); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); if (ifn != null) { ifn.else_body = new if_node(eq_node, stmn, null, loc); ifn = ifn.else_body as if_node; } else ifn = new if_node(eq_node, stmn, null, loc); if (main_ifn == null) main_ifn = ifn; } context.enter_code_block_with_bind(); CheckToEmbeddedStatementCannotBeADeclaration(_case_node.else_statement); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); if (ifn == null) { ifn = new if_node(en, new statements_list(null), null, get_location(_case_node)); main_ifn = ifn; } ifn.else_body = else_statement; return_value(main_ifn); } } public override void visit(SyntaxTree.case_variant _case_variant) { throw new NotSupportedError(get_location(_case_variant)); } public override void visit(SyntaxTree.get_address _get_address) { expression_node exp = convert_strong(_get_address.address_of); if (!exp.is_addressed) { AddError(exp.location, "CAN_NOT_GET_ADDRESS_FROM_EXPRESSION"); } expression_node res = new get_addr_node(exp, get_location(_get_address)); return_value(res); } public override void visit(SyntaxTree.hex_constant _hex_constant) { expression_node en = null; if (_hex_constant.val <= Int32.MaxValue && _hex_constant.val >= Int32.MinValue) en = new int_const_node((int)_hex_constant.val, get_location(_hex_constant)); else en = new long_const_node(_hex_constant.val, get_location(_hex_constant)); return_value(en); } private System.Collections.Generic.List ConvertDirectives(SyntaxTree.compilation_unit cu) { System.Collections.Generic.List list = new System.Collections.Generic.List(); foreach (SyntaxTree.compiler_directive sncd in cu.compiler_directives) { list.Add(new compiler_directive(sncd.Name.text, sncd.Directive!=null?sncd.Directive.text:"", get_location(sncd), cu.file_name)); } return list; } //TODO: Слить как нибудь два следующих метода. public override void visit(SyntaxTree.program_module _program_module) { //MikhailoMMX Инициализация OpenMP OpenMP.InitOpenMP(_program_module.compiler_directives, this, _program_module); //\MikhailoMMX string namespace_name = ""; location loc = get_location(_program_module); if (_program_module.program_name != null) { namespace_name = _program_module.program_name.prog_name.name; loc = get_location(_program_module.program_name.prog_name); } _compiled_unit = new common_unit_node(); _compiled_unit.compiler_directives = ConvertDirectives(_program_module); SymbolTable.Scope[] used_units = build_referenced_units(ReferencedUnits,true); _compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units, namespace_name == ""? System.IO.Path.GetFileName(CurrentDocument) : namespace_name); common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc); cnsn.is_main = true; reset_for_interface(); UpdateUnitDefinitionItemForUnit(_compiled_unit); hard_node_test_and_visit(_program_module.program_block); context.check_labels(context.converted_namespace.labels); context.check_abstracts_implemented(inherited_from_partials_list); // frninja 28/04/16 - режем мусорные методы хелперы yield { var toRemove = cnsn.functions.Where(m => m.is_yield_helper).ToArray(); foreach (var m in toRemove) { cnsn.functions.remove(m); } } // end frninja common_namespace_function_node main_function = new common_namespace_function_node(StringConstants.temp_main_function_name, null, null, cnsn, null); main_function.function_code = context.code; context.apply_special_local_vars(main_function); cnsn.functions.AddElement(main_function); context.leave_block(); #if DEBUG /*var fname = "C:\\st1.txt"; if (System.IO.File.Exists(fname)) System.IO.File.Delete(fname); System.IO.File.AppendAllText(fname, SymbolTable.ToString());*/ #endif _compiled_unit.main_function = main_function; } private void reset_for_interface() { body_exists = false; } private bool check_for_dll_entry_module(List directives) { foreach (compiler_directive cd in directives) { if (string.Compare(cd.name,"apptype",true)==0 && string.Compare(cd.directive,"dll",true)==0) return true; } return false; } internal bool _is_interface_part = false; public override void visit(SyntaxTree.unit_module _unit_module) { //MikhailoMMX Инициализация OpenMP OpenMP.InitOpenMP(_unit_module.compiler_directives, this, _unit_module); //\MikhailoMMX //current_document=new document(_unit_module.file_name); string namespace_name = ""; _is_interface_part = true; location loc = null; if (_unit_module.unit_name != null) { namespace_name = _unit_module.unit_name.idunit_name.name; loc = get_location(_unit_module.unit_name.idunit_name); if (namespace_name.ToLower() != System.IO.Path.GetFileNameWithoutExtension(_unit_module.file_name).ToLower()) AddError(loc, "UNIT_NAME_MUST_BE_EQUAL_UNIT_FILE_NAME"); } _compiled_unit = new common_unit_node(_unit_module.unit_name.idunit_name.name); assign_doc_info(_compiled_unit,_unit_module.unit_name); _compiled_unit.compiler_directives = ConvertDirectives(_unit_module); SymbolTable.Scope[] used_units = build_referenced_units(ReferencedUnits,true); _compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units, "unit " + namespace_name); common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc); _compiled_unit.add_unit_name_to_namespace(); if (check_for_dll_entry_module(_compiled_unit.compiler_directives)) { cnsn.is_main = true; } UpdateUnitDefinitionItemForUnit(_compiled_unit); reset_for_interface(); in_interface_part = false; if (_unit_module.implementation_part != null) in_interface_part = true; hard_node_test_and_visit(_unit_module.interface_part); if (_unit_module.implementation_part != null) in_interface_part = false; if (_unit_module.attributes != null) make_attributes_for_declaration(_unit_module, _compiled_unit); context.leave_interface_part(); _is_interface_part = false; /*#if DEBUG var fname = "C:\\st1.txt"; if (System.IO.File.Exists(fname)) System.IO.File.Delete(fname); SymbolTable.ToString(); System.IO.File.AppendAllText(fname, SymbolTable.Print()); //var st = new SymbolTableVisitor("C:\\st1.txt", SymbolTable); //st.PrintProgam(true); #endif*/ } public void convert_pabc_namespaces(syntax_namespace_node[] namespaces) { context.namespace_converted = true; Dictionary dict = new Dictionary(); foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { _syntax_namespace_node.referenced_units.AddRange(ReferencedUnits); var names = _syntax_namespace_node.name.Split('.'); SymTable.Scope scope = null; SymTable.Scope parent_scope = context.CurrentScope; for (int i = 0; i < names.Length; i++) { var si_list = context.CurrentScope.Find(names[i]); if (si_list == null) { List top_scopes = new List(); top_scopes.AddRange(build_referenced_units(_syntax_namespace_node.referenced_units, false)); if (parent_scope != context.CurrentScope) top_scopes.Add(parent_scope); scope = convertion_data_and_alghoritms.symbol_table.CreateNamespaceScope(top_scopes.ToArray(), parent_scope); common_namespace_node cmn = new common_namespace_node(null, _compiled_unit, names[i], scope, null); parent_scope.AddSymbol(names[i], new SymbolInfo(cmn)); scope.AddSymbol(names[i], new SymbolInfo(cmn)); if (i == names.Length - 1) { dict.Add(_syntax_namespace_node, cmn); var unit_scope = context.converted_namespace.scope as SymTable.UnitInterfaceScope; if (unit_scope.TopScopeArray != null) for (int j = 0; j < unit_scope.TopScopeArray.Length; j++) { if (unit_scope.TopScopeArray[j] is NetHelper.NetScope) { NetHelper.NetScope netScope = unit_scope.TopScopeArray[j] as NetHelper.NetScope; if (netScope.used_namespaces.Count > 0 && string.Compare(netScope.used_namespaces[0].namespace_name, _syntax_namespace_node.name, true) == 0) { unit_scope.TopScopeArray[j] = scope; } } } } } else { foreach (SymbolInfo si in si_list) if (si.sym_info is common_namespace_node) { common_namespace_node cmn = si.sym_info as common_namespace_node; scope = cmn.scope; if (!(scope is SymTable.NamespaceScope)) { if (i == names.Length - 1) dict.Add(_syntax_namespace_node, cmn); } break; } else if (si.sym_info is compiled_namespace_node) { List top_scopes = new List(); top_scopes.AddRange(build_referenced_units(_syntax_namespace_node.referenced_units, false)); if (parent_scope != context.CurrentScope) top_scopes.Add(parent_scope); compiled_namespace_node cnn = si.sym_info as compiled_namespace_node; if (cnn.common_namespace == null) { scope = convertion_data_and_alghoritms.symbol_table.CreateNamespaceScope(top_scopes.ToArray(), parent_scope); common_namespace_node cmn = new common_namespace_node(null, _compiled_unit, names[i], scope, null); cnn.common_namespace = cmn; } else scope = cnn.common_namespace.scope; if (i == names.Length - 1 && !dict.ContainsKey(_syntax_namespace_node)) dict.Add(_syntax_namespace_node, cnn.common_namespace); } if (scope == null) AddError(get_location(_syntax_namespace_node), "NAMESPACE_REDECLARATION"); } parent_scope = scope; } } foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { var cmn = dict[_syntax_namespace_node]; List scopes = new List(); SymTable.UnitInterfaceScope ns_scope = cmn.scope as SymTable.UnitInterfaceScope; if (ns_scope.TopScopeArray != null) scopes.AddRange(ns_scope.TopScopeArray); foreach (unit_node un in _syntax_namespace_node.referenced_units) { if (un is namespace_unit_node) { var nun = un as namespace_unit_node; var names = nun.namespace_name.namespace_name.Split('.'); var si_list = context.CurrentScope.Find(names[0]); if (si_list != null && si_list.FirstOrDefault().sym_info is common_namespace_node) { SymTable.Scope ns_scope2 = (si_list.FirstOrDefault().sym_info as common_namespace_node).scope; for (int i = 1; i < names.Length; i++) { si_list = ns_scope2.Find(names[i]); if (si_list != null && si_list.FirstOrDefault().sym_info is common_namespace_node) ns_scope2 = (si_list.FirstOrDefault().sym_info as common_namespace_node).scope; else AddError(new NamespaceNotFound(nun.namespace_name.namespace_name, un.location)); } scopes.Add(ns_scope2); } else if (si_list == null) AddError(new NamespaceNotFound(nun.namespace_name.namespace_name, un.location)); } } ns_scope.TopScopeArray = scopes.ToArray(); } //convert type predefinitions foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { var cmn = dict[_syntax_namespace_node]; var scope = cmn.scope; context.enter_scope(scope); foreach (declaration decl in _syntax_namespace_node.defs) { if (decl is type_declarations) { type_declarations type_decls = decl as type_declarations; foreach (type_declaration td in type_decls.types_decl) { if (td.type_def is class_definition) { class_definition cl_def = td.type_def as class_definition; if (cl_def.body == null) AddError(get_location(cl_def), "TYPE_PREDEFINITION_NOT_ALLOWED"); common_type_node ctn = null; if (td.type_name is template_type_name) ctn = context.advanced_create_type(td.type_name.name + "`" + (td.type_name as template_type_name).template_args.Count, get_location(td.type_name), (td.type_def as class_definition).keyword == class_keyword.Interface, (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial, cl_def.attribute); else ctn = context.advanced_create_type(td.type_name.name, get_location(td.type_name), (td.type_def as class_definition).keyword == class_keyword.Interface, (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial, cl_def.attribute); ctn.ForwardDeclarationOnly = true; if ((td.type_def as class_definition).keyword == class_keyword.Interface) ctn.IsInterface = true; context.converted_type = null; context.add_type_header(td, ctn); } else if (td.type_def is procedure_header || td.type_def is function_header || td.type_def is named_type_reference) { } else if (td.type_def is enum_type_definition) { hard_node_test_and_visit(td); } else AddError(get_location(decl), "NAMESPACE_SHOULD_CONTAINS_ONLY_TYPES"); } } else if (decl is procedure_definition /*&& get_location(decl) == null*/) { //yield } else AddError(get_location(decl), "NAMESPACE_SHOULD_CONTAINS_ONLY_TYPES"); } context.leave_scope(); } foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { common_namespace_node cmn = dict[_syntax_namespace_node]; context.enter_scope(cmn.scope); foreach (declaration decl in _syntax_namespace_node.defs) { if (decl is type_declarations) { type_declarations type_decls = decl as type_declarations; foreach (type_declaration td in type_decls.types_decl) { if (td.type_def is procedure_header || td.type_def is function_header || td.type_def is named_type_reference) { hard_node_test_and_visit(td); if (!(td.type_def is named_type_reference)) { common_type_node ctn = context.converted_namespace.types[context.converted_namespace.types.Count - 1]; ctn.SetName(_syntax_namespace_node.name + "." + ctn.name); } } } } } context.leave_scope(); } foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { common_namespace_node cmn = dict[_syntax_namespace_node]; context.enter_scope(cmn.scope); foreach (declaration decl in _syntax_namespace_node.defs) { if (decl is type_declarations) { type_declarations type_decls = decl as type_declarations; foreach (type_declaration td in type_decls.types_decl) { if (td.type_def is class_definition) { hard_node_test_and_visit(td); common_type_node ctn = context.converted_namespace.types[context.converted_namespace.types.Count - 1]; ctn.SetName(_syntax_namespace_node.name + "." + ctn.name); } } } else if (decl is procedure_definition) { SemanticRulesConstants.OrderIndependedFunctionNames = true; hard_node_test_and_visit(decl); } } context.leave_scope(); } foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { common_namespace_node cmn = dict[_syntax_namespace_node]; context.enter_scope(cmn.scope); foreach (declaration decl in _syntax_namespace_node.defs) { if (decl is procedure_definition) { common_function_node cfn = context.get_method_to_realize(decl); if (cfn != null) { context.push_function(cfn); if ((decl as SyntaxTree.procedure_definition).proc_body != null) { hard_node_test_and_visit((decl as SyntaxTree.procedure_definition).proc_body); add_clip_for_set(context.top_function); context.leave_block(); } } } } context.leave_scope(); } foreach (syntax_namespace_node _syntax_namespace_node in namespaces) { common_namespace_node cmn = dict[_syntax_namespace_node]; context.enter_scope(cmn.scope); foreach (declaration decl in _syntax_namespace_node.defs) { if (decl is type_declarations) { type_declarations type_decls = decl as type_declarations; foreach (type_declaration td in type_decls.types_decl) { if (td.type_def is class_definition) { context.converted_type = context.get_type_to_realize(td); class_definition cl_def = td.type_def as class_definition; visit_class_member_realizations(cl_def.body); context.converted_type = null; } } } } context.leave_scope(); } context.namespace_converted = false; context.clear_member_bindings(); } public override void visit(SyntaxTree.compilation_unit _compilation_unit) { if (_compilation_unit.source_context == null) throw new NotSupportedError(); throw new NotSupportedError(get_location(_compilation_unit)); } public override void visit(SyntaxTree.program_body _program_body) { throw new NotSupportedError(get_location(_program_body)); } public override void visit(SyntaxTree.uses_list _uses_list) { throw new NotSupportedError(get_location(_uses_list)); } public override void visit(SyntaxTree.uses_unit_in _uses_unit_in) { throw new NotSupportedError(get_location(_uses_unit_in)); } public override void visit(SyntaxTree.unit_name _unit_name) { throw new NotSupportedError(get_location(_unit_name)); } public override void visit(SyntaxTree.consts_definitions_list _consts_definitions_list) { //ssyy if (context.converting_block() == block_type.type_block && context.converted_type.IsInterface) { AddError(get_location(_consts_definitions_list), "INVALID_INTERFACE_MEMBER"); } //\ssyy foreach (SyntaxTree.const_definition cnst in _consts_definitions_list.const_defs) cnst.visit(this); } public override void visit(SyntaxTree.const_definition _const_definition) { throw new NotSupportedError(get_location(_const_definition)); } private bool IsBoundedArray(type_node tn) { return tn.get_internal_interface(internal_interface_kind.bounded_array_interface) != null; } private bool IsUnsizedArray(type_node tn) { return tn.get_internal_interface(internal_interface_kind.unsized_array_interface) != null; } private type_node const_def_type=null; private bool is_typed_const_def=false; public override void visit(SyntaxTree.typed_const_definition _typed_const_definition) { location cons_loc = get_location(_typed_const_definition.const_value); constant_definition_node cdn = context.add_const_definition(_typed_const_definition.const_name.name, get_location(_typed_const_definition.const_name)); type_node tn = convert_strong(_typed_const_definition.const_type); assign_doc_info(cdn,_typed_const_definition); check_for_type_allowed(tn,get_location(_typed_const_definition.const_type)); check_using_static_class(tn, get_location(_typed_const_definition.const_type)); if (context.converted_type != null && context.converted_func_stack.Count == 0) if (!constant_in_class_valid(tn))//proverka na primitivnost konstanty v klasse AddError(get_location(_typed_const_definition), "CLASS_CONSTANT_CAN_HAVE_ONLY_PRIMITIVE_VALUE"); if (tn is common_type_node) { if (!SemanticRulesConstants.DefineMethodsInConstantRecord) CheckConstantRecordNotBeContainsMethods(tn as common_type_node, get_location(_typed_const_definition.const_type)); if (!SemanticRulesConstants.InheritanceConstantRecord) //mnozhestvo zdes iskljuchenie if (tn.base_type is common_type_node && tn.base_type.type_special_kind != SemanticTree.type_special_kind.base_set_type/*tn.base_type != SystemLibrary.SystemLibInitializer.TypedSetType.sym_info as type_node*/) AddError(get_location(_typed_const_definition.const_type), "CONSTANT_RECORD_CAN_NOT_BE_INHERITANCE"); } const_def_type = tn.element_type; is_typed_const_def = true; _typed_const_definition.const_value = get_possible_array_const(_typed_const_definition.const_value,tn); cdn.const_value = convert_strong_to_constant_node(_typed_const_definition.const_value, tn); const_def_type = null; is_typed_const_def = false; if (cdn is class_constant_definition && (cdn.constant_value.value == null && !(cdn.constant_value is array_const))) AddError(new NotSupportedError(cons_loc)); } private void CheckConstantRecordNotBeContainsMethods(common_type_node ctn, location loc) { if (ctn.is_value) { if (ctn.methods.Count > 0) { for (int i=0; i 1) { AddError(get_location(tpars.idents.idents[1]), "ONLY_ONE_PARAMS_PARAMETER_ALLOWED"); } } SyntaxTree.array_type arr = tpars.vars_type as SyntaxTree.array_type; if (tpars.vars_type is SyntaxTree.class_definition || /*tpars.vars_type is SyntaxTree.enum_type_definition ||*/ (arr != null && arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null)) { AddError(get_location(tpars.vars_type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); } type_node tp = convert_strong(tpars.vars_type); if (tpars.param_kind == SyntaxTree.parametr_kind.params_parametr) { internal_interface ii = tp.get_internal_interface(internal_interface_kind.unsized_array_interface); if (ii == null) { AddError(get_location(tpars.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED"); } } foreach (common_parameter ccp in temp_params) { ccp.type = tp; } if (params_met) { AddError(get_location(tpars), "ONLY_LAST_PARAMETER_CAN_BE_PARAMS"); } if (tpars.param_kind == PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr) { params_met = true; } } } type_node ret_val_type = null; if (return_type != null) { ret_val_type = convert_strong(return_type); } common_type_node del; if (del_type == null) { del = convertion_data_and_alghoritms.type_constructor.create_delegate(type_name, ret_val_type, parameters, context.converted_namespace, loc); } else { del = del_type; convertion_data_and_alghoritms.type_constructor.init_delegate(del, ret_val_type, parameters, loc); } context.converted_namespace.types.AddElement(del); return del; } private string get_template_instance_name(string template_name, System.Collections.Generic.List args) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("$"); sb.Append("template_"); sb.Append(template_name); foreach (string s in args) { sb.Append("$"); sb.Append(s); } return sb.ToString(); } private string record_type_name = null; private bool record_is_generic = false; private void check_where_section(SyntaxTree.class_definition cl_def) { if (cl_def.where_section != null && cl_def.where_section.defs != null) { AddError(get_location(cl_def.where_section), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS"); } } //(ssyy) Проверяет параметры шаблона на совпадение друг с другом private void check_param_redeclared(List idents) { for (int i = 0; i < idents.Count; i++) for (int j = i + 1; j < idents.Count; j++) { if (string.Equals(idents[i].name, idents[j].name, StringComparison.InvariantCultureIgnoreCase)) { AddError(get_location(idents[j]), "TEMPLATE_PARAMETER_{0}_REDEFINITION", idents[j].name); } } if (context.top_function != null && context.converted_type != null && context.converted_type.is_generic_type_definition) { //List gparams = context.converted_type.generic_params; foreach (SyntaxTree.ident id in idents) foreach(SemanticTree.ICommonTypeNode ictn in context.converted_type.generic_params) if (string.Equals(id.name, ictn.name, StringComparison.InvariantCultureIgnoreCase)) { AddError(get_location(id), "TEMPLATE_PARAMETER_{0}_REDEFINITION", id.name); } } } private void visit_generic_params(common_type_node ctn, List idents) { if (SemanticRulesConstants.RuntimeInitVariablesOfGenericParameters) { if (SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction != null) // SSM 12/05/15 - из-за отсутствия этого падало при наличии обобщенных классов в системном модуле! Ужас! SystemLibrary.SystemLibInitializer.RuntimeInitializeFunction.Restore(); } ctn.is_generic_type_definition = true; check_param_redeclared(idents); ctn.generic_params = new List(); foreach (SyntaxTree.ident id in idents) { common_type_node par = new common_type_node( id.name, SemanticTree.type_access_level.tal_public, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), get_location(id)); SystemLibrary.SystemLibrary.init_reference_type(par); par.SetBaseType(SystemLibrary.SystemLibrary.object_type); par.generic_type_container = ctn; ctn.generic_params.Add(par); ctn.scope.AddSymbol(id.name, new SymbolInfo(par)); if (SemanticRulesConstants.RuntimeInitVariablesOfGenericParameters && !ctn.IsInterface && !ctn.IsDelegate) { class_field cf = new class_field( StringConstants.generic_param_kind_prefix + id.name, SystemLibrary.SystemLibrary.byte_type, ctn, PascalABCCompiler.SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, null); ctn.fields.AddElement(cf); par.runtime_initialization_marker = cf; } } } private void visit_generic_params(common_function_node cfn, List idents) { check_param_redeclared(idents); cfn.generic_params = new List(); foreach (SyntaxTree.ident id in idents) { common_type_node par = new common_type_node( id.name, SemanticTree.type_access_level.tal_public, context.converted_namespace, convertion_data_and_alghoritms.symbol_table.CreateInterfaceScope(null, SystemLibrary.SystemLibrary.object_type.Scope, null), get_location(id)); // voloshinbogdan 2018.05.21 Fix missing attributes translation for generic parameters make_attributes_for_declaration(id, par); SystemLibrary.SystemLibrary.init_reference_type(par); par.SetBaseType(SystemLibrary.SystemLibrary.object_type); par.generic_function_container = cfn; cfn.generic_params.Add(par); cfn.scope.AddSymbol(id.name, new SymbolInfo(par)); } } public override void visit(SyntaxTree.type_declaration _type_declaration) { if (_type_declaration.type_name.name.ToLower() == "program") { AddError(get_location(_type_declaration), "PROGRAM_NAME_FOR_TYPE_NAME_IS_PROHIBITED"); } //bool is_template_synonym = false; //SyntaxTree.array_type at=_type_declaration.type_def as SyntaxTree.array_type; if (_type_declaration.type_def is class_definition cd && cd.keyword == class_keyword.Class && (cd.attribute & SyntaxTree.class_attribute.Static) == SyntaxTree.class_attribute.Static) { var name = _type_declaration.type_name.name.ToLower(); if(context.types_predefined.Select(tn => tn.name.ToLower()).Contains(name)) AddError(get_location(_type_declaration), "STATIC_CLASS_CANNOT_HAVE_PREDEFINITION"); // #2266 } template_class tc = null; SyntaxTree.template_type_name ttn = _type_declaration.type_name as SyntaxTree.template_type_name; SyntaxTree.class_definition cl_def = _type_declaration.type_def as SyntaxTree.class_definition; SyntaxTree.function_header function_header = _type_declaration.type_def as SyntaxTree.function_header; SyntaxTree.procedure_header procedure_header = _type_declaration.type_def as SyntaxTree.procedure_header; if (cl_def != null && (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial && cl_def.keyword != SyntaxTree.class_keyword.Class) { AddError(get_location(_type_declaration), "ONLY_CLASS_CAN_BE_PARTIAL"); } if (ttn != null && cl_def == null && function_header == null && procedure_header == null) { location t_loc = get_location(ttn); context.check_name_free(ttn.name, t_loc); tc = new template_class(_type_declaration, ttn.name, context.converted_namespace, current_document, using_list); tc.is_synonym = true; //Проверяем параметры шаблона на совпадение друг с другом check_param_redeclared(ttn.template_args.idents); context.AddTemplate(ttn.name, tc, t_loc); // SSM 23.10.18. Bug fix #1395. Пытаемся проверить, что это - enum. Повторяем с изменениями код в enum_type_node if (_type_declaration.type_def is enum_type_definition etd) { // значит это возможно enum //var etd = foreach (SyntaxTree.enumerator en in etd.enumerators.enumerators) { if (!((en.name is named_type_reference) && (en.name as named_type_reference).names.Count() == 1)) { // Это tupletype return; } // Все - идентификаторы. Проверяем дальше SyntaxTree.ident id = (en.name as named_type_reference).FirstIdent; // Если равен какому-то имени в параметрах обобщения, то это тип - пропускаем. Ищем не тип или неизвестное имя if (ttn.template_args.idents.Select(ide => ide.name.ToLower()).Any(s => s.Equals(id.name.ToLower()))) continue; var si = context.CurrentScope.Find(id.name); if ((si == null) || !(si.FirstOrDefault().sym_info is type_node)) { // Это точно enum. Выдавать ошибку - enumы не могут быть обобщёнными AddError(get_location(ttn), "ENUMS_CANNOT_BE_GENERIC"); } } } // Это не enum. Значит, просто выйти. Так было в коде до SSM 23.10.18 return; //is_template_synonym = true; //AddError(new TemplateCanBeClassOnly(get_location(ttn))); } if ((function_header != null) || (procedure_header != null)) { location loc; if (function_header != null) loc = get_location(function_header); else loc = get_location(procedure_header); string del_name = _type_declaration.type_name.name; if (ttn != null) { if (context.top_function != null) { AddError(loc, "GENERIC_DELEGATE_INNER_FUNCTION"); } del_name += StringConstants.generic_params_infix + ttn.template_args.idents.Count; } context.check_name_free(del_name, loc); common_type_node del_type = convertion_data_and_alghoritms.type_constructor.create_delegate_without_init( del_name, context.converted_namespace, loc); //(ssyy) Обработка дженериков common_type_node tmp_converted_type = null; if (ttn != null) { tmp_converted_type = context.converted_type; context.converted_type = del_type; visit_generic_params(del_type, ttn.template_args.idents); } if (function_header != null) { del_type = convert_function_type(function_header, loc, del_name, del_type); } else { del_type = convert_function_type(procedure_header, loc, del_name, del_type); } if (ttn != null) { context.converted_type = tmp_converted_type; } //blocks.converted_namespace.types.AddElement(del_type); CheckWaitedRefTypes(del_type); if (_type_declaration.attributes != null) { make_attributes_for_declaration(_type_declaration,del_type); } context.converted_namespace.scope.AddSymbol(del_name, new SymbolInfo(del_type)); return; } if (cl_def == null && ttn == null) { string name = _type_declaration.type_name.name; location loc = get_location(_type_declaration.type_name); context.check_name_free(name, loc); is_direct_type_decl = true; type_node tn = convert_strong(_type_declaration.type_def); if (_type_declaration.type_def is enum_type_definition) context.check_name_free(name, loc); assign_doc_info(tn,_type_declaration); is_direct_type_decl = false; if (_type_declaration.type_def is SyntaxTree.named_type_reference|| _type_declaration.type_def is SyntaxTree.ref_type || _type_declaration.type_def is SyntaxTree.string_num_definition || _type_declaration.type_def is SyntaxTree.sequence_type || //SSM 01.11.2018 _type_declaration.type_def is SyntaxTree.set_type_definition || //SSM 07.11.2024 tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_kind)// || /*tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type*/ { if (context.converted_func_stack.Count == 0) { type_synonym ts = new type_synonym(name, tn, loc); assign_doc_info(ts,_type_declaration); context.converted_namespace.type_synonyms.Add(ts); } } else { tn.SetName(context.BuildName(name, generatedNamesManager)); } if (_type_declaration.attributes != null) if (_type_declaration.type_def is SyntaxTree.enum_type_definition) { make_attributes_for_declaration(_type_declaration,tn); (tn as common_type_node).add_additional_enum_operations(); } else AddError(get_location(_type_declaration.attributes), "ATTRIBUTES_APPLICABLE_ONLY_TO_THESE_TYPES"); context.add_type(name, tn, loc); return; } //Проверим, что список template-ов не пуст bool is_generic = false; if (ttn != null && cl_def != null && cl_def.template_args == null) { cl_def.template_args = ttn.template_args; } if (cl_def != null && cl_def.template_args != null && cl_def.template_args.idents != null && cl_def.template_args.idents.Count > 0) { switch (cl_def.keyword) { case PascalABCCompiler.SyntaxTree.class_keyword.TemplateClass: cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Class; is_generic = false; check_where_section(cl_def); break; case PascalABCCompiler.SyntaxTree.class_keyword.TemplateRecord: cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Record; is_generic = false; check_where_section(cl_def); break; case PascalABCCompiler.SyntaxTree.class_keyword.TemplateInterface: cl_def.keyword = PascalABCCompiler.SyntaxTree.class_keyword.Interface; is_generic = false; check_where_section(cl_def); break; default: is_generic = true; break; } if (!is_generic) { string t_name = _type_declaration.type_name.name; location t_loc = get_location(_type_declaration.type_name); List sil = context.find_only_in_namespace(t_name); tc = null; //Ищем предописание if (sil != null) { tc = sil.FirstOrDefault().sym_info as template_class; if (tc == null || !tc.ForwardDeclarationOnly) { AddError(new NameRedefinition(t_name, convertion_data_and_alghoritms.get_location(sil.FirstOrDefault().sym_info), t_loc)); } SyntaxTree.class_definition prev_cl_def = tc.type_dec.type_def as SyntaxTree.class_definition; if (prev_cl_def.keyword != cl_def.keyword || prev_cl_def.template_args.idents.Count != cl_def.template_args.idents.Count) { AddError(t_loc, "FORWARD_TEMPLATE_{0}_DECLARATION_MISMATCH_DECLARATION", t_name); } for (int k = 0; k < cl_def.template_args.idents.Count; k++) { if (string.Compare(cl_def.template_args.idents[k].name, prev_cl_def.template_args.idents[k].name, true) != 0) { AddError(t_loc, "FORWARD_TEMPLATE_{0}_DECLARATION_MISMATCH_DECLARATION", t_name); } } if (cl_def.body == null) { AddError(new NameRedefinition(t_name, convertion_data_and_alghoritms.get_location(sil.FirstOrDefault().sym_info), t_loc)); } tc.type_dec = _type_declaration; tc.ForwardDeclarationOnly = false; return; } tc = new template_class(_type_declaration, t_name, context.converted_namespace, current_document, using_list); //Проверяем параметры шаблона на совпадение друг с другом check_param_redeclared(cl_def.template_args.idents); tc.ForwardDeclarationOnly = cl_def.body == null; context.AddTemplate(t_name, tc, t_loc); if (!tc.ForwardDeclarationOnly && template_class.check_template_definitions) { int count = cl_def.template_args.idents.Count; List test_types = new List(count); for (int i = 0; i < count; i++) { test_types.Add(new indefinite_type_node(cl_def.template_args.idents[i].name)); } instance(tc, test_types, t_loc); } return; } } //(ssyy) Теперь проверим на модификатор template if (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateClass || cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateRecord || cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.TemplateInterface) { //Ошибка, т.к. нет списка шаблонных параметров. AddError(get_location(_type_declaration.type_name), "TEMPLATE_PARAMS_EXPECTED"); } bool predefined_generic = false; if (is_generic) { List sil = context.find_only_in_namespace(_type_declaration.type_name.name + StringConstants.generic_params_infix + cl_def.template_args.idents.Count.ToString()); if (!(sil != null && sil.FirstOrDefault().sym_info is common_type_node && ((sil.FirstOrDefault().sym_info as common_type_node).IsPartial || context.types_predefined.IndexOf(sil.FirstOrDefault().sym_info as common_type_node) != -1))) { context.check_name_free(_type_declaration.type_name.name, get_location(_type_declaration.type_name)); } else predefined_generic = true; _type_declaration.type_name.name += StringConstants.generic_params_infix + cl_def.template_args.idents.Count.ToString(); } if (cl_def.keyword == SyntaxTree.class_keyword.Record) { string name = record_type_name = _type_declaration.type_name.name; if (context.top_function != null && context.top_function.generic_params != null) { AddError(get_location(_type_declaration.type_name), "NESTED_RECORDS_IN_GENERIC_FUNCTIONS_NOT_ALLOWED"); } record_is_generic = is_generic; location loc = get_location(_type_declaration.type_name); context.check_name_free(name, loc); //context.create_record_type(loc, record_type_name); is_direct_type_decl = true; type_node tn = convert_strong(_type_declaration.type_def); assign_doc_info(tn,_type_declaration); if (_type_declaration.attributes != null) { make_attributes_for_declaration(_type_declaration, tn); } is_direct_type_decl = false; record_type_name = null; record_is_generic = false; tn.SetName(context.BuildName(name, generatedNamesManager)); return; } //(ssyy) Флаг показывает, создаём ли мы интерфейс bool interface_creating = (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface); common_type_node ctn = context.advanced_create_type(_type_declaration.type_name.name, get_location(_type_declaration.type_name), interface_creating, (cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial, cl_def.attribute); assign_doc_info(ctn,_type_declaration); if (_type_declaration.attributes != null) { make_attributes_for_declaration(_type_declaration, ctn); } if (cl_def.keyword == class_keyword.Class || cl_def.keyword == class_keyword.Interface) ctn.is_class = true;//nado ranshe pomechat kak is_class if (is_generic) { if (predefined_generic) { if (ctn.generic_params.Count != cl_def.template_args.idents.Count) AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH"); foreach (ident id in cl_def.template_args.idents) { SymbolInfo si = ctn.find_first_in_type(id.name); if (si == null) AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH"); if (!(si.sym_info is common_type_node && (si.sym_info as common_type_node).is_generic_parameter)) AddError(get_location(cl_def.template_args), "GENERIC_PARAMETERS_MISMATCH"); } } else { context.create_generic_indicator(ctn); visit_generic_params(ctn, cl_def.template_args.idents); } } if (predefined_generic && cl_def.where_section != null && cl_def.where_section.defs.Count > 0) AddError(get_location(cl_def.where_section), "WHERE_SECTION_NOT_ALLOWED"); visit_where_list(cl_def.where_section); if ((cl_def.attribute & SyntaxTree.class_attribute.Partial) == SyntaxTree.class_attribute.Partial && cl_def.class_parents != null) { type_node tn = ret.visit(cl_def.class_parents.types[0]); if (!tn.IsInterface && ctn.base_type != SemanticRulesConstants.ClassBaseType && ctn.base_type != null && !ctn.base_type.IsInterface && tn != ctn.base_type) AddError(get_location(cl_def.class_parents), "PARTIAL_CLASS_PARENTS_MISMATCH"); /*if (ctn.ImplementingInterfaces.Count != cl_def.class_parents.types.Count - 1) AddError(get_location(cl_def.class_parents), "PARTIAL_CLASS_PARENTS_MISMATCH"); for (int i=1; i < cl_def.class_parents.types.Count; i++) { tn = ret.visit(cl_def.class_parents.types[i]); if (ctn.ImplementingInterfaces[i-1] != tn) AddError(get_location(cl_def.class_parents.types[i]), "PARTIAL_CLASS_PARENTS_MISMATCH"); }*/ } CheckWaitedRefTypes(ctn); is_direct_type_decl = true; hard_node_test_and_visit(_type_declaration.type_def); check_where_from_base_class(ctn); // frninja 28/04/16 - режем мусорные методы хелперы yield { var toRemove = ctn.methods.Where(m => m.is_yield_helper).ToArray(); foreach (var m in toRemove) { ctn.methods.remove(m); } } // end frninja is_direct_type_decl = false; } private bool attribute_converted = false; private AttributeTargets get_usage_attrs(type_node tn, out bool allowMultiple) { allowMultiple = false; if (tn is common_type_node) { common_type_node ctn = tn as common_type_node; for (int i=0; i(); foreach (SyntaxTree.simple_attribute_list sal in td.attributes.attributes) for (int j = 0; j < sal.attributes.Count; j++) { SyntaxTree.attribute attr = sal.attributes[j]; attribute_converted = true; type_node tn = convert_strong(attr.type); bool is_attr = false; type_node tmp = tn; while (tmp.base_type != null && !is_attr) { is_attr = tmp.base_type == SystemLibrary.SystemLibrary.attribute_type; tmp = tmp.base_type; } if (!is_attr) AddError(get_location(attr), "CLASS_{0}_NOT_ATTRIBUTE", tn.name); bool allowMultiple = false; AttributeTargets targets = get_usage_attrs(tn, out allowMultiple); if (ht.Contains(tn) && !allowMultiple) { AddError(get_location(attr), "DUPLICATE_ATTRIBUTE_{0}_APPLICATION", tn.name); } else ht.Add(tn); SemanticTree.attribute_qualifier_kind qualifier = SemanticTree.attribute_qualifier_kind.none_kind; if (attr.qualifier != null) if (j == 0) { if (attr.qualifier.name.Equals("return", context.CurrentScope.StringComparison) || attr.qualifier.name.Equals(result_var_name, context.CurrentScope.StringComparison)) { if (context.top_function == null) AddError(get_location(attr), "ATTRIBUTE_APPLICABLE_ONLY_TO_METHOD"); if (context.top_function.return_value_type == null || context.top_function.return_value_type == SystemLibrary.SystemLibrary.void_type) AddError(get_location(attr), "EXPECTED_RETURN_VALUE_FOR_ATTRIBUTE"); //throw new NotSupportedError(get_location(attr.qualifier)); qualifier = SemanticTree.attribute_qualifier_kind.return_kind; } else throw new NotSupportedError(get_location(attr.qualifier)); } else AddError(get_location(attr.qualifier), "ATTRIBUTE_QUALIFIER_MUST_BE_FIRST"); if (tn.is_generic_type_instance || tn.is_generic_type_definition) AddError(get_location(attr), "ATTRIBUTE_CANNOT_BE_GENERIC"); check_for_usage_attribute(ctn, targets, tn.name, get_location(attr), qualifier); attribute_converted = false; SyntaxTree.expression_list cnstr_args = new SyntaxTree.expression_list(); if (attr.arguments != null) { foreach (SyntaxTree.expression e in attr.arguments.expressions) { if (e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident) { break; } else { cnstr_args.expressions.Add(e); } } } expressions_list args = new expressions_list(); for (int i = 0; i < cnstr_args.expressions.Count; i++) { constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]); if (cn is basic_function_call_as_constant && (cn as basic_function_call_as_constant).method_call.function_node.compile_time_executor != null) cn = (cn as basic_function_call_as_constant).method_call.function_node.compile_time_executor(cn.location, (cn as basic_function_call_as_constant).method_call.parameters.ToArray()) as constant_node; check_for_strong_constant(cn, get_location(cnstr_args.expressions[i])); args.AddElement(cn); } context.save_var_definitions(); base_function_call bfc = create_constructor_call(tn, args, get_location(attr)); context.restore_var_definitions(); if (ctn is common_type_node && tn == SystemLibrary.SystemLibrary.struct_layout_attribute_type) { if ((System.Runtime.InteropServices.LayoutKind)Convert.ToInt32((args[0] as constant_node).get_object_value()) == System.Runtime.InteropServices.LayoutKind.Explicit) { check_all_fields_have_field_offset_attr(ctn as common_type_node); } } attribute_node attr_node = new attribute_node(bfc.simple_function_node, tn, get_location(attr)); foreach (expression_node en in bfc.parameters) { constant_node cn = null; if (en is array_initializer) { List cnst_list = new List(); foreach (expression_node ex in (en as array_initializer).element_values) { constant_node elem_cn = convert_strong_to_constant_node(ex, ex.type); check_for_strong_constant(elem_cn, ex.location); cnst_list.Add(elem_cn); } cn = convert_strong_to_constant_node(new array_const(cnst_list, en.location), en.type); } else { cn = convert_strong_to_constant_node(en, en.type); check_for_strong_constant(cn, en.location); } attr_node.args.Add(cn); } if (attr.arguments != null) { for (int i = cnstr_args.expressions.Count; i < attr.arguments.expressions.Count; i++) { SyntaxTree.expression e = attr.arguments.expressions[i]; if (!(e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident)) { AddError(get_location(e), "EXPECTED_ATTRIBUTE_INITIALIZER"); } else { SyntaxTree.ident id = (e as SyntaxTree.bin_expr).left as SyntaxTree.ident; SymbolInfo si = tn.find_first_in_type(id.name); definition_node dn; if (si != null) dn = context.check_name_node_type(id.name, si, get_location(id), general_node_type.property_node, general_node_type.variable_node); else dn = context.check_name_node_type(id.name, null, get_location(id), general_node_type.property_node, general_node_type.variable_node); type_node mem_tn = null; if (dn is property_node) { property_node pn = dn as property_node; attr_node.prop_names.Add(pn); if (pn.set_function == null) AddError(new ThisPropertyCanNotBeWrited(pn, get_location(id))); if (pn.set_function.parameters.Count != 1) AddError(get_location(id), "INDEX_PROPERTY_INITIALIZING_NOT_VALID"); mem_tn = pn.set_function.parameters[0].type; } else if (dn is var_definition_node) { attr_node.field_names.Add(dn as var_definition_node); mem_tn = (dn as var_definition_node).type; } else { throw new CompilerInternalError("Bad general node type for attribute initializer"); } //SyntaxTree.assign tmp_ass = new SyntaxTree.assign(id,(e as SyntaxTree.bin_expr).right,SyntaxTree.Operators.Assignment); //tmp_ass.source_context = e.source_context; //basic_function_call tmp_bfc = convert_strong(tmp_ass) as basic_function_call; constant_node cn = convert_strong_to_constant_node((e as SyntaxTree.bin_expr).right, mem_tn); check_for_strong_constant(cn, get_location((e as SyntaxTree.bin_expr).right)); if (dn is property_node) attr_node.prop_initializers.Add(cn); else attr_node.field_initializers.Add(cn); } } } attr_node.qualifier = qualifier; ctn.attributes.AddElement(attr_node); } } } private void make_attributes_for_declaration(SyntaxTree.unit_module un, common_unit_node cun) { if (cun.attributes != null) { var ht = new HashSet(); foreach (SyntaxTree.simple_attribute_list sal in un.attributes.attributes) for (int j = 0; j < sal.attributes.Count; j++) { SyntaxTree.attribute attr = sal.attributes[j]; attribute_converted = true; type_node tn = convert_strong(attr.type); bool is_attr = false; type_node tmp = tn; while (tmp.base_type != null && !is_attr) { is_attr = tmp.base_type == SystemLibrary.SystemLibrary.attribute_type; tmp = tmp.base_type; } if (!is_attr) AddError(get_location(attr), "CLASS_{0}_NOT_ATTRIBUTE", tn.name); bool allowMultiple = false; AttributeTargets targets = get_usage_attrs(tn, out allowMultiple); if (ht.Contains(tn) && !allowMultiple) { AddError(get_location(attr), "DUPLICATE_ATTRIBUTE_{0}_APPLICATION", tn.name); } else ht.Add(tn); SemanticTree.attribute_qualifier_kind qualifier = SemanticTree.attribute_qualifier_kind.none_kind; if (attr.qualifier != null) if (j == 0) { if (string.Compare(attr.qualifier.name, "return", true) == 0) { if (context.top_function == null) AddError(get_location(attr), "ATTRIBUTE_APPLICABLE_ONLY_TO_METHOD"); if (context.top_function.return_value_type == null || context.top_function.return_value_type == SystemLibrary.SystemLibrary.void_type) AddError(get_location(attr), "EXPECTED_RETURN_VALUE_FOR_ATTRIBUTE"); throw new NotSupportedError(get_location(attr.qualifier)); // qualifier = SemanticTree.attribute_qualifier_kind.return_kind; } else throw new NotSupportedError(get_location(attr.qualifier)); } else AddError(get_location(attr.qualifier), "ATTRIBUTE_QUALIFIER_MUST_BE_FIRST"); check_for_usage_attribute(cun, targets, tn.name, get_location(attr), qualifier); attribute_converted = false; SyntaxTree.expression_list cnstr_args = new SyntaxTree.expression_list(); if (attr.arguments != null) { foreach (SyntaxTree.expression e in attr.arguments.expressions) { if (e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident) { break; } else { cnstr_args.expressions.Add(e); } } } expressions_list args = new expressions_list(); for (int i = 0; i < cnstr_args.expressions.Count; i++) { constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]); check_for_strong_constant(cn, get_location(cnstr_args.expressions[i])); args.AddElement(cn); } base_function_call bfc = create_constructor_call(tn, args, get_location(attr)); attribute_node attr_node = new attribute_node(bfc.simple_function_node, tn, get_location(un)); foreach (expression_node en in bfc.parameters) { constant_node cn = convert_strong_to_constant_node(en, en.type); check_for_strong_constant(cn, en.location); attr_node.args.Add(cn); } if (attr.arguments != null) { for (int i = cnstr_args.expressions.Count; i < attr.arguments.expressions.Count; i++) { SyntaxTree.expression e = attr.arguments.expressions[i]; if (!(e is SyntaxTree.bin_expr && (e as SyntaxTree.bin_expr).operation_type == SyntaxTree.Operators.Equal && (e as SyntaxTree.bin_expr).left is SyntaxTree.ident)) { AddError(get_location(e), "EXPECTED_ATTRIBUTE_INITIALIZER"); } else { SyntaxTree.ident id = (e as SyntaxTree.bin_expr).left as SyntaxTree.ident; List sil = tn.find(id.name); definition_node dn; if(sil != null) dn = context.check_name_node_type(id.name, sil?.FirstOrDefault(), get_location(id), general_node_type.property_node, general_node_type.variable_node); else dn = context.check_name_node_type(id.name, null, get_location(id), general_node_type.property_node, general_node_type.variable_node); type_node mem_tn = null; if (dn is property_node) { property_node pn = dn as property_node; attr_node.prop_names.Add(pn); if (pn.set_function == null) AddError(new ThisPropertyCanNotBeWrited(pn, get_location(id))); if (pn.set_function.parameters.Count != 1) AddError(get_location(id), "INDEX_PROPERTY_INITIALIZING_NOT_VALID"); mem_tn = pn.set_function.parameters[0].type; } else if (dn is var_definition_node) { attr_node.field_names.Add(dn as var_definition_node); mem_tn = (dn as var_definition_node).type; } else { throw new CompilerInternalError("Bad general node type for attribute initializer"); } constant_node cn = convert_strong_to_constant_node((e as SyntaxTree.bin_expr).right, mem_tn); check_for_strong_constant(cn, get_location((e as SyntaxTree.bin_expr).right)); if (dn is property_node) attr_node.prop_initializers.Add(cn); else attr_node.field_initializers.Add(cn); } } } attr_node.qualifier = qualifier; cun.attributes.AddElement(attr_node); if (cun.namespaces.Count > 0) cun.namespaces[0].attributes.AddElement(attr_node); } } } private void check_for_strong_constant(constant_node cn, location loc) { switch (cn.semantic_node_type) { case semantic_node_type.bool_const_node : case semantic_node_type.byte_const_node : case semantic_node_type.char_const_node : case semantic_node_type.sbyte_const_node : case semantic_node_type.short_const_node : case semantic_node_type.ushort_const_node : case semantic_node_type.int_const_node : case semantic_node_type.uint_const_node : case semantic_node_type.long_const_node : case semantic_node_type.ulong_const_node : case semantic_node_type.float_const_node : case semantic_node_type.double_const_node : case semantic_node_type.string_const_node : case semantic_node_type.enum_const : case semantic_node_type.null_const_node : case semantic_node_type.typeof_operator_as_constant: return; default: AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); break; } } internal void check_using_static_class(type_node tn, location loc) { if (tn.IsStatic) AddError(loc, "USING_STATIC_CLASS_NOT_VALID"); } internal void check_for_type_allowed(type_node tn, location loc) { if (tn == SystemLibrary.SystemLibrary.void_type) AddError(loc, "TYPE_{0}_NOT_VALID", tn.name); } private void check_cycle_inheritance(common_type_node cnode, type_node base_of_cnode) { List base_params = new List(); base_params.Add(cnode); common_type_node bt = base_of_cnode as common_type_node; while (bt != null && bt.is_generic_parameter) { if (base_params.Contains(bt)) { AddError(bt.loc, "TYPE_{0}_DERIVED_FROM_ITSELF", bt.name); } base_params.Add(bt); bt = bt.base_type as common_type_node; } } private void check_where_from_base_class(common_type_node ctn) { if (ctn.base_type != null && ctn.base_type.is_generic_type_instance && ctn.is_generic_type_definition) { common_type_node bctn = ctn.base_type.original_generic as common_type_node; compiled_type_node bctn2 = ctn.base_type.original_generic as compiled_type_node; Dictionary where_cache = new Dictionary(); foreach (SemanticTree.ICommonTypeNode t in ctn.generic_params) { int ind = ctn.base_type.instance_params.IndexOf(t as type_node); if (ind != -1) { if (bctn != null) where_cache.Add(bctn.generic_params[ind].name, t); else where_cache.Add(bctn2.generic_params[ind].name, t); } } if (bctn != null && bctn.generic_params != null) { foreach (SemanticTree.ICommonTypeNode t in bctn.generic_params) { SemanticTree.ICommonTypeNode thist = null; where_cache.TryGetValue(t.name, out thist); if (thist == null) continue; if (t.is_class || t.is_value_type || t.methods.Length > 0 || t.base_type != SystemLibrary.SystemLibrary.object_type) { //if (thist.is_class != t.is_class || thist.is_value_type != t.is_value_type /*&& !(t.is_value_type && thist.base_type.is_value_type)*/ // последнее непонятно // || thist.methods.Length != t.methods.Length || // это наличие конструктора // t.base_type != thist.base_type && !type_table.is_derived(t.base_type as type_node, thist.base_type as type_node)) if (t.is_class && !thist.is_class) AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); if (t.is_value_type && !thist.is_value_type) AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); if (t.methods.Length > thist.methods.Length) AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); var old_base = t.base_type as type_node; var new_base = thist.base_type as type_node; //ToDo: (тест where16) с1 и c1 это не всегда одно и тоже - только если T2 подставили вместо T1 old_base = old_base.original_generic; new_base = new_base.original_generic; if (old_base!=new_base && !type_table.is_derived(old_base, new_base)) AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); } } } else if (bctn2 != null && bctn2.generic_params != null) { foreach (compiled_type_node t in bctn2.generic_params) { SemanticTree.ICommonTypeNode thist = null; where_cache.TryGetValue(t.name, out thist); if (thist == null) continue; if (t.is_value_type || t.base_type != SystemLibrary.SystemLibrary.object_type) { if (thist.is_value_type != t.is_value_type && !(t.is_value_type && thist.base_type.is_value_type) || thist.base_type != t.base_type) AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); } } } } } private void visit_where_list(SyntaxTree.where_definition_list where_list) { if (where_list == null) { return; } context.BeginSkipGenericInstanceChecking(); List gparams = null; common_function_node cfn = context.top_function; if (cfn != null) { if (!cfn.is_generic_function) { AddError(get_location(where_list), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS"); return; } gparams = cfn.generic_params; } else { if (!context.converted_type.is_generic_type_definition) { AddError(get_location(where_list), "WHERE_SECTION_ALLOWED_ONLY_IN_GENERICS"); return; } gparams = context.converted_type.generic_params; } List used_types = new List(where_list.defs.Count); foreach (SyntaxTree.where_definition wd in where_list.defs) { int ind = 0; foreach (SyntaxTree.ident wd_id in wd.names.idents) { bool param_not_found = true; foreach (common_type_node param in gparams) { if (String.Equals(param.name, wd_id.name, StringComparison.InvariantCultureIgnoreCase)) { //Нашли нужный шаблонный параметр if (used_types.Contains(param)) { AddError(get_location(wd.names), "SPECIFICATORS_FOR_{0}_ALREADY_EXIST", wd_id.name); } add_generic_eliminations(param, wd.types.defs); used_types.Add(param); param_not_found = false; break; } } if (param_not_found) { AddError(new UndefinedNameReference(wd.names.idents[ind].name, get_location(wd.names.idents[ind]))); } ind++; } } foreach (common_type_node ctn in used_types) { if (ctn.base_type != null && ctn.base_type.is_generic_parameter && ctn.base_type.ImplementingInterfaces != null && ctn.base_type.ImplementingInterfaces.Count > 0) { foreach (type_node tn in ctn.base_type.ImplementingInterfaces) { type_table.AddInterface(ctn, tn, null); InitInterfaceScope(ctn); } } } context.EndSkipGenericInstanceChecking(); } //Добавляет ограничители для параметра шаблона private void add_generic_eliminations(common_type_node param, List specificators) { var used_interfs = new HashSet(); // System.Enum это класс, но его наследники - записи // Если указать "where T: Enum, record" - станет нельзя применять T=Enum, с ошибкой что Enum не запись // Но чтобы в секции where override метода можно было указать record без System.Enum // И чтобы можно было передавать конкретные энумы (которые записи), когда record не указан во where // Разрешил стрелять себе в ногу, указывая Enum вместе с record или class var base_is_enum = false; for (int i = 0; i < specificators.Count; ++i) { SyntaxTree.declaration_specificator ds = specificators[i] as SyntaxTree.declaration_specificator; if (ds != null) { switch (ds.specificator) { case SyntaxTree.DeclarationSpecificator.WhereDefClass: if (i == 0 || i == 1 && base_is_enum) { param.is_class = true; } else { AddError(get_location(specificators[i]), "CLASS_OR_RECORD_SPECIFICATOR_MUST_BE_FIRST"); } break; case SyntaxTree.DeclarationSpecificator.WhereDefValueType: if (i == 0 || i == 1 && base_is_enum) { param.internal_is_value = true; } else { AddError(get_location(specificators[i]), "CLASS_OR_RECORD_SPECIFICATOR_MUST_BE_FIRST"); } break; case SyntaxTree.DeclarationSpecificator.WhereDefConstructor: if (i == specificators.Count - 1) { generic_parameter_eliminations.add_default_ctor(param); } else { AddError(get_location(specificators[i]), "CONSTRUCTOR_SPECIFICATOR_MUST_BE_LAST"); } break; } } else { SyntaxTree.named_type_reference ntr = specificators[i] as SyntaxTree.named_type_reference; if (ntr == null) { AddError(get_location(specificators[i]), "SPECIFICATOR_MUST_BE_TYPE_REFERENCE"); } else { type_node spec_type = ret.visit(ntr); if (spec_type is ref_type_node || spec_type == SystemLibrary.SystemLibrary.void_type || spec_type == SystemLibrary.SystemLibrary.pointer_type) AddError(new SimpleSemanticError(get_location(specificators[i]), "INAVLID_TYPE")); //if (spec_type.is_class) // param.is_class = true; if (spec_type.IsInterface) { if (used_interfs.Contains(spec_type)) { AddError(get_location(specificators[i]), "INTERFACE_{0}_ALREADY_ADDED_TO_IMPLEMENTING_LIST", spec_type.PrintableName); } else { used_interfs.Add(spec_type); } //Добавляем интерфейс type_table.AddInterface(param, spec_type, get_location(specificators[i])); } else { if (i != 0) { AddError(get_location(specificators[i]), "PARENT_SPECIFICATOR_MUST_BE_FIRST"); } else { if (spec_type.is_value) AddError(get_location(specificators[i]), "RECORD_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR"); //Тип-предок if (spec_type == SystemLibrary.SystemLibrary.object_type) { AddError(get_location(specificators[i]), "OBJECT_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR"); } /*if (spec_type == SystemLibrary.SystemLibrary.enum_base_type) { AddError(get_location(specificators[i]), "ENUM_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR"); }*/ if (spec_type.IsStatic) AddError(get_location(specificators[i]), "STATIC_CLASS_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR"); check_cycle_inheritance(param, spec_type); param.SetBaseType(spec_type); if (spec_type.is_generic_parameter && spec_type.ImplementingInterfaces.Count > 0) { foreach (type_node tn in spec_type.ImplementingInterfaces) { used_interfs.Add(tn); type_table.AddInterface(param, tn, get_location(specificators[i])); } } base_is_enum = spec_type == SystemLibrary.SystemLibrary.enum_base_type; // Чтобы в секции where override метода можно было указать class вместо конкретного типа // Иначе CLR падает с TypeLoadException if (!base_is_enum) param.is_class = true; } } } } } InitInterfaceScope(param); } private bool is_direct_type_decl = false; private bool FunctionExsistsInSymbolInfo(function_node fn, List sil) { if (sil != null) { foreach (SymbolInfo si in sil) { if (si.sym_info is function_node) if (convertion_data_and_alghoritms.function_eq_params(fn, si.sym_info as function_node)) return true; } } return false; } internal bool body_exists; internal bool current_converted_method_not_in_class_defined = false; internal bool assign_is_converting = false; //lroman// public void visit_lambda_header(SyntaxTree.function_header _function_header, SyntaxTree.proc_block proc_body) { hard_node_test_and_visit(_function_header.name); if (context.converted_template_type != null) { return; } if (_function_header.template_args != null) { visit_generic_params(context.top_function, _function_header.template_args.idents); } if (_function_header.where_defs != null) visit_where_list(_function_header.where_defs); SymbolInfo si = context.create_special_names(); weak_node_test_and_visit(_function_header.parameters); type_node tn = null; bool unique = context.close_function_params(body_exists); if (!unique && _function_header.where_defs != null) // Видимо, ошибка только для глобальных forward продпрограмм AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION"); #region Вывод типа возвращаемого значения лямбды //lroman// if (LambdaHelper.IsLambdaName(_function_header.name.meth_name)) { if (_function_header.return_type != null && _function_header.return_type is SyntaxTree.lambda_inferred_type) LambdaHelper.InferResultType(_function_header, proc_body, this); } //\lroman// #endregion if (_function_header.return_type == null) { if (context.top_function.IsOperator) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); } if (_function_header.return_type != null) { check_parameter_on_complex_type(_function_header.return_type); tn = convert_strong(_function_header.return_type); //if (tn == SystemLibrary.SystemLibrary.void_type) // AddError(new VoidNotValid(get_location(_function_header.return_type))); check_for_type_allowed(tn,get_location(_function_header.return_type)); check_using_static_class(tn, get_location(_function_header.return_type)); } //(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения context.top_function.return_value_type = tn; assign_doc_info(context.top_function,_function_header); if (_function_header.attributes != null) { make_attributes_for_declaration(_function_header, context.top_function); } if (context.converted_type != null && has_dll_import_attribute(context.top_function)) AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD"); if (_function_header.name.class_name != null) with_class_name = true; if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes)) { SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static); pa.source_context = _function_header.source_context; _function_header.proc_attributes.proc_attributes.Add(pa); } weak_node_test_and_visit(_function_header.proc_attributes); if (context.top_function.IsOperator) { common_method_node cmmn = context.top_function as common_method_node; //if (cmmn == null) //{ // throw new OverloadOperatorMustBeStaticFunction(get_location(_function_header), context.top_function); //} if (cmmn != null && cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION"); } if (cmmn != null && (cmmn.name == StringConstants.implicit_operator_name || cmmn.name == StringConstants.explicit_operator_name)) if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type)) { AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName); } else if (convertion_data_and_alghoritms.eq_type_nodes(tn,cmmn.parameters[0].type)) { AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION"); } } with_class_name = false; if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator) { concrete_parameter_type cpt = concrete_parameter_type.cpt_none; SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value; if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type) { cpt = concrete_parameter_type.cpt_var; pt = PascalABCCompiler.SemanticTree.parameter_type.var; } if (!has_extensionmethod_attr(_function_header.proc_attributes.proc_attributes)) { common_parameter cp = new common_parameter(StringConstants.self_word, (context.top_function as common_namespace_function_node).ConnectedToType, pt, context.top_function, cpt, null, null); context.top_function.parameters.AddElementFirst(cp); context.top_function.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(cp)); } } CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header)); if (context.top_function.return_value_type == null) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si); //TODO: Разобрать подробнее. if (!body_exists) { if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node) || ((context.func_stack_size_is_one()) && (_is_interface_part))) { //context.leave_block(); } } body_exists = false; } //\lroman// public override void visit(SyntaxTree.procedure_definition _procedure_definition) { // SSM 20.07.13 если это - узел с коротким определением функции без типа возвращаемого значения, то вывести этот тип var fh = (_procedure_definition.proc_header as SyntaxTree.function_header); if (fh != null && fh.return_type == null) { var bl = _procedure_definition.proc_body as SyntaxTree.block; if (bl != null && bl.program_code != null) { if (bl.program_code.subnodes.Count != 1) AddError(get_location(fh.name), "ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED"); var ass = bl.program_code.subnodes[0] as SyntaxTree.assign; if (ass != null && ass.to is ident && (ass.to as ident).name.Equals(result_var_name, context.CurrentScope.StringComparison)) { if (ass.from is nil_const) AddError(get_location(ass.from), "CAN_NOT_DEDUCE_TYPE_{0}","nil"); // undefined_type означает, что где-то в будущем это надо исправить. Потому что и Result будет этого типа var typ = new semantic_type_node(new undefined_type("#Und",null));//SyntaxTreeBuilder.BuildSameType(ass.from); fh.return_type = typ; } else AddError(get_location(fh.name), "ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED"); } } //\ SSM var proc_name = _procedure_definition.proc_header != null && _procedure_definition.proc_header.name != null ? _procedure_definition.proc_header.name.meth_name : null; if (_procedure_definition.proc_header.attributes != null && context.converted_func_stack.Count >= 1) AddError(get_location(_procedure_definition.proc_header), "ATTRIBUTES_FOR_NESTED_FUNCTIONS_NOT_ALLOWED"); if (context.top_function != null && context.top_function.generic_params != null && !LambdaHelper.IsLambdaName(proc_name) && !(_procedure_definition.proc_header is SyntaxTree.constructor)) AddError(get_location(_procedure_definition.proc_header), "NESTED_FUNCTIONS_IN_GENERIC_FUNCTIONS_NOT_ALLOWED"); if (context.top_function != null && _procedure_definition.proc_header.template_args != null && !LambdaHelper.IsLambdaName(proc_name)) AddError(get_location(_procedure_definition.proc_header), "GENERIC_NESTED_FUNCTIONS_NOT_ALLOWED"); if (_procedure_definition.proc_header.name != null) current_converted_method_not_in_class_defined = _procedure_definition.proc_header.name.class_name != null; else { if (_procedure_definition.proc_header is SyntaxTree.constructor) { current_converted_method_not_in_class_defined = false; } } bool must_visit_body = true; if (SemanticRulesConstants.OrderIndependedMethodNames && !disable_order_independ && context.converting_block() == block_type.type_block && _procedure_definition.proc_body != null) { if (_procedure_definition.proc_header.name != null) { if (_procedure_definition.proc_header.name.class_name == null || _procedure_definition.Parent is class_members) // SSM #2173 01/07/20 - добавка после || - озн, что это явное расширение интерфейса { must_visit_body = false; context.is_order_independed_method_description = true; } } else { must_visit_body = false; context.is_order_independed_method_description = true; } } if (SemanticRulesConstants.OrderIndependedFunctionNames && !disable_order_independ && context.converting_block() == block_type.namespace_block && _procedure_definition.proc_body != null && _procedure_definition.proc_header.name.class_name == null) { if (_procedure_definition.proc_header.name != null) { if (_procedure_definition.proc_header.name.class_name == null) { must_visit_body = false; context.is_order_independed_method_description = true; } } else { must_visit_body = false; context.is_order_independed_method_description = true; } } //ssyy if (context.converting_block() == block_type.type_block && context.converted_type.IsInterface) { AddError(get_location(_procedure_definition), "INVALID_INTERFACE_MEMBER"); } //\ssyy //ssyy добавил if (context.converting_block() == block_type.function_block) { common_method_node cmnode = context.top_function as common_method_node; if (cmnode != null && cmnode.is_constructor) { //throw new NotSupportedError(get_location(_procedure_definition)); } } //\ssyy if (context.converted_type != null && context.converted_type.IsStatic && !_procedure_definition.proc_header.class_keyword && context.func_stack.Count == 0) AddError(get_location(_procedure_definition), "STATIC_CLASSES_CANNOT_NON_STATIC_MEMBERS"); if (_procedure_definition.proc_body == null) { body_exists = false; } else { body_exists = true; } //lroman// if (_procedure_definition != null && _procedure_definition.proc_header != null && _procedure_definition.proc_header is SyntaxTree.function_header && _procedure_definition.proc_header.name != null && _procedure_definition.proc_header.name.meth_name != null && LambdaHelper.IsLambdaName(_procedure_definition.proc_header.name.meth_name)) { //!!!!!!!!!!!!!!!!!! convertion_data_and_alghoritms.check_node_parser_error(_procedure_definition.proc_header); visit_lambda_header(_procedure_definition.proc_header as SyntaxTree.function_header, _procedure_definition.proc_body); } else { hard_node_test_and_visit(_procedure_definition.proc_header); } //\lroman// // Patterns if (context.top_function != null && context.top_function is common_namespace_function_node commonNode && commonNode.name.ToLower() == StringConstants.deconstruct_method_name) { var deconstructor = commonNode; if (!deconstructor.is_extension_method) { //AddWarning(); } else { if (deconstructor.is_generic_function && deconstructor.generic_parameters_count != GenericParameterIndices(GetSelfParameter(deconstructor).type).Count()) AddError(get_location(_procedure_definition), "DECONSTRUCTOR_GENERIC_PARAMETERS_SHOULD_BE_DEFINED_BY_SELF_PARAMETER"); ExecuteCommonChecks(deconstructor); } } if (context.top_function != null && context.top_function is common_method_node methodNode && methodNode.name.ToLower() == StringConstants.deconstruct_method_name) { var deconstructor = methodNode; if (deconstructor.is_generic_function) AddError(get_location(_procedure_definition), "INSTANCE_DECONSTRUCTORS_CANNOT_BE_GENERIC"); ExecuteCommonChecks(deconstructor); } // !Patterns //ssyy if (context.converted_template_type != null) { if ((context.converted_template_type.type_dec.type_def as SyntaxTree.class_definition).keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface) { AddError(new InterfaceFunctionWithBody(get_location(_procedure_definition))); } context.converted_template_type.external_methods.Add( new procedure_definition_info(context.converted_namespace, _procedure_definition)); context.converted_template_type = null; return; } //\ssyy if (context.top_function == null) { return; } // frninja 20/05/16 - ставим флаг is_yield_helper if (context.top_function is common_namespace_function_node) { (context.top_function as common_namespace_function_node).is_yield_helper = _procedure_definition.proc_header.is_yield_helper; } // end frninja if (context.converted_explicit_interface_type != null) (context.top_function as common_method_node).explicit_interface = context.converted_explicit_interface_type; if (has_dll_import_attribute(context.top_function)) { if (_procedure_definition.proc_body != null) if (!is_pinvoke(_procedure_definition.proc_body)) AddError(get_location(_procedure_definition.proc_body), "EXPECTED_EXTERNAL_STATEMENT"); must_visit_body = true; } if (contextChanger.IsActive()) { must_visit_body = true; } if (context.top_function.return_value_type is undefined_type) // значит, это короткое определение функции, и тело есть, и его надо обойти { must_visit_body = true; } // try { if (context.top_function.is_forward) { if (_procedure_definition.proc_body != null) { AddError(context.top_function.loc, "FORWARD_DEFINITION_WITH_FUNCTION_BODY"); } } else { if (must_visit_body) { common_method_node cmn = context.top_function as common_method_node; // frninja 3/06/16 - ставим флаг is_yield_helper для предописанных методов класса if (cmn != null) cmn.is_yield_helper = _procedure_definition.proc_header.is_yield_helper; // end frninja if (cmn != null && !cmn.IsStatic) { //if (cmn.find_only_in_namespace(StringConstants.self_word) == null) //self variable //добавляем self, обращение к ней заменяется на this_node type_node self_type = cmn.cont_type; if (cmn.cont_type.is_generic_type_definition) self_type = cmn.cont_type.get_instance(cmn.cont_type.generic_params.ConvertAll(o => (type_node)o)); local_variable lv = new local_variable(StringConstants.self_word, self_type, cmn, null); cmn.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(lv)); cmn.self_variable = lv; } if (_procedure_definition.proc_body != null) { hard_node_test_and_visit(_procedure_definition.proc_body); } // SSM 12/04/16 - short func definitions - calc return_value_type var ttt = context.top_function.return_value_type; if (ttt is undefined_type) { var cd = context.top_function.function_code as statements_list; if (cd == null || cd.statements == null || cd.statements.Count == 0) { AddError(context.top_function.loc, "IMPOSSIBLE!SHORT_FUNC_WITHOUT_BODY"); } // Проблема в том, что если в теле короткого определения функции - лямбда // и происходит захват переменной, то в тело выносится вызов конструктора сгенерированного класса // Поэтому result := ... - это не первый оператор, а последний!!! statement_node aa = cd.statements[cd.statements.Count-1]; var bfc = aa as basic_function_call; if (bfc != null) { var ttt1 = bfc.type; context.top_function.return_value_type = ttt1; context.top_function.var_definition_nodes_list[0].type = ttt1; } } add_clip_for_set(context.top_function); } else // if (!must_visit_body) { context.add_method_header(_procedure_definition, context.top_function); } } } //finally { if (_procedure_definition.proc_header.name.class_name != null) { // frninja 03/06/16 - убираем мусорные методы-хелперы yield if (context._ctn != null && (context.top_function is common_method_node) && (context.top_function as common_method_node).is_yield_helper) { context._ctn.methods.remove(context.top_function as common_method_node); } // end frninja context.leave_type_method(); } /*else { if (context._cmn != null && context._cmn.functions != null && (context.top_function is common_namespace_function_node) && (context.top_function as common_namespace_function_node).is_yield_helper && context.top_function.name.ToLower().StartsWith(" p.idents.idents).Where(id => id.name.ToLower() == "self"); if (q != null && q.Count() > 0) { var sid = q.First(); AddError(get_location(sid), "SELF_NOT_ALLOWED_IN_METHOD_PARAMS"); } } if (_function_header.template_args != null) { visit_generic_params(context.top_function, _function_header.template_args.idents); } if (_function_header.where_defs != null) { visit_where_list(_function_header.where_defs); } SymbolInfo si = context.create_special_names(); weak_node_test_and_visit(_function_header.parameters); type_node tn = null; if (_function_header.return_type == null) { if (context.top_function.IsOperator) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); } if (_function_header.return_type != null) { check_parameter_on_complex_type(_function_header.return_type); tn = convert_strong(_function_header.return_type); check_for_type_allowed(tn,get_location(_function_header.return_type)); check_using_static_class(tn, get_location(_function_header.return_type)); if (_function_header.return_type is function_header || _function_header.return_type is procedure_header) check_delegate_on_generic_parameters(tn as common_type_node, get_location(_function_header.return_type)); } //(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения context.top_function.return_value_type = tn; assign_doc_info(context.top_function,_function_header); if (_function_header.attributes != null) { make_attributes_for_declaration(_function_header, context.top_function); } //if (context.converted_type != null && has_dll_import_attribute(context.top_function)) // AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD"); if (_function_header.name.class_name != null) with_class_name = true; if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes)) { SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static); pa.source_context = _function_header.source_context; _function_header.proc_attributes.proc_attributes.Add(pa); } weak_node_test_and_visit(_function_header.proc_attributes); if (context.top_function.IsOperator) { if (context.top_function is common_method_node) { common_method_node cmmn = context.top_function as common_method_node; if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION"); } if ((cmmn.name == StringConstants.implicit_operator_name || cmmn.name == StringConstants.explicit_operator_name)) { if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type)) { if (_function_header.return_type.source_context == null) AddError(get_location(_function_header), "RETURN_VALUE_IMPLICIT_EXPLICIT_EXPECTED"); AddError(get_location(_function_header), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName); } else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.parameters[0].type)) { AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION"); } } else { int expected_params = 2; if (cmmn.name == "not") expected_params = 1; if ((cmmn.name == "+" || cmmn.name == "-")) { if (cmmn.parameters.Count != 2 && cmmn.parameters.Count != 1) AddError(new SimpleSemanticError(cmmn.loc, "OPERATORS_SHOULD_HAVE_1_OR_2_PARAMETERS")); } else if (cmmn.parameters.Count != expected_params) { if (expected_params==1) AddError(new SimpleSemanticError(cmmn.loc, "OPERATOR_SHOULD_HAVE_1_PARAMETER")); else AddError(new SimpleSemanticError(cmmn.loc, "OPERATOR_SHOULD_HAVE_2_PARAMETERS")); } if (cmmn.cont_type.IsDelegate && (cmmn.name == "+" || cmmn.name == "-" || cmmn.name == "+=" || cmmn.name == "-=")) AddError(cmmn.loc, "CANNOT_EXTEND_STANDARD_OPERATORS_FOR_DELEGATE"); bool has_types = false; foreach (parameter p in cmmn.parameters) { type_node ptn = p.type; if (ptn.is_generic_type_instance) ptn = ptn.original_generic; if (ptn == cmmn.cont_type) has_types = true; } if (!has_types) AddError(new SimpleSemanticError(cmmn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cmmn.cont_type.name)); } } else if (context.top_function is common_namespace_function_node) { common_namespace_function_node cnfn = context.top_function as common_namespace_function_node; if ((cnfn.name == StringConstants.implicit_operator_name || cnfn.name == StringConstants.explicit_operator_name)) { if (cnfn.parameters.Count != 1) AddError(new SimpleSemanticError(cnfn.loc,"EXTENSION_METHODS_MUST_HAVE_LEAST_ONE_PARAMETER")); if (cnfn.ConnectedToType == null) AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_BE_EXTENSION_METHOD")); if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cnfn.ConnectedToType) && !convertion_data_and_alghoritms.eq_type_nodes(cnfn.ConnectedToType as type_node, cnfn.parameters[0].type)) { AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cnfn.ConnectedToType as type_node).PrintableName); } else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cnfn.parameters[0].type)) { AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION"); } } else { int expected_params = 2; if (cnfn.name == "not") expected_params = 1; if (cnfn.name == "+" || cnfn.name == "-") { if (cnfn.parameters.Count != 2 && cnfn.parameters.Count != 1) AddError(new SimpleSemanticError(cnfn.loc, "OPERATORS_SHOULD_HAVE_1_OR_2_PARAMETERS")); } else if (cnfn.parameters.Count != expected_params) { if (expected_params == 1) AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_HAVE_1_PARAMETER")); else AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_HAVE_2_PARAMETERS")); } bool has_types = false; foreach (parameter p in cnfn.parameters) { type_node ptn = p.type; if (ptn.is_generic_type_instance) ptn = ptn.original_generic; if (cnfn.ConnectedToType != null && (ptn == cnfn.ConnectedToType || ptn == cnfn.ConnectedToType.original_generic)) has_types = true; } if (cnfn.ConnectedToType == null) AddError(new SimpleSemanticError(cnfn.loc, "OPERATOR_SHOULD_BE_EXTENSION_METHOD")); if (!has_types) AddError(new SimpleSemanticError(cnfn.loc, "LEAST_ONE_PARAMETER_TYPE_SHOULD_EQ_DECLARING_TYPE_{0}",cnfn.ConnectedToType.name)); if (cnfn.ConnectedToType.IsDelegate && (cnfn.name == "+" || cnfn.name == "-" || cnfn.name == "+=" || cnfn.name == "-=")) AddError(cnfn.loc, "CANNOT_EXTEND_STANDARD_OPERATORS_FOR_DELEGATE"); } } } with_class_name = false; if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator) { concrete_parameter_type cpt = concrete_parameter_type.cpt_none; SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value; if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type) { cpt = concrete_parameter_type.cpt_var; pt = PascalABCCompiler.SemanticTree.parameter_type.var; } type_node cur_tn = (context.top_function as common_namespace_function_node).ConnectedToType; type_node self_type = cur_tn; if (context.top_function.generic_params != null && self_type.is_generic_type_definition) { self_type = self_type.get_instance(context.top_function.get_generic_params_list()); } if (!has_extensionmethod_attr(_function_header.proc_attributes.proc_attributes)) { common_parameter cp = new common_parameter(StringConstants.self_word, self_type, pt, context.top_function, cpt, null, null); context.top_function.parameters.AddElementFirst(cp); context.top_function.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(cp)); } } CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header)); common_type_node common_converted_type_tmp = context.converted_type; compiled_type_node compiled_converted_type_tmp = context.converted_compiled_type; common_namespace_function_node cnfn2 = context.top_function as common_namespace_function_node; if (cnfn2 != null && cnfn2.ConnectedToType != null) { if (cnfn2.ConnectedToType is compiled_type_node) context.converted_compiled_type = cnfn2.ConnectedToType as compiled_type_node; else if (cnfn2.ConnectedToType is common_type_node) context.converted_type = cnfn2.ConnectedToType as common_type_node; } bool unique = context.close_function_params(body_exists); context.converted_type = common_converted_type_tmp; context.converted_compiled_type = compiled_converted_type_tmp; if (context.top_function.return_value_type == null) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); if (_function_header.where_defs != null) { if (!unique && false) { AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION"); } } if (context.converted_type != null && context.converted_type.IsInterface) { if (body_exists) { AddError(new InterfaceFunctionWithBody(get_location(_function_header))); } common_method_node cmnode = context.top_function as common_method_node; context.set_virtual_abstract(cmnode); } if (context.converted_type != null) { common_method_node cmnode = context.top_function as common_method_node; if (cmnode != null && cmnode.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract && body_exists) { AddError(new AbstractMethodWithBody(get_location(_function_header))); } } convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si); if (!body_exists) { if (_function_header.name.class_name != null && context.converted_explicit_interface_type != null) { AddError(get_location(_function_header), "EXPLICIT_IMPLEMENTATION_EXPECTED"); } if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node) || ((context.func_stack_size_is_one()) && (_is_interface_part))) { context.leave_block(); } } body_exists = false; } bool has_static_attr(List attrs) { foreach (SyntaxTree.procedure_attribute attr in attrs) { if (attr.attribute_type == PascalABCCompiler.SyntaxTree.proc_attribute.attr_static) { return true; } } return false; } bool has_extensionmethod_attr(List attrs) { foreach (SyntaxTree.procedure_attribute attr in attrs) { if (attr.attribute_type == PascalABCCompiler.SyntaxTree.proc_attribute.attr_extension) { return true; } } return false; } private bool has_var_char_parameters(common_function_node fn) { for (int i=0; i p.idents.idents).Where(id => id.name.ToLower() == "self"); if (q != null && q.Count() > 0) { var sid = q.First(); AddError(get_location(sid), "SELF_NOT_ALLOWED_IN_METHOD_PARAMS"); } } current_function_header = null; if (context.converted_template_type != null) { return; } if (_procedure_header.template_args != null) { visit_generic_params(context.top_function, _procedure_header.template_args.idents); } if (_procedure_header.where_defs != null) { visit_where_list(_procedure_header.where_defs); } weak_node_test_and_visit(_procedure_header.parameters); if (_procedure_header.name.class_name != null) with_class_name = true; if (_procedure_header.class_keyword && !has_static_attr(_procedure_header.proc_attributes.proc_attributes)) { SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static); pa.source_context = _procedure_header.source_context; _procedure_header.proc_attributes.proc_attributes.Insert(0, pa); } weak_node_test_and_visit(_procedure_header.proc_attributes); with_class_name = false; CheckOverrideOrReintroduceExpectedWarning(get_location(_procedure_header)); if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator) { concrete_parameter_type cpt = concrete_parameter_type.cpt_none; SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value; if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type) { cpt = concrete_parameter_type.cpt_var; pt = PascalABCCompiler.SemanticTree.parameter_type.var; } type_node cur_tn = (context.top_function as common_namespace_function_node).ConnectedToType; type_node self_type = cur_tn; if (context.top_function.generic_params != null && self_type.is_generic_type_definition) { self_type = self_type.get_instance(context.top_function.get_generic_params_list()); } if (!has_extensionmethod_attr(_procedure_header.proc_attributes.proc_attributes)) { common_parameter cp = new common_parameter(StringConstants.self_word, self_type, pt, context.top_function, cpt, null, null); context.top_function.parameters.AddElementFirst(cp); context.top_function.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(cp)); } } if (_procedure_header is SyntaxTree.constructor) { common_method_node cmnode = context.top_function as common_method_node; if (cmnode != null) { cmnode.is_constructor = true; cmnode.return_value_type = context.converted_type; } else if (context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null) AddError(get_location(_procedure_header), "EXTENSION_CONSTRUCTOR_NOT_ALLOWED"); else if (context.converted_compiled_type != null) AddError(get_location(_procedure_header), "EXTENSION_CONSTRUCTOR_NOT_ALLOWED"); } if (context.top_function.IsOperator) { if (context.top_function is common_method_node) { common_method_node cmmn = context.top_function as common_method_node; if (cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_procedure_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION"); } } } common_type_node common_converted_type_tmp = context.converted_type; compiled_type_node compiled_converted_type_tmp = context.converted_compiled_type; common_namespace_function_node cnfn2 = context.top_function as common_namespace_function_node; if (cnfn2 != null && cnfn2.ConnectedToType != null) { if (cnfn2.ConnectedToType is compiled_type_node) context.converted_compiled_type = cnfn2.ConnectedToType as compiled_type_node; else if (cnfn2.ConnectedToType is common_type_node) context.converted_type = cnfn2.ConnectedToType as common_type_node; } bool unique = context.close_function_params(body_exists); context.converted_compiled_type = compiled_converted_type_tmp; context.converted_type = common_converted_type_tmp; if (context.converted_type != null && context.converted_type.IsInterface) { if (body_exists) { AddError(new InterfaceFunctionWithBody(get_location(_procedure_header))); } common_method_node cmnode = context.top_function as common_method_node; context.set_virtual_abstract(cmnode); } if (context.converted_type != null) { common_method_node cmnode = context.top_function as common_method_node; if (cmnode != null && cmnode.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract && body_exists) { AddError(new AbstractMethodWithBody(get_location(_procedure_header))); } } if (_procedure_header.where_defs != null) { if (!unique && false) { AddError(get_location(_procedure_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION"); } } assign_doc_info(context.top_function,_procedure_header); if (_procedure_header.attributes != null) { make_attributes_for_declaration(_procedure_header, context.top_function); } if (context.converted_type != null && has_dll_import_attribute(context.top_function)) AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD"); if (!body_exists) { if (_procedure_header.name.class_name != null && context.converted_explicit_interface_type != null) { AddError(get_location(_procedure_header), "EXPLICIT_IMPLEMENTATION_EXPECTED"); } if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node) || ((context.func_stack_size_is_one()) && (_is_interface_part))) { context.leave_block(); if (_procedure_header.name.class_name != null && context.converted_compiled_type != null) context.converted_compiled_type = null; } } body_exists = false; } public override void visit(SyntaxTree.procedure_header _procedure_header) { visit_procedure_header(_procedure_header); } public override void visit(SyntaxTree.procedure_attributes_list _procedure_attributes_list) { bool is_override = false; bool is_virtual = false; bool is_abstract = false; bool is_reintroduce = false; string override_proc_attr=null; string virtual_proc_attr=null; string abstract_proc_attr = null; string reintroduce_proc_attr = null; for (int i = 0; i < _procedure_attributes_list.proc_attributes.Count; i++) { switch (_procedure_attributes_list.proc_attributes[i].attribute_type) { case SyntaxTree.proc_attribute.attr_abstract: { is_abstract = true; abstract_proc_attr = _procedure_attributes_list.proc_attributes[i].name; } break; case SyntaxTree.proc_attribute.attr_override: { is_override = true; override_proc_attr = _procedure_attributes_list.proc_attributes[i].name; } break; case SyntaxTree.proc_attribute.attr_virtual: { is_virtual = true; virtual_proc_attr = _procedure_attributes_list.proc_attributes[i].name; } break; case SyntaxTree.proc_attribute.attr_reintroduce: { is_reintroduce = true; reintroduce_proc_attr = _procedure_attributes_list.proc_attributes[i].name; } break; } } context.top_function.is_overload = true; // SSM 12/08/15 context.last_created_function.symbol_kind = symbol_kind.sk_overload_function; bool is_forward = false; for (int i = 0; i < _procedure_attributes_list.proc_attributes.Count; i++) { convertion_data_and_alghoritms.check_node_parser_error(_procedure_attributes_list.proc_attributes[i]); for (int j = 0; j < i; j++) { if (_procedure_attributes_list.proc_attributes[i].attribute_type == _procedure_attributes_list.proc_attributes[j].attribute_type) { AddError(new DuplicateAttributeDefinition(get_location(_procedure_attributes_list.proc_attributes[j]), get_location(_procedure_attributes_list.proc_attributes[i]))); } } switch (_procedure_attributes_list.proc_attributes[i].attribute_type) { case SyntaxTree.proc_attribute.attr_overload:// ничего не делать - это и так есть { break; } case SyntaxTree.proc_attribute.attr_forward: { if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); //(ssyy) В интерфейсах аттрибуты недопустимы if (context.converted_type != null && context.converted_type.IsInterface) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER"); } common_namespace_function_node top_function = context.top_function as common_namespace_function_node; if (top_function != null && top_function.ConnectedToType != null) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "FORWARD_EXTENSION_METHODS_NOT_ALLOWED"); } is_forward = true; break; } case SyntaxTree.proc_attribute.attr_virtual: { if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); //(ssyy) В интерфейсах аттрибуты недопустимы if (context.converted_type != null && context.converted_type.IsInterface) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER"); } //(ssyy) В записях нет виртуальных функций if (context.converted_type != null && context.converted_type.is_value) { AddError(new VirtualMethodInRecord( get_location(_procedure_attributes_list.proc_attributes[i]))); } common_function_node ccfn = context.top_function; if (ccfn.semantic_node_type != semantic_node_type.common_method_node) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name); } common_method_node cmn = ccfn as common_method_node; if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD"); } if (is_override) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "USING_MODIFIERS{0}_{1}_TOGETHER_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name,override_proc_attr); } if (!context.converted_type.IsAbstract || true) { is_virtual = true; virtual_proc_attr = _procedure_attributes_list.proc_attributes[i].name; if (!is_abstract) context.set_virtual(cmn); } break; } case SyntaxTree.proc_attribute.attr_override: case SyntaxTree.proc_attribute.attr_reintroduce: { if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); //(ssyy) В интерфейсах аттрибуты недопустимы if (context.converted_type != null && context.converted_type.IsInterface) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER"); } common_function_node ccfn = context.top_function; if (ccfn.return_value_type is undefined_type) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "OVERRIDE_NOT_ALLOWED_FOR_SHORT_FUNCTIONS"); } if (ccfn.semantic_node_type != semantic_node_type.common_method_node) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name); } common_method_node cmn = ccfn as common_method_node; if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD"); } if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_reintroduce) { cmn.IsReintroduce = true; if (is_abstract) cmn.newslot_awaited = true; break; } if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_override && is_virtual) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]),"USING_MODIFIERS{0}_{1}_TOGETHER_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name,virtual_proc_attr); } if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_override && is_reintroduce) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "USING_MODIFIERS{0}_{1}_TOGETHER_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name, reintroduce_proc_attr); } if (_procedure_attributes_list.proc_attributes[i].attribute_type == SyntaxTree.proc_attribute.attr_override) { is_override = true; override_proc_attr = _procedure_attributes_list.proc_attributes[i].name; } context.set_override(cmn); if (is_abstract) { cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract; } if (is_override && (_procedure_attributes_list.Parent as procedure_header)?.where_defs is where_definition_list where_node) { var where_loc = get_location(where_node); var gen_pars1 = cmn.overrided_method.get_generic_params_list(); var gen_pars2 = cmn.get_generic_params_list(); System.Diagnostics.Debug.Assert(gen_pars1.Count == gen_pars2.Count); for (int par_i = 0; par_i < gen_pars1.Count; par_i++) { var gen_par1 = gen_pars1[par_i] as common_type_node; var gen_par2 = gen_pars2[par_i] as common_type_node; if (gen_par2.base_type != SystemLibrary.SystemLibrary.object_type && !convertion_data_and_alghoritms.eq_type_nodes(gen_par2.base_type, gen_par1.base_type, true)) if (gen_par1.base_type == SystemLibrary.SystemLibrary.object_type) AddError(where_loc, "OVERRIDE_WHERE_UNEXPECTED_TYPE", gen_par2.name, gen_par2.base_type.PrintableName); else AddError(where_loc, "OVERRIDE_WHERE_TYPE_MUST_BE_SAME", gen_par2.name, gen_par1.base_type.PrintableName); foreach (type_node intr2 in gen_par2.ImplementingInterfaces) if (!gen_par1.ImplementingInterfaces.Any(intr1=> convertion_data_and_alghoritms.eq_type_nodes((type_node)intr1, intr2, true))) AddError(where_loc, "OVERRIDE_WHERE_UNEXPECTED_INTERFACE", gen_par2.name, intr2.PrintableName); if (gen_par2.has_explicit_default_constructor && !gen_par1.has_explicit_default_constructor) AddError(where_loc, "OVERRIDE_WHERE_UNEXPECTED_X", gen_par2.name, "constructor"); if (gen_par2.is_class && !gen_par1.is_class) AddError(where_loc, "OVERRIDE_WHERE_UNEXPECTED_X", gen_par2.name, "class"); if (gen_par2.is_value && !gen_par1.is_value) AddError(where_loc, "OVERRIDE_WHERE_UNEXPECTED_X", gen_par2.name, "record"); } } if (cmn.field_access_level < cmn.overrided_method.field_access_level) AddError(cmn.loc, "CAN_NOT_BE_DOWN_ACCESS_LEVEL_FOR_METH"); break; } case SyntaxTree.proc_attribute.attr_static: { if (with_class_name) { if (context.top_function != null) { context.top_function.polymorphic_state = PascalABCCompiler.SemanticTree.polymorphic_state.ps_static; break; } AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); } //(ssyy) В интерфейсах аттрибуты недопустимы if (context.converted_type != null && context.converted_type.IsInterface) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER"); } common_function_node ccfn = context.top_function; if (ccfn.semantic_node_type != semantic_node_type.common_method_node) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "STATIC_KEYWORD_ALLOWED_ONLY_WITH_METHOD"); } common_method_node cmn = ccfn as common_method_node; if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CAN_NOT_BE_VIRTUAL_STATIC_METHOD"); } if (cmn.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CANNOT_BE_ABSTRACT_STATIC_METHOD"); } cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_static; break; } case SyntaxTree.proc_attribute.attr_abstract: { if (with_class_name) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); if (context.converted_type != null && context.converted_type.IsInterface) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ATTRIBUTES_IN_INTERFACE_MEMBER"); } common_function_node ccfn = context.top_function; common_method_node cmn = ccfn as common_method_node; if (ccfn.semantic_node_type != semantic_node_type.common_method_node) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "{0}_KEYWORD_ALLOWED_ONLY_WITH_METHOD", _procedure_attributes_list.proc_attributes[i].name); } if (context.converted_type != null && context.converted_type.is_value) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ABSTRACT_METHOD_IN_RECORD"); } if (ccfn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "CANNOT_BE_ABSTRACT_STATIC_METHOD"); } if (cmn.is_constructor) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "DIRECTIVE_{0}_NOT_ALLOWED", _procedure_attributes_list.proc_attributes[i].name); cmn.polymorphic_state = SemanticTree.polymorphic_state.ps_virtual_abstract; if (context.converted_type.IsSealed) AddError(get_location(_procedure_attributes_list.proc_attributes[i]), "ABSTRACT_METHOD_IN_SEALED_CLASS"); context.converted_type.SetIsAbstract(true, null); // Причина null, потому что предыдущая строчка уже даёт ошибку раньше, чем та - для которой понадобится эта причина if (cmn.IsReintroduce) cmn.newslot_awaited = true; break; } case proc_attribute.attr_extension: { if (is_forward) AddError(get_location(_procedure_attributes_list), "EXTENSIONMETHOD_KEYWORD_NOT_ALLOWED"); if (context.converted_compiled_type != null) AddError(get_location(_procedure_attributes_list), "EXTENSIONMETHOD_KEYWORD_NOT_ALLOWED"); if (in_interface_part) AddError(get_location(_procedure_attributes_list), "EXTENSION_METHODS_IN_INTERFACE_PART_NOT_ALLOWED"); if (!(context.top_function is common_namespace_function_node)) AddError(get_location(_procedure_attributes_list), "EXTENSION_ATTRIBUTE_ONLY_FOR_NAMESPACE_FUNCTIONS_ALLOWED"); if (context.top_function.parameters.Count == 0) AddError(context.top_function.loc, "EXTENSION_METHODS_MUST_HAVE_LEAST_ONE_PARAMETER"); if (!context.top_function.IsOperator && context.top_function.parameters[0].parameter_type != SemanticTree.parameter_type.value && !(context.top_function.parameters[0].type is compiled_type_node ctn && ctn.compiled_type == typeof(string))) AddError(context.top_function.loc, "FIRST_PARAMETER_SHOULDBE_ONLY_VALUE_PARAMETER"); if (!context.top_function.IsOperator && context.top_function.parameters[0].name.ToLower() != StringConstants.self_word) AddError(context.top_function.loc,"FIRST_PARAMETER_MUST_HAVE_NAME_SELF"); common_namespace_function_node top_function = context.top_function as common_namespace_function_node; top_function.ConnectedToType = context.top_function.parameters[0].type; if (top_function.ConnectedToType.Scope == null && top_function.ConnectedToType is compiled_type_node) { (top_function.ConnectedToType as compiled_type_node).init_scope(); } if (top_function.ConnectedToType.Scope == null) AddError(context.top_function.loc, "EXTENSION_METHODS_FOR_CONSTRUCTED_TYPES_NOT_ALLOWED"); SymbolInfo si = new SymbolInfo(context.top_function); si.symbol_kind = symbol_kind.sk_overload_function; top_function.ConnectedToType.Scope.AddSymbol(top_function.name, si); if (top_function.ConnectedToType.type_special_kind == SemanticTree.type_special_kind.array_kind /*&& top_function.ConnectedToType.element_type.is_generic_parameter*/) top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); else if (top_function.ConnectedToType.is_generic_parameter) top_function.ConnectedToType.base_type.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); else if (top_function.ConnectedToType is compiled_type_node && top_function.ConnectedToType.is_generic_type_instance && top_function.ConnectedToType.original_generic.Scope != null) top_function.ConnectedToType.original_generic.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); else if (top_function.ConnectedToType is compiled_generic_instance_type_node && top_function.ConnectedToType.original_generic.Scope != null) top_function.ConnectedToType.original_generic.Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); else if (top_function.ConnectedToType.IsDelegate && top_function.ConnectedToType.base_type.IsDelegate) compiled_type_node.get_type_node(typeof(Delegate)).Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); else if (top_function.ConnectedToType.type_special_kind == SemanticTree.type_special_kind.typed_file && top_function.ConnectedToType.element_type.is_generic_parameter && SystemLibrary.SystemLibInitializer.TypedFileType.sym_info != null) (SystemLibrary.SystemLibInitializer.TypedFileType.sym_info as type_node).Scope.AddSymbol(top_function.name, new SymbolInfo(context.top_function)); if (top_function.ConnectedToType.IsDelegate && context.top_function.IsOperator && (context.top_function.name == "+" || context.top_function.name == "-" || context.top_function.name == "+=" || context.top_function.name == "-=")) AddError(get_location(_procedure_attributes_list), "CANNOT_EXTEND_STANDARD_OPERATORS_FOR_DELEGATE"); if (context.top_function.IsOperator && (context.top_function.name == StringConstants.implicit_operator_name || context.top_function.name == StringConstants.explicit_operator_name) && context.top_function.parameters.Count == 1 && context.top_function.return_value_type != null) { if (!(context.top_function.return_value_type is compiled_type_node) && !(context.top_function.return_value_type is compiled_generic_instance_type_node) || !(context.top_function.parameters[0].type is compiled_type_node) && !(context.top_function.parameters[0].type is compiled_generic_instance_type_node)) ;//AddError(get_location(_procedure_attributes_list), "IMPLICIT_EXPLICIT_OPERATOR_EXTENSION_ONLY_FOR_COMPILED_CLASSES_ALLOWED"); } break; } default: { throw new NotSupportedError(get_location(_procedure_attributes_list.proc_attributes[i])); } } } } private bool first_param=false; public override void visit(SyntaxTree.formal_parameters _formal_parametres) { bool default_value_met = false; bool params_met = false; first_param = true; foreach (SyntaxTree.typed_parameters tp in _formal_parametres.params_list) { if (params_met) { AddError(get_location(tp), "ONLY_LAST_PARAMETER_CAN_BE_PARAMS"); } if (tp.param_kind == PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr) { params_met = true; if (default_value_met) { AddError(get_location(tp), "FUNCTION_WITH_PARAMS_PARAMETER_CAN_NOT_HAVE_DEFAULT_PARAMETERS"); } } hard_node_test_and_visit(tp); first_param = false; if ((default_value_met) && (tp.inital_value == null)) { AddError(new NeedDefaultValueForParameter(get_location(tp))); } if (tp.inital_value != null) { default_value_met = true; } } first_param = false; common_method_node cnode = context.top_function as common_method_node; parameter_list pars = context.top_function.parameters; if (cnode != null && cnode.IsOperator) { if (cnode.name != StringConstants.implicit_operator_name && cnode.name != StringConstants.explicit_operator_name) { bool all_types_mismatch = true; foreach (parameter par in pars) { //if (par.type == cnode.comperehensive_type) if (convertion_data_and_alghoritms.eq_type_nodes(par.type, cnode.comperehensive_type as type_node)) { all_types_mismatch = false; break; } } if (all_types_mismatch) { AddError(cnode.loc, "TYPE_OF_ONE_OR_MORE_OPERATOR_PARAMETERS_MUST_BE_{0}", ((type_node)(cnode.comperehensive_type)).PrintableName); } } if (pars.Count > 0 && pars[pars.Count - 1].is_params) { AddError(convertion_data_and_alghoritms.get_location(pars[pars.Count - 1]), "PARAMS_IN_OPERATOR"); } } if (context.top_function.IsOperator) { int pcount = name_reflector.get_params_count(context.top_function.name); if (pcount != pars.Count) { if (context.top_function.name != StringConstants.minus_name && context.top_function.name != StringConstants.plus_name) AddError(context.top_function.loc, "OPERATOR_{0}_PARAMETERS_COUNT_MUST_EQUAL_{1}", context.top_function.name, pcount); else if (pars.Count != 1 && pars.Count != 2) AddError(context.top_function.loc, "OPERATOR_{0}_PARAMETERS_COUNT_MUST_EQUAL_{1}", context.top_function.name, pcount); } } } private void check_array_on_complex_type(SyntaxTree.array_type type) { SyntaxTree.array_type arr = type as SyntaxTree.array_type; if (arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null) AddError(get_location(type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); if (arr.elements_type is SyntaxTree.array_type) check_array_on_complex_type(arr.elements_type as SyntaxTree.array_type); else if (arr.elements_type is SyntaxTree.class_definition) AddError(get_location(arr.elements_type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); else if (arr.elements_type is SyntaxTree.set_type_definition) check_set_on_complex_type(arr.elements_type as set_type_definition); else if (arr.elements_type is SyntaxTree.file_type) check_file_on_complex_type(arr.elements_type as file_type); } private void check_set_on_complex_type(SyntaxTree.set_type_definition type) { SyntaxTree.set_type_definition set = type as SyntaxTree.set_type_definition; if (set.of_type is SyntaxTree.array_type) check_array_on_complex_type(set.of_type as SyntaxTree.array_type); else if (set.of_type is SyntaxTree.class_definition) AddError(get_location(set.of_type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); else if (set.of_type is SyntaxTree.file_type) check_file_on_complex_type(set.of_type as file_type); else if (set.of_type is SyntaxTree.set_type_definition) check_set_on_complex_type(set.of_type as set_type_definition); } private void check_file_on_complex_type(SyntaxTree.file_type type) { SyntaxTree.file_type file = type as SyntaxTree.file_type; if (file.file_of_type is SyntaxTree.array_type) check_array_on_complex_type(file.file_of_type as SyntaxTree.array_type); else if (file.file_of_type is SyntaxTree.class_definition) AddError(get_location(file.file_of_type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); else if (file.file_of_type is SyntaxTree.file_type) check_file_on_complex_type(file.file_of_type as file_type); else if (file.file_of_type is SyntaxTree.set_type_definition) check_set_on_complex_type(file.file_of_type as set_type_definition); } public void check_parameter_on_complex_type(SyntaxTree.type_definition type) { SyntaxTree.array_type arr = type as SyntaxTree.array_type; if (type is SyntaxTree.class_definition || /*type is SyntaxTree.enum_type_definition ||*/ (arr != null && arr.indexers != null && arr.indexers.indexers.Count > 0 && arr.indexers.indexers[0] != null)) { AddError(get_location(type), "STRUCT_TYPE_DEFINITION_IN_FORMAL_PARAM"); } if (arr != null) { check_array_on_complex_type(arr); return; } if (type is SyntaxTree.set_type_definition) { check_set_on_complex_type(type as SyntaxTree.set_type_definition); return; } else if (type is SyntaxTree.file_type) { check_file_on_complex_type(type as SyntaxTree.file_type); return; } if (context.top_function is common_method_node && (context.converted_type.IsInterface || context.top_function.polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract ) && (type is function_header || type is procedure_header)) AddError(get_location(type), "ANONYMOUS_DELEGATE_IN_INTERFACE_NOT_ALLOWED"); } public override void visit(SyntaxTree.typed_parameters _typed_parametres) { SemanticTree.parameter_type par_type = SemanticTree.parameter_type.value; concrete_parameter_type cpt = concrete_parameter_type.cpt_none; bool is_params = false; switch (_typed_parametres.param_kind) { case SyntaxTree.parametr_kind.const_parametr: { par_type = SemanticTree.parameter_type.value; cpt = concrete_parameter_type.cpt_const; break; } case SyntaxTree.parametr_kind.none: { par_type = SemanticTree.parameter_type.value; cpt = concrete_parameter_type.cpt_none; break; } case SyntaxTree.parametr_kind.out_parametr: { par_type = SemanticTree.parameter_type.var; cpt = concrete_parameter_type.cpt_var; break; } case SyntaxTree.parametr_kind.var_parametr: { par_type = SemanticTree.parameter_type.var; cpt = concrete_parameter_type.cpt_var; break; } case PascalABCCompiler.SyntaxTree.parametr_kind.params_parametr: { is_params = true; break; } } common_parameter com_par = null; if (is_params) { if (_typed_parametres.idents.idents.Count != 1) { AddError(get_location(_typed_parametres.idents.idents[1]), "ONLY_ONE_PARAMS_PARAMETER_ALLOWED"); } } if (_typed_parametres.vars_type == null) throw new NotSupportedError(get_location(_typed_parametres)); check_parameter_on_complex_type(_typed_parametres.vars_type); type_node tn = convert_strong(_typed_parametres.vars_type); if (tn.IsStatic) AddError(get_location(_typed_parametres), "VARIABLES_OF_STATIC_CLASS_NOT_ALLOWED"); if (_typed_parametres.vars_type is function_header || _typed_parametres.vars_type is procedure_header) { check_delegate_on_generic_parameters(tn as common_type_node, get_location(_typed_parametres.vars_type)); } check_for_type_allowed(tn,get_location(_typed_parametres.vars_type)); foreach (SyntaxTree.ident id in _typed_parametres.idents.idents) { com_par = context.add_parameter(id.name, par_type, cpt, get_location(id)); if (is_params) { com_par.intrenal_is_params = true; } } if (is_params) { internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface); if (ii == null) { AddError(get_location(_typed_parametres.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED"); } if (tn is compiled_type_node && (tn as compiled_type_node).rank > 1) { AddError(get_location(_typed_parametres.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED"); } if (tn is common_type_node && (tn as common_type_node).rank > 1) { AddError(get_location(_typed_parametres.vars_type), "ONLY_UNSIZED_ARRAY_PARAMS_PARAMETER_ALLOWED"); } } com_par.type = tn; foreach (SyntaxTree.ident id in _typed_parametres.idents.idents) { if (_typed_parametres.attributes != null) { make_attributes_for_declaration(_typed_parametres, com_par); } } com_par.type = tn; context.in_parameters_block = true; //TODO: Доделать параметры со значениями по умолчанию. if (_typed_parametres.inital_value != null) { if (_typed_parametres.idents.idents.Count != 1) { AddError(new OnlyOneParameterNameWithDefaultValueAllowed(get_location(_typed_parametres))); } if (cpt == concrete_parameter_type.cpt_var) { AddError(new VarParametersCanNotHaveDefaultValue(get_location(_typed_parametres))); } if (cpt == concrete_parameter_type.cpt_const) { AddError(get_location(_typed_parametres), "CONST_PARAMETERS_CANNOT_HAVE_DEFAULT_VALUE"); } context.top_function.num_of_default_variables = context.top_function.num_of_default_variables + 1; expression_node def_val_expr = convert_strong_to_constant_node(_typed_parametres.inital_value); com_par.default_value = convertion_data_and_alghoritms.convert_type(def_val_expr, tn); } context.in_parameters_block = false; context.close_var_definition_list(tn, null); } private void check_delegate_on_generic_parameters(common_type_node ctn, location loc) { if (ctn == null) return; foreach (common_method_node cmn in ctn.methods) { if (cmn.name == "Invoke") { foreach (common_parameter prm in cmn.parameters) { if (is_instance_of_generic_parameter(prm.type)) AddError(loc, "ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS"); } if (cmn.return_value_type != null && is_instance_of_generic_parameter(cmn.return_value_type)) AddError(loc, "ANONYMOUS_FUNCTION_TYPE_WITH_GENERICS"); } } } private bool is_instance_of_generic_parameter(type_node tn) { if (tn.is_generic_parameter) return true; else if (tn.is_generic_type_instance) { foreach (type_node inst_tn in tn.instance_params) if (is_instance_of_generic_parameter(inst_tn)) return true; } return false; } public override void visit(SyntaxTree.procedure_attribute _procedure_attribute) { throw new NotSupportedError(get_location(_procedure_attribute)); } public override void visit(SyntaxTree.label_definitions _label_definitions) { /*if (context.converting_block() == block_type.type_block && context.converted_type.IsInterface) { throw new InvalidInterfaceMember(get_location(_label_definitions)); }*/ foreach (SyntaxTree.ident id in _label_definitions.labels.idents) { context.add_label_declaration(id.name, get_location(id)); } } private bool depended_from_generic_parameter(type_node tn) { //Ivan 1.09.08 added if (tn == null) return false; if (tn.is_generic_parameter) return true; if (tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type) { return depended_from_generic_parameter(tn.element_type); } if (tn.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.array_kind) { return depended_from_generic_parameter(tn.element_type); } ref_type_node rtn = tn as ref_type_node; if (rtn != null) { return depended_from_generic_parameter(rtn.pointed_type); } generic_instance_type_node gitn = tn as generic_instance_type_node; if (gitn == null) return false; foreach (type_node param in gitn.generic_parameters) { if (depended_from_generic_parameter(param)) return true; } return false; } private bool is_unsized_array(SyntaxTree.indexers_types indexes, out int rank) { rank = 1; if (indexes == null) return true; bool wait_empty = false; for (int i=0; i 32) AddError(get_location(_array_type.indexers), "ARRAY_RANK_CANNOT_BE_GREATER_32"); type_node ret = null; type_node et = convert_strong(_array_type.elements_type); if (et.type_special_kind == type_special_kind.diap_type) // SSM 4/12/24 et = et.base_type; //if (et == SystemLibrary.SystemLibrary.void_type) //AddError(new VoidNotValid(get_location(_array_type.elemets_types))); check_for_type_allowed(et,get_location(_array_type.elements_type)); check_using_static_class(et, get_location(_array_type.elements_type)); ret = convertion_data_and_alghoritms.type_constructor.create_unsized_array(et, rank, get_location(_array_type)); return_value(ret); return; } type_node_list ind_types = new type_node_list(); foreach (SyntaxTree.type_definition td in _array_type.indexers.indexers) { type_node tn = convert_strong(td); internal_interface ii = tn.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null) { AddError(new OrdinalTypeExpected(get_location(td))); } if (tn.IsEnum && tn is common_type_node) { common_type_node enum_ctn = tn as common_type_node; int c = 0; for (int i = 0; i < enum_ctn.const_defs.Count; i++) { class_constant_definition ccdn = enum_ctn.const_defs[i]; if (ccdn.constant_value != null) { int nextc = Convert.ToInt32(ccdn.constant_value.value); if (nextc - c != 1 && i != 0) AddError(get_location(td), "ENUM_MUST_HAVE_SEQUENCED_VALUES"); else if (nextc != 0 && i == 0) AddError(get_location(td), "ENUM_MUST_HAVE_SEQUENCED_VALUES"); c = nextc; } } } if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type) { if (tn.base_type == SystemLibrary.SystemLibrary.uint_type || tn.base_type == SystemLibrary.SystemLibrary.int64_type || tn.base_type == SystemLibrary.SystemLibrary.uint64_type) //ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; AddError(get_location(td), "RANGE_TOO_LARGE"); if (tn.base_type == SystemLibrary.SystemLibrary.integer_type) { Int64 low = ((tn as SemanticTree.ICommonTypeNode).lower_value as int_const_node).constant_value; Int64 high = ((tn as SemanticTree.ICommonTypeNode).upper_value as int_const_node).constant_value; if (high-low >= int.MaxValue) AddError(get_location(td), "RANGE_TOO_LARGE"); } } else if (tn == SystemLibrary.SystemLibrary.uint_type || tn == SystemLibrary.SystemLibrary.int64_type || tn == SystemLibrary.SystemLibrary.uint64_type || tn == SystemLibrary.SystemLibrary.integer_type) AddError(get_location(td), "RANGE_TOO_LARGE"); ind_types.AddElement(tn); } type_node elem_type = convert_strong(_array_type.elements_type); //TODO: Сделать и массивы, связанные с generics! if (depended_from_generic_parameter(elem_type)) { throw new NotSupportedError(get_location(_array_type.elements_type)); } check_for_type_allowed(elem_type,get_location(_array_type.elements_type)); check_using_static_class(elem_type, get_location(_array_type.elements_type)); for (int i = ind_types.Count - 1; i >= 0; i--) { internal_interface ii = ind_types[i].get_internal_interface(internal_interface_kind.ordinal_interface); ordinal_type_interface oti_ind = (ordinal_type_interface)ii; elem_type = convertion_data_and_alghoritms.type_constructor.get_array_type(oti_ind, elem_type, context.converted_namespace, get_location(_array_type), generatedNamesManager); } return_value(elem_type); } public override void visit(SyntaxTree.indexers_types _indexers_types) { throw new NotSupportedError(get_location(_indexers_types)); } private constant_node convert_strong_to_constant_node(SyntaxTree.expression expr) { expression_node exp = convert_strong(expr); var is_const_section = (expr.Parent != null && (expr.Parent is const_definition)); var is_userdefined = false; var cnf = exp as common_namespace_function_call; if (cnf != null) { is_userdefined = ! (cnf.function_node.namespace_node.namespace_name.Equals(StringConstants.pascalSystemUnitName) || cnf.function_node.namespace_node.namespace_name.Equals("PABCSystem_implementation______")); } return convert_strong_to_constant_node(exp, exp.type, is_const_section && is_userdefined, is_const_section); } public expression_node convert_strong_to_constant_or_function_call_for_varinit(expression_node exp) { return convert_strong_to_constant_or_function_call_for_varinit(exp, exp.type); } private expression_node convert_strong_to_constant_or_function_call_for_varinit(expression_node exp, type_node tn) { if (exp is constant_node) { possible_type_convertions pct = type_table.get_convertions(exp.type, tn); if (pct.first != null && pct.first.convertion_method.IsOperator) //if (convertion_data_and_alghoritms.can_convert_type(exp, tn)) return convertion_data_and_alghoritms.convert_type(exp, tn); else return convert_strong_to_constant_node(exp, tn); } if (exp is array_initializer) { //if (tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper) { //exp.type = DeduceType(exp.type,exp.location); exp = ConvertArrayInitializer(tn, exp as array_initializer); return exp; //return convertion_data_and_alghoritms.convert_type(exp,tn); } // else // { // exp.type = tn; // return exp; // } } else if (exp is compiled_static_method_call && (exp.type.type_special_kind == SemanticTree.type_special_kind.set_type || exp.type.type_special_kind == SemanticTree.type_special_kind.base_set_type)) { if (!(tn == exp.type) && !type_table.is_derived(tn, exp.type) && !(convertion_data_and_alghoritms.can_convert_type(exp, tn))) { AddError(new CanNotConvertTypes(exp, exp.type, tn, exp.location)); } if (tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { compiled_static_method_call cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(exp); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; return new compiled_static_method_call_as_constant(cmc, null); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { compiled_static_method_call cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(exp); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null)); cmc.ret_type = tn; return new compiled_static_method_call_as_constant(cmc, null); } } return new compiled_static_method_call_as_constant(exp as compiled_static_method_call, null); } else if (exp is common_namespace_function_call && (exp.type.type_special_kind == SemanticTree.type_special_kind.set_type || exp.type.type_special_kind == SemanticTree.type_special_kind.base_set_type)) { if (!(tn == exp.type) && !type_table.is_derived(tn, exp.type) && !(convertion_data_and_alghoritms.can_convert_type(exp, tn))) { AddError(new CanNotConvertTypes(exp, exp.type, tn, exp.location)); } if (tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(exp); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; return new common_namespace_function_call_as_constant(cmc, null); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(exp); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null)); cmc.ret_type = tn; return new common_namespace_function_call_as_constant(cmc, null); } } return new common_namespace_function_call_as_constant(exp as common_namespace_function_call, null); } else if (exp is record_initializer) { if (tn is common_type_node) exp = ConvertRecordInitializer(tn as common_type_node, exp as record_initializer); else if (tn is compiled_type_node) throw new NotSupportedError(exp.location); return exp; } switch (SemanticRulesConstants.VariableInitializationParams) { case VariableInitializationParams.ConstructorCall: if ((exp is common_constructor_call) || (exp is compiled_constructor_call)) return convertion_data_and_alghoritms.convert_type(exp, tn); break; case VariableInitializationParams.Expression: if (exp.type != null) return convertion_data_and_alghoritms.convert_type(exp, tn); break; } return convert_strong_to_constant_node(exp, tn); } private constant_node convert_strong_to_constant_node(SyntaxTree.expression expr, type_node tn) { var exp = convert_strong(expr); var is_const_section = (expr.Parent != null && (expr.Parent is const_definition)); var is_userdefined = false; var cnf = exp as common_namespace_function_call; if (cnf != null) { is_userdefined = !(cnf.function_node.namespace_node.namespace_name.Equals(StringConstants.pascalSystemUnitName) || cnf.function_node.namespace_node.namespace_name.Equals("PABCSystem_implementation______")); } /*if (exp.type is ArrayConstType || convertion_data_and_alghoritms.eq_type_nodes(exp.type, tn)) { return convert_strong_to_constant_node(exp, tn, is_const_section && is_userdefined, is_const_section); } else { var conv = convertion_data_and_alghoritms.convert_type(exp, tn); return convert_strong_to_constant_node(conv, tn, is_const_section && is_userdefined, is_const_section); }*/ /*if (expr is pascal_set_constant) { var conv = convertion_data_and_alghoritms.convert_type(exp, tn); return convert_strong_to_constant_node(conv, tn, is_const_section && is_userdefined, is_const_section); } else { return convert_strong_to_constant_node(exp, tn, is_const_section && is_userdefined, is_const_section); }*/ return convert_strong_to_constant_node(exp, tn, is_const_section && is_userdefined, is_const_section); } private void check_set_for_constant(common_namespace_function_call cnfc) { expressions_list exprs = null; if (cnfc.function_node == SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node) exprs = get_set_initializer(cnfc); else exprs = cnfc.parameters; foreach (expression_node en in exprs) if (en is common_namespace_function_call) { cnfc = en as common_namespace_function_call; if (cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetUnionProcedure.sym_info as common_namespace_function_node || cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetSubtractProcedure.sym_info as common_namespace_function_node || cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node || cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.SetIntersectProcedure.sym_info as common_namespace_function_node || cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateDiapason.sym_info as common_namespace_function_node || cnfc.function_node == PascalABCCompiler.SystemLibrary.SystemLibInitializer.CreateObjDiapason.sym_info as common_namespace_function_node) check_set_for_constant(en as common_namespace_function_call); else AddError(en.location, "CONSTANT_EXPRESSION_EXPECTED"); } else if (!(en is constant_node /*|| en is statements_expression_node*/)) AddError(en.location, "CONSTANT_EXPRESSION_EXPECTED"); } private constant_node convert_strong_to_constant_node(expression_node expr, type_node tn, bool is_const_section_and_userfuncall = false, bool is_const_section = false, location parent_loc = null) { location loc = expr.location; if (parent_loc != null) loc = parent_loc; constant_node constant = null; try_convert_typed_expression_to_function_call(ref expr); if (expr is null_const_node) { if (!(tn is null_type_node) && !type_table.is_with_nil_allowed(tn)) AddError(loc, "NIL_WITH_VALUE_TYPES_NOT_ALLOWED"); return null_const_node.get_const_node_with_type(tn, expr as null_const_node); } if (expr is compiled_static_method_call) { compiled_static_method_call csmc = expr as compiled_static_method_call; if (csmc.type != null && csmc.type != SystemLibrary.SystemLibrary.void_type && (csmc.function_node.IsSpecialName && csmc.function_node.is_readonly || NetHelper.NetHelper.PABCSystemType != null && csmc.function_node.cont_type.compiled_type.Assembly == NetHelper.NetHelper.PABCSystemType.Assembly || !is_const_section)) constant = new compiled_static_method_call_as_constant(csmc, expr.location); } else if (expr is common_namespace_function_call && SystemLibrary.SystemLibInitializer.CreateSetProcedure != null && (expr as common_namespace_function_call).function_node == SystemLibrary.SystemLibInitializer.CreateSetProcedure.sym_info as common_namespace_function_node) { common_namespace_function_call cnfc = expr as common_namespace_function_call; expressions_list exprs = get_set_initializer(cnfc); check_set_for_constant(cnfc); foreach (expression_node en in exprs) { if (en is common_namespace_function_call) { common_namespace_function_call cnfc2 = en as common_namespace_function_call; check_set_for_constant(cnfc2); } else if (!(en is constant_node)) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } constant = new common_namespace_function_call_as_constant(cnfc, loc); } else if (expr is common_namespace_function_call cnfc1 && cnfc1.function_node.attributes.Count > 0 && cnfc1.function_node.attributes[0].attribute_type.name.ToLower() == "SetCreatorFunctionAttribute".ToLower() ) { convertion_data_and_alghoritms.check_convert_type(cnfc1, tn, loc); // Надо компоненты проверять на константность var values0 = ((cnfc1.parameters[0] as basic_function_call). parameters[0] as common_namespace_function_call).parameters.Skip(3); var values1 = ((cnfc1.parameters[1] as basic_function_call). parameters[0] as common_namespace_function_call).parameters.Skip(3); var values = values0.Concat(values1).ToArray(); foreach (expression_node en in values) { if (!(en is constant_node)) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } constant = new common_namespace_function_call_as_constant(cnfc1, loc); return constant; } else if (expr is common_namespace_function_call && (expr as common_namespace_function_call).function_node.name.StartsWith("__NewSetCreatorInternal") ) { var cnfc2 = expr as common_namespace_function_call; convertion_data_and_alghoritms.check_convert_type(cnfc2, tn, loc); var values = (cnfc2.parameters[0] as array_initializer).element_values; // Надо компоненты проверять на константность foreach (expression_node en in values) { if (!(en is constant_node)) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } constant = new common_namespace_function_call_as_constant(cnfc2, loc); return constant; } else if (is_const_section_and_userfuncall && (expr is basic_function_call || expr is common_namespace_function_call)) // только в разделе const { AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } else if (expr is common_namespace_function_call) { // Отдельно для пустого множества common_namespace_function_call cnfc = expr as common_namespace_function_call; if (cnfc.type.name == "EmptyCollection") { constant = new common_namespace_function_call_as_constant(expr as common_namespace_function_call, loc); return constant; } if (cnfc.function_node.name != "op_Implicit") foreach (expression_node el in cnfc.parameters) convert_strong_to_constant_node(el, el.type, false, false, cnfc.location); //if (cnfc.function_node.namespace_node == context.converted_namespace) // AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); // throw new ConstantExpressionExpected(loc); constant = new common_namespace_function_call_as_constant(expr as common_namespace_function_call, loc); return constant; } else if (expr is common_namespace_function_call_as_constant cnfcac && cnfcac.type.name == "EmptyCollection") { expr = create_constructor_call(tn, new expressions_list(), loc); constant = new common_constructor_call_as_constant(expr as common_constructor_call, loc); return constant; } else if (expr is common_namespace_function_call_as_constant cnfcac1) { constant = cnfcac1; return constant; } else if (expr is common_constructor_call) { constant = new common_constructor_call_as_constant(expr as common_constructor_call, null); return constant; } else if (expr is common_constructor_call_as_constant cccac) { // constant = cccac.get_constant_copy(loc); return constant; } else if (expr is basic_function_call) { basic_function_call cnfc = expr as basic_function_call; //if (cnfc.function_node.namespace_node == context.converted_namespace) // throw new ConstantExpressionExpected(loc); // Как быть с new integer[5](2,3,4)? Там cnfc.parameters сщдержит 1 элемент, у которого в parameters первые три элемента - информационные if (cnfc.parameters[0] is common_namespace_function_call cnsfc && cnsfc.function_node.SpecialFunctionKind == SpecialFunctionKind.NewArray) { foreach (expression_node el in cnsfc.parameters.Skip(3)) // это для 1 + 2 * 3 convert_strong_to_constant_node(el, el.type); if (convertion_data_and_alghoritms.eq_type_nodes(expr.type, tn)) { constant = new basic_function_call_as_constant(expr as basic_function_call, loc); return constant; } else { var conv = convertion_data_and_alghoritms.convert_type(expr, tn); constant = convert_strong_to_constant_node(conv, tn); return constant; } } else { foreach (expression_node el in cnfc.parameters) // это для 1 + 2 * 3 - этот код был convert_strong_to_constant_node(el, el.type); } constant = new basic_function_call_as_constant(expr as basic_function_call, loc); // - этот код был return constant; } else if (expr is basic_function_call_as_constant bfcac) { constant = bfcac; return constant; } else if (expr is typed_expression) { expr = convertion_data_and_alghoritms.convert_type(expr, tn); if (expr is common_constructor_call) { constant = new common_constructor_call_as_constant(expr as common_constructor_call, null); } else if (expr is typed_expression) { if (const_def_type != null) { expr = convertion_data_and_alghoritms.convert_type(expr, const_def_type); tn = const_def_type; constant = new common_constructor_call_as_constant(expr as common_constructor_call, null); } else { base_function_call bfc = ((expr as typed_expression).type as delegated_methods).proper_methods[0]; common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); tn = del; expr = convertion_data_and_alghoritms.explicit_convert_type(expr, del); expr.type = tn; constant = new common_constructor_call_as_constant(expr as common_constructor_call, loc); } } } else if (expr is namespace_constant_reference) { constant = (expr as namespace_constant_reference).constant.const_value; convertion_data_and_alghoritms.check_convert_type(constant, tn, expr.location); if ((tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.base_set_type) && tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; constant = new common_namespace_function_call_as_constant(cmc, null); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null)); cmc.ret_type = tn; constant = new common_namespace_function_call_as_constant(cmc, null); } } else if (tn.type_special_kind == SemanticTree.type_special_kind.short_string) { /*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/ expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.string_type), new int_const_node((tn as short_string_type_node).Length, null)); constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null); } /*expression_node e = convertion_data_and_alghoritms.convert_type(constant.get_constant_copy(expr.location), tn); switch (e.semantic_node_type) { case semantic_node_type.compiled_constructor_call: constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc); break; default: constant = e as constant_node; break; }*/ /*if (constant.get_object_value() != null) { //if (const_def_type != null) { expression_node e = convertion_data_and_alghoritms.convert_type(constant.get_constant_copy(expr.location), tn); switch (e.semantic_node_type) { case semantic_node_type.compiled_constructor_call: constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc); break; default: constant = e as constant_node; break; } } } else { //if (const_def_type != null) { expression_node e = convertion_data_and_alghoritms.convert_type(expr, tn); switch (e.semantic_node_type) { case semantic_node_type.compiled_constructor_call: constant = new compiled_constructor_call_as_constant(e as compiled_constructor_call, loc); break; default: constant = e as constant_node; break; } } }*/ return constant; } else if (expr is function_constant_reference) { constant = (expr as function_constant_reference).constant.const_value; convertion_data_and_alghoritms.check_convert_type(constant, tn, expr.location); if ((tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.base_set_type) && tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; constant = new common_namespace_function_call_as_constant(cmc, null); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null)); cmc.ret_type = tn; constant = new common_namespace_function_call_as_constant(cmc, null); } } else if (tn.type_special_kind == SemanticTree.type_special_kind.short_string) { /*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/ expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.string_type), new int_const_node((tn as short_string_type_node).Length, null)); constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null); } return constant; } else if (expr is static_compiled_variable_reference && !(expr as static_compiled_variable_reference).var.IsLiteral) { constant = new compiled_static_field_reference_as_constant(expr as static_compiled_variable_reference, null); return constant; } else if (expr is default_operator_node) constant = new default_operator_node_as_constant(expr as default_operator_node, null); else if (expr is sizeof_operator) constant = new sizeof_operator_as_constant(expr as sizeof_operator, null); else if (expr is typeof_operator && !is_const_section) constant = new typeof_operator_as_constant(expr as typeof_operator, null); else if (expr is common_static_method_call) { var csmc = expr as common_static_method_call; if (csmc.function_node.cont_type != null) { foreach (common_property_node cpn in csmc.function_node.cont_type.properties) if (cpn.get_function == csmc.function_node && cpn.set_function == null) { constant = new common_static_method_call_as_constant(csmc, null); break; } if (csmc.function_node.name == "op_Implicit") // SSM 04/12/24 - это делается для преобразования array в set { constant = new common_static_method_call_as_constant(csmc, loc); return constant; } } else { var values = (csmc.parameters[0] as array_initializer).element_values; // Надо компоненты проверять на константность foreach (expression_node en in values) { if (!(en is constant_node)) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); } constant = new common_static_method_call_as_constant(csmc, loc); return constant; } } else { constant = expr as constant_node; if (tn.type_special_kind == SemanticTree.type_special_kind.short_string) { /*common_namespace_function_call cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as common_namespace_function_node,null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn as short_string_type_node).Length,null));*/ expression_node cmc = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node, null, convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.string_type), new int_const_node((tn as short_string_type_node).Length, null)); if (cmc is common_namespace_function_call) constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null); else constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null); } //else //constant = convertion_data_and_alghoritms.convert_type(constant, tn) as constant_node; if (expr is static_compiled_variable_reference) { compiled_class_constant_definition cccd = NetHelper.NetHelper.ConvertToConstant(((static_compiled_variable_reference)expr).var); if (cccd != null) constant = cccd.const_value; else constant = new compiled_static_field_reference_as_constant(expr as static_compiled_variable_reference, null); } } if (constant == null) AddError(loc, "CONSTANT_EXPRESSION_EXPECTED"); if (IsBoundedArray(tn) || IsUnsizedArray(tn)) { if (!(constant is array_const)) AddError(loc, "ARRAY_CONST_EXPECTED"); constant = ConvertArrayConst(tn, constant as array_const); } else if (tn is common_type_node) { if (tn.type_special_kind != SemanticTree.type_special_kind.set_type && tn.type_special_kind != SemanticTree.type_special_kind.base_set_type && tn.type_special_kind != SemanticTree.type_special_kind.diap_type) { if (!tn.is_value) { if (expr is common_constructor_call) return constant; if (expr is common_constructor_call_as_constant) return expr as common_constructor_call_as_constant; convertion_data_and_alghoritms.check_convert_type(expr,tn,expr.location); return constant; //AddError(new CanNotConvertTypes(expr,expr.type,tn,expr.location)); //throw new NotSupportedError(loc); } if ((tn as common_type_node).IsEnum) { convertion_data_and_alghoritms.check_convert_type(expr,tn,expr.location); enum_const_node ecn = expr as enum_const_node; if (ecn == null) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED"); return ecn; } if (!(constant is record_constant)) AddError(loc, "RECORD_CONST_EXPECTED"); constant = ConvertRecordConst(tn as common_type_node, constant as record_constant); } else if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type) { constant = expr as constant_node; if (constant == null) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED"); //constant = (expr as namespace_constant_reference).constant.const_value; convertion_data_and_alghoritms.check_convert_type(constant,tn,expr.location); ordinal_type_interface oti = tn.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; bool success = false; int val = convertion_data_and_alghoritms.convert_type_to_int_constant(constant, out success); if (success) { int left = convertion_data_and_alghoritms.convert_type_to_int_constant(oti.lower_value, out success); if (success) { int right = convertion_data_and_alghoritms.convert_type_to_int_constant(oti.upper_value, out success); if (success) if (val < left || val > right) AddError(loc, "OUT_OF_RANGE"); } } } else { //obrezka konstantnogo mnozhestva if (!(tn == expr.type) && !type_table.is_derived(tn,expr.type)) { AddError(new CanNotConvertTypes(expr,expr.type,tn,expr.location)); } if (tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { base_function_call cmc = null; if (SystemLibrary.SystemLibInitializer.ClipFunction.sym_info is common_namespace_function_node) cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null); else cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; if (cmc is common_namespace_function_call) constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null); else constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null); } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { base_function_call cmc = null; if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info is common_namespace_function_node) cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null); else cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length,null)); cmc.ret_type = tn; if (cmc is common_namespace_function_call) constant = new common_namespace_function_call_as_constant(cmc as common_namespace_function_call, null); else constant = new compiled_static_method_call_as_constant(cmc as compiled_static_method_call, null); } } } } else { expression_node exprc = convertion_data_and_alghoritms.convert_type(constant, tn); switch (exprc.semantic_node_type) { case semantic_node_type.compiled_constructor_call: constant = new compiled_constructor_call_as_constant(exprc as compiled_constructor_call, loc); break; case semantic_node_type.compiled_static_method_call: constant = new compiled_static_method_call_as_constant(exprc as compiled_static_method_call, loc); break; case semantic_node_type.common_static_method_call: constant = new common_static_method_call_as_constant(exprc as common_static_method_call, loc); break; case semantic_node_type.basic_function_call: constant = new basic_function_call_as_constant(exprc as basic_function_call, loc); break; case semantic_node_type.common_namespace_function_call: constant = new common_namespace_function_call_as_constant(exprc as common_namespace_function_call, loc); break; default: constant = exprc as constant_node; break; } } return constant; } internal common_type_node CreateDelegate(function_node fn) { common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), fn.return_value_type, fn.parameters, context.converted_namespace, null); bool has_lambda_any_type = false; foreach (common_method_node cmn in del.methods) if (cmn.parameters.Count > 0 && cmn.parameters[0].type is lambda_any_type_node) { has_lambda_any_type = true; break; } if (!has_lambda_any_type) context.converted_namespace.types.AddElement(del); return del; } internal expression_node CreateDelegateCall(base_function_call fn_call) { common_type_node del = CreateDelegate(fn_call.simple_function_node); common_constructor_call deleg_costructor_call = new common_constructor_call(del.methods[0], fn_call.location); deleg_costructor_call.parameters.AddElement((base_function_call)fn_call); return deleg_costructor_call; } private record_initializer ConvertRecordInitializer(common_type_node ctn, record_initializer constant) { location loc = constant.location; var non_static_fields = ctn.fields.Where(x => !x.IsStatic).ToArray(); if (!ctn.is_value_type) AddError(loc, "RECORD_CONST_NOT_ALLOWED_{0}", ctn.name); if (non_static_fields.Length != constant.record_const_definition_list.Count) AddError(loc, "INVALID_RECORD_CONST_FIELD_COUNT"); constant.type = ctn; constant.field_values.Clear(); for (int i = 0; i < non_static_fields.Length; i++) { class_field cf = ctn.fields[i]; if (cf.name.ToLower() != constant.record_const_definition_list[i].name.name.ToLower()) AddError(get_location(constant.record_const_definition_list[i].name), "FIELD_NAME_SHOULD_BE_EQUAL_RECORD_FIELD_NAME", cf.name); expression_node en = convert_strong_to_constant_or_function_call_for_varinit(convert_strong(constant.record_const_definition_list[i].val),cf.type); en.type = cf.type; constant.field_values.Add(en); } return constant; } private array_initializer ConvertNDimArrayInitializer(type_node tn, int cur_rank, type_node element_type, array_initializer constant) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; int rank = aii.rank; int size = -1; for (int i=0; i= rank) constant.element_values[i] = ConvertArrayInitializer(tn.element_type, e as array_initializer); //AddError(new CanNotConvertTypes(e,e.type,tn.element_type,e.location)); else constant.element_values[i] = ConvertNDimArrayInitializer(tn,cur_rank + 1, element_type, e as array_initializer); } else if (e is record_initializer) { if (element_type is common_type_node) constant.element_values[i] = ConvertRecordInitializer(element_type as common_type_node, e as record_initializer); else throw new NotSupportedError(constant.element_values[i].location); } else { if (cur_rank != rank) AddError(constant.location, "RANK_MISMATCH_IN_INITILIALIZER"); constant.element_values[i] = convertion_data_and_alghoritms.convert_type(constant.element_values[i], element_type); } } constant.type = tn; return constant; } private expression_node ConvertArrayInitializer(type_node tn, array_initializer constant) { type_node element_type = null; if (IsBoundedArray(tn)) { bounded_array_interface bai = tn.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; element_type = bai.element_type; ordinal_type_interface oti_indexer = bai.ordinal_type_interface; int arr_length = oti_indexer.ordinal_type_to_int(oti_indexer.upper_value) - oti_indexer.ordinal_type_to_int(oti_indexer.lower_value) + 1; if (arr_length != constant.element_values.Count) AddError(constant.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", arr_length); } else if (IsUnsizedArray(tn)) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; element_type = aii.element_type; if (aii.rank > 1) { array_initializer cnst = ConvertNDimArrayInitializer(tn,1,element_type,constant); cnst.type = tn; return cnst; } } else if (tn == SystemLibrary.SystemLibrary.complex_type && constant.element_values.Count == 2) { compiled_constructor_call cccall = new compiled_constructor_call(SystemLibrary.SystemLibrary.complex_type_constructor, null); cccall.parameters.AddElement(convertion_data_and_alghoritms.convert_type(constant.element_values[0], SystemLibrary.SystemLibrary.double_type)); cccall.parameters.AddElement(convertion_data_and_alghoritms.convert_type(constant.element_values[1], SystemLibrary.SystemLibrary.double_type)); compiled_constructor_call_as_constant cccall_cnst = new compiled_constructor_call_as_constant(cccall, null); return cccall_cnst; } else AddError(new CanNotConvertTypes(constant,constant.type,tn,constant.location));//CompilerInternalError("Unexpected array type"); for (int i = 0; i < constant.element_values.Count; i++) if (constant.element_values[i] is array_initializer) constant.element_values[i] = ConvertArrayInitializer(element_type, constant.element_values[i] as array_initializer); else if (constant.element_values[i] is record_initializer) { if (element_type is common_type_node) constant.element_values[i] = ConvertRecordInitializer(element_type as common_type_node, constant.element_values[i] as record_initializer); else throw new NotSupportedError(constant.element_values[i].location); } else { constant.element_values[i] = convertion_data_and_alghoritms.convert_type(constant.element_values[i], element_type); } constant.type = tn; return constant; } private array_const ConvertNDimArrayConst(type_node tn, int cur_rank, type_node element_type, array_const constant) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; int rank = aii.rank; int size = -1; for (int i=0; i=rank) constant.element_values[i] = ConvertArrayConst(tn.element_type,e as array_const); //AddError(new CanNotConvertTypes(e,e.type,tn.element_type,e.location)); else constant.element_values[i] = ConvertNDimArrayConst(tn,cur_rank+1,element_type,e as array_const); } else if (e is record_constant) { if (element_type is common_type_node) constant.element_values[i] = ConvertRecordConst(element_type as common_type_node, e as record_constant); else AddError(new NotSupportedError(constant.element_values[i].location)); } else { if (cur_rank != rank) AddError(constant.location, "RANK_MISMATCH_IN_INITILIALIZER"); constant.element_values[i] = convert_strong_to_constant_node(constant.element_values[i], element_type); } } constant.SetType(tn); return constant; } private array_const ConvertArrayConst(type_node tn, array_const constant) { type_node element_type = null; if (IsBoundedArray(tn)) { bounded_array_interface bai = tn.get_internal_interface(internal_interface_kind.bounded_array_interface) as bounded_array_interface; element_type = bai.element_type; ordinal_type_interface oti_indexer = bai.ordinal_type_interface; int arr_length = oti_indexer.ordinal_type_to_int(oti_indexer.upper_value) - oti_indexer.ordinal_type_to_int(oti_indexer.lower_value) + 1; if (arr_length != constant.element_values.Count) AddError(constant.location, "ARRAY_CONST_{0}_ELEMENTS_EXPECTED", arr_length); } else if (IsUnsizedArray(tn)) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; element_type = aii.element_type; if (aii.rank > 1) { array_const cnst = ConvertNDimArrayConst(tn,1,element_type,constant); cnst.SetType(tn); return cnst; } } else throw new CompilerInternalError("Unexpected array type"); for (int i = 0; i < constant.element_values.Count; i++) { if (constant.element_values[i].type is ArrayConstType || convertion_data_and_alghoritms.eq_type_nodes(constant.element_values[i].type,element_type)) constant.element_values[i] = convert_strong_to_constant_node(constant.element_values[i], element_type); else { var conv = convertion_data_and_alghoritms.convert_type(constant.element_values[i], element_type); constant.element_values[i] = convert_strong_to_constant_node(conv, element_type); } //convertion_data_and_alghoritms.check_convert_type(constant.element_values[i], element_type,constant.element_values[i].location); } constant.SetType(tn); return constant; } private record_constant ConvertRecordConst(common_type_node ctn, record_constant constant) { location loc = constant.location; if (!ctn.is_value_type) AddError(loc, "RECORD_CONST_NOT_ALLOWED_{0}", ctn.name); if (ctn.fields.Count != constant.record_const_definition_list.Count) AddError(loc, "INVALID_RECORD_CONST_FIELD_COUNT"); constant.SetType(ctn); constant.field_values.Clear(); bool tmp = this.is_typed_const_def; this.is_typed_const_def = true; for (int i = 0; i < ctn.fields.Count; i++) { class_field cf = ctn.fields[i]; if (cf.name.ToLower() != constant.record_const_definition_list[i].name.name.ToLower()) AddError(get_location(constant.record_const_definition_list[i].name), "FIELD_NAME_SHOULD_BE_EQUAL_RECORD_FIELD_NAME", cf.name); constant.field_values.Add(convert_strong_to_constant_node(constant.record_const_definition_list[i].val, cf.type)); } this.is_typed_const_def = tmp; return constant; } public override void visit(SyntaxTree.diapason _diapason) { constant_node cnleft = convert_strong_to_constant_node(_diapason.left); constant_node cnright = convert_strong_to_constant_node(_diapason.right); type_node tn = convertion_data_and_alghoritms.type_constructor.get_pascal_diap(cnleft, cnright, get_location(_diapason.left), context.converted_namespace, get_location(_diapason.right)); return_value(tn); } public override void visit(SyntaxTree.ref_type _ref_type) { if (_ref_type.pointed_to is SyntaxTree.named_type_reference && ((_ref_type.pointed_to as SyntaxTree.named_type_reference).names.Count == 1) && context.CurrentScope.Find((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name) == null) { //это указатель на тип который еще не описан if (!is_direct_type_decl) AddError(new UndefinedNameReference((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name,get_location(_ref_type.pointed_to))); return_value(GetWaitedRefType((_ref_type.pointed_to as SyntaxTree.named_type_reference).names[0].name, get_location(_ref_type.pointed_to))); } else { type_node tn = convert_strong(_ref_type.pointed_to); if (tn.is_generic_parameter) { if (SemanticRulesConstants.AllowPointersForGenericParameters) { get_type_abilities(tn).useful_for_pointers = true; } else { AddError(get_location(_ref_type), "POINTERS_OF_GENERIC_PARAMETERS_NOT_ALLOWED"); } } else { if (!tn.is_value /*&& tn.type_special_kind != SemanticTree.type_special_kind.array_kind && tn.type_special_kind != SemanticTree.type_special_kind.set_type && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper && tn.type_special_kind != SemanticTree.type_special_kind.binary_file && tn.type_special_kind != SemanticTree.type_special_kind.binary_file*/ && !(tn is ref_type_node) && tn != SystemLibrary.SystemLibrary.pointer_type && tn.type_special_kind != SemanticTree.type_special_kind.short_string && tn.type_special_kind != SemanticTree.type_special_kind.diap_type && !tn.IsEnum && !(tn.semantic_node_type == semantic_node_type.indefinite_type)) AddError(get_location(_ref_type), "POINTERS_OF_REF_TYPES_NOT_ALLOWED"); } ref_type_node rtn = tn.ref_type; if (rtn != null) { rtn.loc = get_location(_ref_type); if (SemanticRulesConstants.StrongPointersTypeCheckForDotNet) //CheckPointersTypeForDotNetFramework(tn, get_location(_ref_type.pointed_to)); RefTypesForCheckPointersTypeForDotNetFramework.Add(rtn); return_value(rtn); } else { return_value(SystemLibrary.SystemLibrary.pointer_type); } } } internal bool CheckPointersTypeForDotNetFramework(type_node tn, location loc) { type_node ttn = FindBadTypeNodeForPointersInDotNetFramework(tn); __findBadTypeNodeForPointersPreparedTypes.Clear(); if (ttn != null) { AddErrorCheckPointersTypeForDotNetFramework(tn, ttn, loc); return false; } return true; } public void AddErrorCheckPointersTypeForDotNetFramework(type_node tn, type_node ttn, location loc) { if (tn == ttn) AddError(loc, "CANNOT_DECLARED_POINTER_TO_REFERENCE_TYPE"); else AddError(loc, "CANNOT_DECLARED_POINTER_TO_RECORD_CONTAINS_REFERENCE_FIELDS"); } private List __findBadTypeNodeForPointersPreparedTypes = new List(); private type_node FindBadTypeNodeForPointersInDotNetFramework(type_node tn) { if (__findBadTypeNodeForPointersPreparedTypes.Contains(tn)) return null; __findBadTypeNodeForPointersPreparedTypes.Add(tn); if (tn.semantic_node_type == semantic_node_type.indefinite_type) { return null; } if (tn.is_generic_parameter) { if (SemanticRulesConstants.AllowPointersForGenericParameters) { get_type_abilities(tn).useful_for_pointers = true; return null; } else { return tn; } } type_node btn = null; if (tn is ref_type_node) return FindBadTypeNodeForPointersInDotNetFramework((tn as ref_type_node).pointed_type); if (tn == SystemLibrary.SystemLibrary.pointer_type || tn == SystemLibrary.SystemLibrary.void_type) return null; if (tn.is_value) { generic_instance_type_node gitn = tn as generic_instance_type_node; if (gitn != null) { List ftypes = gitn.all_field_types; foreach (type_node ftype in ftypes) { if ((btn = FindBadTypeNodeForPointersInDotNetFramework(ftype)) != null) return btn; } return null; } if (tn is common_type_node) { if (tn.IsEnum || tn.type_special_kind == SemanticTree.type_special_kind.diap_type) return null; common_type_node ctn = tn as common_type_node; foreach (class_field cf in ctn.fields) if (!cf.IsStatic) if ((btn = FindBadTypeNodeForPointersInDotNetFramework(cf.type)) != null) return btn; return null; } if (tn is compiled_type_node) { compiled_type_node ctn = tn as compiled_type_node; if (ctn.IsPrimitive) return null; System.Reflection.FieldInfo[] fields = ctn.compiled_type.GetFields(); foreach (System.Reflection.FieldInfo fi in fields) if (!fi.IsStatic) if ((btn = FindBadTypeNodeForPointersInDotNetFramework(compiled_type_node.get_type_node(fi.FieldType))) != null) return btn; return null; } } /*if (IsBoudedArray(el_type)) { //это обычный массив bounded_array_interface bai = (bounded_array_interface)el_type.get_internal_interface(internal_interface_kind.bounded_array_interface); return CanUseThisTypeForTypedFiles(bai.element_type); }*/ if (tn == SystemLibrary.SystemLibrary.string_type || tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.short_string || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper || tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file || tn.type_special_kind == SemanticTree.type_special_kind.array_kind) return null; return tn; } /*private void ConvertStatement(SyntaxTree.statement stmt) { while (stmt != null) { if (stmt is SyntaxTree.if_node) { SyntaxTree.if_node _if_node = stmt as SyntaxTree.if_node; expression_node condition = convert_strong(_if_node.condition); condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type); statements_list sl = new statements_list(get_location(_if_node.then_body)); convertion_data_and_alghoritms.statement_list_stack_push(sl); context.enter_code_block_with_bind(); statement_node then_st = convert_strong(_if_node.then_body); context.leave_code_block(); sl = convertion_data_and_alghoritms.statement_list_stack.pop(); if (sl.statements.Count > 0) { sl.statements.AddElement(then_st); then_st = sl; } if (_if_node.else_body != null) { sl = new statements_list(get_location(_if_node.else_body)); convertion_data_and_alghoritms.statement_list_stack_push(sl); } context.enter_code_block_with_bind(); statement_node else_st = convert_weak(_if_node.else_body); context.leave_code_block(); if (_if_node.else_body != null) { sl = convertion_data_and_alghoritms.statement_list_stack.pop(); if (sl.statements.Count > 0) { sl.statements.AddElement(else_st); else_st = sl; } } if_node if_node = new if_node(condition, then_st, else_st, get_location(_if_node)); return_value(if_node); return; } visit(stmt); } }*/ void CheckToEmbeddedStatementCannotBeADeclaration(SyntaxTree.statement st) { if (st != null && st is SyntaxTree.var_statement) AddError(get_location(st), "EMBEDDED_SATATEMENT_CANNOT_BE_A_DECLARATION"); } public override void visit(SyntaxTree.if_node _if_node) { expression_node condition = null; if (!for_intellisense) { condition = convert_strong(_if_node.condition); condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type); try_convert_typed_expression_to_function_call(ref condition, true); CheckToEmbeddedStatementCannotBeADeclaration(_if_node.then_body); CheckToEmbeddedStatementCannotBeADeclaration(_if_node.else_body); } statements_list sl = new statements_list(get_location(_if_node.then_body)); convertion_data_and_alghoritms.statement_list_stack_push(sl); context.enter_code_block_with_bind(); statement_node then_st = convert_strong(_if_node.then_body); context.leave_code_block(); sl = convertion_data_and_alghoritms.statement_list_stack.Pop(); if (sl.statements.Count > 0 || sl.local_variables.Count > 0) { sl.statements.AddElement(then_st); then_st = sl; } if (_if_node.else_body != null) { sl = new statements_list(get_location(_if_node.else_body)); convertion_data_and_alghoritms.statement_list_stack_push(sl); } context.enter_code_block_with_bind(); statement_node else_st = convert_weak(_if_node.else_body); context.leave_code_block(); if (_if_node.else_body != null) { sl = convertion_data_and_alghoritms.statement_list_stack.Pop(); if (sl.statements.Count > 0 || sl.local_variables.Count > 0) { sl.statements.AddElement(else_st); else_st = sl; } } if_node if_node = new if_node(condition, then_st, else_st, get_location(_if_node)); return_value(if_node); } public override void visit(SyntaxTree.while_node _while_node) { expression_node expr = null; if (!for_intellisense) { expr = convert_strong(_while_node.expr); expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.bool_type); try_convert_typed_expression_to_function_call(ref expr, true); CheckToEmbeddedStatementCannotBeADeclaration(_while_node.statements); } while_node wn = new while_node(expr, get_location(_while_node)); context.enter_in_cycle(wn); statements_list sl = new statements_list(get_location(_while_node.statements)); convertion_data_and_alghoritms.statement_list_stack_push(sl); context.enter_code_block_with_bind(); statement_node st = convert_strong(_while_node.statements); context.leave_code_block(); sl = convertion_data_and_alghoritms.statement_list_stack.Pop(); if (sl.statements.Count > 0 || sl.local_variables.Count > 0) { sl.statements.AddElement(st); st = sl; } wn.body = st; context.leave_cycle(); return_value(wn); } public override void visit(SyntaxTree.repeat_node _repeat_node) { repeat_node rep = new repeat_node(get_location(_repeat_node)); context.enter_in_cycle(rep); statements_list sl = new statements_list(get_location(_repeat_node.statements)); convertion_data_and_alghoritms.statement_list_stack_push(sl); CheckToEmbeddedStatementCannotBeADeclaration(_repeat_node.statements); statement_node st = convert_strong(_repeat_node.statements); sl = convertion_data_and_alghoritms.statement_list_stack.Pop(); //if (!(st is statements_list)) if (sl.statements.Count > 0 || sl.local_variables.Count > 0) { sl.statements.AddElement(st); st = sl; } rep.body = st; expression_node expr = null; if (!for_intellisense) { expr = convert_strong(_repeat_node.expr); expr = convertion_data_and_alghoritms.convert_type(expr, SystemLibrary.SystemLibrary.bool_type); try_convert_typed_expression_to_function_call(ref expr, true); rep.condition = expr; } context.leave_cycle(); return_value(rep); } private expression_node additional_indexer_convertion(expression_node ind_expr, type_node array_type) { return convertion_data_and_alghoritms.convert_type(ind_expr, SystemLibrary.SystemLibrary.integer_type); } private void indexer_as_expression_index(expression_node expr, SyntaxTree.expression_list parameters, motivation mot, location loc) { try_convert_typed_expression_to_function_call(ref expr); // SSM 10.01.16 Tuple t[i] var ent = expr.type as compiled_type_node; if (ent== null) { var eeee = expr.type as compiled_generic_instance_type_node; if (eeee!= null) ent = eeee.original_generic as compiled_type_node; } if (ent != null) { var t = ent.compiled_type; if (t != null && IsTupleType(t)) { expression eee = parameters.expressions[0]; if (parameters.expressions.Count > 1) AddError(get_location(eee), "TUPLE_CAN_HAVE_ONLY_ONE_INDEX"); var cn = convert_strong_to_constant_node(eee); var v = cn as int_const_node; if (v != null) { if (v.constant_value<0 || v.constant_value >= t.GetGenericArguments().Count()) AddError(cn.location, "TUPLE_INDEX_OUT_OF_RANGE_{0}", t.GetGenericArguments().Count()-1); var dn = new dot_node(new semantic_addr_value(expr), new ident("Item" + (v.constant_value + 1).ToString(), eee.source_context),new SourceContext(loc.begin_line_num,loc.begin_column_num,loc.end_line_num,loc.end_column_num)); visit(dn); return; } else AddError(cn.location, "TUPLE_INDEX_MUST_BE_INTEGER_CONSTANT"); } } // end SSM 09.01.16 Tuple t[i] if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_kind) { internal_interface ii = expr.type.get_internal_interface(internal_interface_kind.unsized_array_interface); array_internal_interface aii = (array_internal_interface)ii; int rank = aii.rank; //TODO: Многомерные массивы. expression_node ind_expr = convert_strong(parameters.expressions[0]); ind_expr = additional_indexer_convertion(ind_expr, expr.type); try_convert_typed_expression_to_function_call(ref ind_expr, true); simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, aii.element_type, loc); if (rank == 1) for (int i = 1; i < parameters.expressions.Count; i++) { ii = sai.type.get_internal_interface(internal_interface_kind.unsized_array_interface); location lloc = get_location(parameters.expressions[i]); if (ii == null) { AddError(lloc, "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", i, i+1); } aii = (array_internal_interface)ii; ind_expr = convert_strong(parameters.expressions[i]); ind_expr = additional_indexer_convertion(ind_expr, sai.type); try_convert_typed_expression_to_function_call(ref ind_expr, true); sai = new simple_array_indexing(sai, ind_expr, aii.element_type, lloc); } else { if (rank != parameters.expressions.Count) AddError(get_location(parameters), "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", rank, rank + 1); List lst = new List(); for (int i = 0; i < parameters.expressions.Count; i++) { location lloc = get_location(parameters.expressions[i]); ind_expr = convert_strong(parameters.expressions[i]); ind_expr = additional_indexer_convertion(ind_expr, sai.type); try_convert_typed_expression_to_function_call(ref ind_expr, true); lst.Add(ind_expr); } sai = new simple_array_indexing(expr, lst[0], aii.element_type, get_location(parameters)); sai.expr_indices = lst.ToArray(); } switch (mot) { case motivation.address_receiving: { return_addressed_value(sai); break; } case motivation.expression_evaluation: { return_value(sai); break; } case motivation.semantic_node_reciving: { return_semantic_value(sai); break; } } return; } else if (expr.type.type_special_kind == SemanticTree.type_special_kind.short_string) { if (parameters.expressions.Count != 1) AddError(loc, "INVALID_PARAMETER_COUNT_IN_INDEXER"); expression_node ind_expr = convert_strong(parameters.expressions[0]); ind_expr = additional_indexer_convertion(ind_expr, expr.type); try_convert_typed_expression_to_function_call(ref ind_expr, true); //expression_node en = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null)); switch (mot) { case motivation.address_receiving: { simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, SystemLibrary.SystemLibrary.char_type, loc); return_addressed_value(sai); //return_addressed_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.SetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr) as common_namespace_function_call); break; } case motivation.expression_evaluation: { return_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null))); break; } case motivation.semantic_node_reciving: { return_semantic_value(convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.GetCharInShortStringProcedure.sym_info as function_node,loc,expr,ind_expr,new int_const_node((expr.type as short_string_type_node).Length,null))); break; } } return; } /*else if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { internal_interface ii = expr.type.get_internal_interface(internal_interface_kind.bounded_array_interface); array_internal_interface aii = (array_internal_interface)ii; //TODO: Многомерные массивы. expression_node ind_expr = convert_strong(parameters.expressions[0]); ind_expr = additional_indexer_convertion(ind_expr, expr.type); simple_array_indexing sai = new simple_array_indexing(expr, ind_expr, aii.element_type, loc); for (int i = 1; i < parameters.expressions.Count; i++) { ii = sai.type.get_internal_interface(internal_interface_kind.bounded_array_interface); location lloc = get_location(parameters.expressions[i]); if (ii == null) { throw new NDimensionalArrayCanNotHaveNPlusOneIndexer(lloc, expr, i); } aii = (array_internal_interface)ii; ind_expr = convert_strong(parameters.expressions[i]); ind_expr = create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, ind_expr, new int_const_node(ii.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),cmc.location)); ind_expr = additional_indexer_convertion(ind_expr, sai.type); sai = new simple_array_indexing(sai, ind_expr, aii.element_type, lloc); } switch (mot) { case motivation.address_reciving: { return_addressed_value(sai); break; } case motivation.expression_evaluation: { return_value(sai); break; } case motivation.semantic_node_reciving: { return_semantic_value(sai); break; } } return; if (factparams[i].semantic_node_type == semantic_node_type.common_method_call) { common_method_call cmc = (common_method_call)factparams[i]; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value),cmc.location)); factparams[i] = new simple_array_indexing(left, right, cmc.type, cmc.location); is_pascal_array_ref = true; } } } }*/ if (expr.type.default_property_node == null && expr.type is generic_instance_type_node && (expr.type as generic_instance_type_node).original_generic.default_property_node != null) { generic_convertions.instance_default_property(expr.type as generic_instance_type_node); } if (expr.type.default_property_node == null) { if (expr.type.semantic_node_type != semantic_node_type.delegated_method) { AddError(loc, "NO_DEFAULT_PROPERTY_TO_TYPE_{0}", expr.type.PrintableName); } else { AddError(loc, "NO_DEFAULT_PROPERTY_TO_FUNCTION_TYPE"); } if (for_intellisense) { return_value(expr); return; } } if (expr.type.default_property_node.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToStaticPropertyWithExpression(expr.type.default_property_node, loc, expr.type)); } non_static_property_reference nspr = new non_static_property_reference(expr.type.default_property_node, expr, loc); indexer_as_property_indexes(nspr, parameters, mot, loc); //eto vrode rabotaet normalno. no imet v vidu if (expr.type.type_special_kind == SemanticTree.type_special_kind.array_wrapper) { expression_node en = ret.get_expression(); if (en is non_static_property_reference) { non_static_property_reference cmc = (non_static_property_reference)en; internal_interface ii = cmc.expression.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { //if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.expression, cmc.location); expression_node right = cmc.fact_parametres[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); en = new simple_array_indexing(left, right, cmc.type, cmc.location); //is_pascal_array_ref = true; } } } else { common_method_call cmc = (common_method_call)en; internal_interface ii = cmc.obj.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { //if (cmc.function_node.name == StringConstants.get_val_pascal_array_name) { bounded_array_interface bai = (bounded_array_interface)ii; class_field cf = bai.int_array; expression_node left = new class_field_reference(cf, cmc.obj, cmc.location); expression_node right = cmc.parameters[0]; //right = convert_type(right, SystemLibrary.SystemLibrary.integer_type); right = convertion_data_and_alghoritms.convert_type(right, (ii as bounded_array_interface).ordinal_type_interface.elems_type); right = convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibrary.int_sub, cmc.location, right, new int_const_node(bai.ordinal_type_interface.ordinal_type_to_int(bai.ordinal_type_interface.lower_value), cmc.location)); en = new simple_array_indexing(left, right, cmc.type, cmc.location); //is_pascal_array_ref = true; } } } return_value(en); } return; } private void indexer_as_type_indexes(type_node type, SyntaxTree.expression_list parameters, motivation mot, location loc) { if (type.default_property_node == null) { if (type.semantic_node_type != semantic_node_type.delegated_method) { AddError(loc, "NO_DEFAULT_PROPERTY_TO_TYPE_{0}", type.PrintableName); } else { AddError(loc, "NO_DEFAULT_PROPERTY_TO_FUNCTION_TYPE"); } } if (type.default_property_node.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToNonStaticPropertyWithType(type.default_property_node, loc, type)); } static_property_reference spr = new static_property_reference(type.default_property_node, loc); indexer_as_property_indexes(spr, parameters, mot, loc); return; } private void indexer_as_property_indexes(static_property_reference spr, SyntaxTree.expression_list parameters, motivation mot, location loc) { /*if (spr.property.parameters.Count==0) { switch(mot) { case motivation.expression_evaluation: case motivation.semantic_node_reciving: { function_node fn=spr.property.get_function; base_function_call_with_method bfc=convertion_data_and_alghoritms.create_simple_function_call(fn,loc,new expression_node[0]); return_value(bfc); return; } case motivation.address_reciving: { return_addressed_value(spr); return; } } throw new CompilerInternalError("Unsupported motivation"); }*/ if (spr.property.parameters.Count != 0) { if (parameters.expressions.Count != spr.property.parameters.Count) { AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", spr.property.name); } for (int i = 0; i < parameters.expressions.Count; i++) { expression_node exp = convert_strong(parameters.expressions[i]); exp = convertion_data_and_alghoritms.convert_type(exp, spr.property.parameters[i].type); spr.fact_parametres.AddElement(exp); } } switch (mot) { case motivation.expression_evaluation: case motivation.semantic_node_reciving: { function_node fn = spr.property.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(spr.property, loc)); } //expression_node bfc=convertion_data_and_alghoritms.create_simple_function_call(fn,loc,spr.fact_params.ToArray()); base_function_call bfc = create_static_method_call(fn, loc, spr.property.comprehensive_type, false); bfc.parameters.AddRange(spr.fact_parametres); if (spr.property.parameters.Count != 0) { return_value(bfc); return; } indexer_as_expression_index(bfc, parameters, mot, loc); return; } case motivation.address_receiving: { if (spr.property.parameters.Count != 0) { return_addressed_value(spr); return; } function_node fn = spr.property.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(spr.property, loc)); } base_function_call bfc = create_static_method_call(fn, loc, spr.property.comprehensive_type, false); bfc.parameters.AddRange(spr.fact_parametres); indexer_as_expression_index(bfc, parameters, mot, loc); return; } } throw new CompilerInternalError("Unsupported motivation"); } private void indexer_as_property_indexes(non_static_property_reference nspr, SyntaxTree.expression_list parameters, motivation mot, location loc) { if (nspr.property.parameters.Count != 0) { if (parameters.expressions.Count != nspr.property.parameters.Count) { internal_interface ii = nspr.property.comprehensive_type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii != null) { //bounded_array_interface dii = (bounded_array_interface)ii; expression_node exp = convert_strong(parameters.expressions[0]); exp = convertion_data_and_alghoritms.convert_type(exp, nspr.property.parameters[0].type); nspr.fact_parametres.AddElement(exp); base_function_call bfc = null; for (int i = 1; i < parameters.expressions.Count; i++) { bfc = create_not_static_method_call(nspr.property.get_function, nspr.expression, exp.location, false); bfc.parameters.AddRange(nspr.fact_parametres); location lloc = get_location(parameters.expressions[i]); ii = bfc.type.get_internal_interface(internal_interface_kind.bounded_array_interface); if (ii == null) { AddError(lloc, "{0}_DIMENSIONAL_ARRAY_CAN_NOT_HAVE_{1}_AND_MORE_INDEXING", i, i+1); } bounded_array_interface bii = (bounded_array_interface)ii; exp = convert_strong(parameters.expressions[i]); exp = convertion_data_and_alghoritms.convert_type(exp, bii.index_type); nspr = new non_static_property_reference(bii.index_property, bfc, lloc); nspr.fact_parametres.AddElement(exp); } } else { AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", nspr.property.name); } } else { var lbvr = nspr.expression as local_block_variable_reference; //String 1 based if (parameters.expressions.Count == 1 && nspr.property.comprehensive_type == SystemLibrary.SystemLibrary.string_type && !SemanticRulesConstants.ZeroBasedStrings && (lbvr == null || !lbvr.var.name.StartsWith("<>match"))) { nspr.fact_parametres.AddElement( ConstructDecExpr( convertion_data_and_alghoritms.convert_type( convert_strong(parameters.expressions[0]), nspr.property.parameters[0].type), null)); } else for (int i = 0; i < parameters.expressions.Count; i++) { expression_node exp = convert_strong(parameters.expressions[i]); exp = convertion_data_and_alghoritms.convert_type(exp, nspr.property.parameters[i].type); nspr.fact_parametres.AddElement(exp); } } } switch (mot) { case motivation.expression_evaluation: case motivation.semantic_node_reciving: { function_node fn = nspr.property.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(nspr.property, loc)); } base_function_call bfc = create_not_static_method_call(fn, nspr.expression, loc, false); bfc.parameters.AddRange(nspr.fact_parametres); if (nspr.property.parameters.Count != 0) { return_value(bfc); return; } indexer_as_expression_index(bfc, parameters, mot, loc); return; } case motivation.address_receiving: { if (nspr.property.parameters.Count != 0) { return_addressed_value(nspr); return; } function_node fn = nspr.property.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(nspr.property, loc)); } base_function_call bfc = create_not_static_method_call(fn, nspr.expression, loc, false); bfc.parameters.AddRange(nspr.fact_parametres); indexer_as_expression_index(bfc, parameters, mot, loc); return; } } throw new CompilerInternalError("Unsupported motivation"); } public override void visit(SyntaxTree.indexer _indexer) { //SSM 11/02/16 - нет, это глупость /*if (_indexer.dereferencing_value is SyntaxTree.question_colon_expression) // то разбросать индекс по компонентам { var q = _indexer.dereferencing_value as SyntaxTree.question_colon_expression; var nodeToVisit = new SyntaxTree.question_colon_expression(q.condition, new indexer(q.ret_if_true as addressed_value, _indexer.indexes, _indexer.source_context), new indexer(q.ret_if_false as addressed_value, _indexer.indexes, _indexer.source_context), _indexer.source_context); visit(nodeToVisit); return; }*/ //end SSM 11/02/16 // SSM 18.08.16 - пробуем обработать захват enn[i] в yieldах где enn - поле класса и нуждается в переименовании // Так же ниже делает lroman if (_indexer.dereferencing_value is yield_unknown_ident) { var yui = (yield_unknown_ident)_indexer.dereferencing_value; var av = ProcessUnknownIdent(yui); var nodeToVisit = new indexer(av,_indexer.indexes); visit(nodeToVisit); return; } //lroman if (_indexer.dereferencing_value is closure_substituting_node) { var nodeToVisit = new indexer(((closure_substituting_node) _indexer.dereferencing_value).substitution, _indexer.indexes); visit(nodeToVisit); return; } var mot = motivation_keeper.motivation; motivation_keeper.reset(); SyntaxTree.ident idi = _indexer.dereferencing_value as SyntaxTree.ident; if (idi != null) { List sil = context.find(idi.name); if (sil == null) { AddError(new UndefinedNameReference(idi.name, get_location(idi))); } if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) { indexer_as_type_indexes((type_node)sil.FirstOrDefault().sym_info, _indexer.indexes, mot, get_location(idi)); return; } if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.property_node) { property_node pn = (property_node)sil.FirstOrDefault().sym_info; if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { static_property_reference spr = new static_property_reference(pn, get_location(idi)); indexer_as_property_indexes(spr, _indexer.indexes, mot, get_location(idi)); return; } else { this_node thisnode = new this_node(pn.comprehensive_type, get_location(_indexer)); location loc111 = get_location(idi); non_static_property_reference nspr = new non_static_property_reference(pn, thisnode, loc111); indexer_as_property_indexes(nspr, _indexer.indexes, mot, loc111); return; } } expression_node en = ident_value_reciving(sil, idi); indexer_as_expression_index(en, _indexer.indexes, mot, get_location(idi)); return; } else { SyntaxTree.dot_node dotnd = _indexer.dereferencing_value as SyntaxTree.dot_node; if (dotnd != null) { SyntaxTree.ident id = dotnd.right as SyntaxTree.ident; semantic_node sn = convert_semantic_strong(dotnd.left); switch (sn.general_node_type) { case general_node_type.type_node: { type_node ttp = (type_node)sn; List sil = ttp.find_in_type(id.name, context.CurrentScope); if (sil == null) { AddError(new UndefinedNameReference(id.name, get_location(id))); } if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.property_node) { property_node pn = (property_node)sil.FirstOrDefault().sym_info; static_property_reference spr = new static_property_reference(pn, get_location(id)); indexer_as_property_indexes(spr, _indexer.indexes, mot, get_location(dotnd)); return; } expression_node exp1 = create_static_expression(ttp, id, sil); indexer_as_expression_index(exp1, _indexer.indexes, mot, get_location(id)); return; } case general_node_type.namespace_node: case general_node_type.unit_node: { List sil = null; if (sn is namespace_node) { sil = ((namespace_node)sn).find(id.name); } else { sil = ((unit_node)sn).find_only_in_namespace(id.name); } if (sil == null) { AddError(new UndefinedNameReference(id.name, get_location(id))); } location lloc = get_location(id); if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.type_node) { type_node tn = (type_node)sil.FirstOrDefault().sym_info; indexer_as_type_indexes(tn, _indexer.indexes, mot, lloc); return; } expression_node exp2 = ident_value_reciving(sil, id); indexer_as_expression_index(exp2, _indexer.indexes, mot, get_location(id)); return; } case general_node_type.expression: { expression_node ex = (expression_node)sn; List sil = ex.type.find_in_type(id.name, context.CurrentScope); if (sil == null) { AddError(new UndefinedNameReference(id.name, get_location(id))); } if (sil.FirstOrDefault().sym_info.general_node_type == general_node_type.property_node) { property_node pn = (property_node)sil.FirstOrDefault().sym_info; if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { AddError(new CanNotReferenceToStaticPropertyWithExpression(pn, get_location(dotnd), ex.type)); } location lloc11 = get_location(dotnd); try_convert_typed_expression_to_function_call(ref ex); non_static_property_reference nspr = new non_static_property_reference(pn, ex, lloc11); indexer_as_property_indexes(nspr, _indexer.indexes, mot, lloc11); return; } expression_node en2 = convert_strong(_indexer.dereferencing_value);//expression_value_reciving(id, sil, ex, false); indexer_as_expression_index(en2, _indexer.indexes, mot, get_location(id)); return; } } } else { expression_node expr = convert_strong(_indexer.dereferencing_value); indexer_as_expression_index(expr, _indexer.indexes, mot, get_location(_indexer.dereferencing_value)); return; } } } public override void visit(SyntaxTree.roof_dereference _roof_dereference) { expression_node exp = null; var mot = motivation_keeper.motivation; motivation_keeper.reset(); exp = convert_strong(_roof_dereference.dereferencing_value); if (exp is typed_expression) exp = convert_typed_expression_to_function_call(exp as typed_expression); //Check this expression ref_type_node rtn = exp.type as ref_type_node; //TODO: Сделать нормальное сообщение об ошибке. if (rtn == null) { AddError(get_location(_roof_dereference.dereferencing_value), "CANNOT_DEREFER_THIS_EXPR_OF_NON_POINTER_TYPE"); } if (rtn.pointed_type == null) AddError(get_location(_roof_dereference.dereferencing_value), "TYPE_{0}_IS_NOT_DETERMINED_COMPLETELY", rtn.PointedTypeName); dereference_node res = new dereference_node(exp, get_location(_roof_dereference)); switch (mot) { case motivation.address_receiving: return_addressed_value(res); break; case motivation.expression_evaluation: return_value(res); break; case motivation.semantic_node_reciving: return_semantic_value(res); break; } return; } public override void visit(SyntaxTree.dereference _dereference) { throw new NotSupportedError(get_location(_dereference)); } public override void visit(SyntaxTree.expression_list _expression_list) { //throw new NotSupportedError(get_location(_expression_list)); int count = _expression_list.expressions.Count; statement_node_list snl = new statement_node_list(); for (int i = 0; i < count - 1; i++) { statement_node sn = ret.visit(_expression_list.expressions[i]); snl.AddElement(sn); } expression_node ex = ret.visit(_expression_list.expressions[count - 1]); statements_expression_node sen = new statements_expression_node( snl, ex, get_location(_expression_list)); return_value(sen); } public override void visit(SyntaxTree.string_const _string_const) { expression_node en = null; if (_string_const.Value.Length != 1 || _string_const.IsInterpolated) { en = new string_const_node(_string_const.Value, get_location(_string_const)); if (SemanticRulesConstants.GenerateNativeCode && SemanticRulesConstants.StringType != null) en.type = SemanticRulesConstants.StringType; } else en = new char_const_node(Convert.ToChar(_string_const.Value), get_location(_string_const)); return_value(en); } public override void visit(SyntaxTree.program_name _program_name) { throw new NotSupportedError(get_location(_program_name)); } public override void visit(SyntaxTree.program_tree _program_tree) { _program_tree.compilation_units[0].visit(this); } public override void visit(SyntaxTree.declarations _subprogram_definitions) { if (SemanticRulesConstants.OrderIndependedTypeNames) { foreach (SyntaxTree.declaration sd in _subprogram_definitions.defs) { if (sd is SyntaxTree.type_declaration) { convertion_data_and_alghoritms.check_node_parser_error(sd); sd.visit(this); } } } List namespaces = new List(); foreach (SyntaxTree.declaration sd in _subprogram_definitions.defs) { convertion_data_and_alghoritms.check_node_parser_error(sd); if (sd is syntax_namespace_node) namespaces.Add(sd as syntax_namespace_node); } if (namespaces.Count > 0) convert_pabc_namespaces(namespaces.ToArray()); foreach (SyntaxTree.declaration sd in _subprogram_definitions.defs) { convertion_data_and_alghoritms.check_node_parser_error(sd); if (!(sd is syntax_namespace_node)) sd.visit(this); } if (SemanticRulesConstants.OrderIndependedFunctionNames) { visit_function_realizations(_subprogram_definitions); context.clear_member_bindings(); } } public override void visit(SyntaxTree.declaration _subprogram_definition) { throw new NotSupportedError(get_location(_subprogram_definition)); } private SyntaxTree.expression get_possible_array_const(SyntaxTree.expression expr, type_node tn, int rank) { try { if (tn == null) return expr; if (rank == 0) return get_possible_array_const(expr, tn.element_type); if (expr is SyntaxTree.bracket_expr) { SyntaxTree.array_const arr = new SyntaxTree.array_const(); arr.source_context = expr.source_context; arr.elements = new SyntaxTree.expression_list(); arr.elements.expressions.Add(get_possible_array_const((expr as SyntaxTree.bracket_expr).expr, tn.element_type, rank - 1)); return arr; } else if (expr is SyntaxTree.array_const) { SyntaxTree.array_const arr = expr as SyntaxTree.array_const; if (arr.elements != null) for (int i = 0; i < arr.elements.expressions.Count; i++) arr.elements.expressions[i] = get_possible_array_const(arr.elements.expressions[i], tn.element_type, rank - 1); return arr; } } catch { } return expr; } private SyntaxTree.expression get_possible_array_const(SyntaxTree.expression expr, type_node tn) { try { if (tn == null) return expr; if (expr is SyntaxTree.array_const && tn.BaseFullName != null && tn.BaseFullName.StartsWith("System.Tuple") && tn.type_special_kind != SemanticTree.type_special_kind.array_kind) { method_call mc = new method_call(); mc.parameters = (expr as SyntaxTree.array_const).elements; mc.dereferencing_value = new dot_node(new ident("Tuple", expr.source_context), new ident("Create", expr.source_context), expr.source_context); return mc; } else if (expr is SyntaxTree.bracket_expr && (tn.type_special_kind == SemanticTree.type_special_kind.array_kind || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper)) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (aii != null && aii.rank > 1) return get_possible_array_const(expr, tn, aii.rank); SyntaxTree.array_const arr = new SyntaxTree.array_const(); arr.source_context = expr.source_context; arr.elements = new SyntaxTree.expression_list(); arr.elements.expressions.Add(get_possible_array_const((expr as SyntaxTree.bracket_expr).expr, tn.element_type)); return arr; } else if (expr is SyntaxTree.array_const && (tn.type_special_kind == SemanticTree.type_special_kind.array_kind || tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper)) { array_internal_interface aii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface; if (aii != null && aii.rank > 1) return get_possible_array_const(expr, tn, aii.rank); SyntaxTree.array_const arr = expr as SyntaxTree.array_const; if (arr.elements != null) for (int i = 0; i < arr.elements.expressions.Count; i++) arr.elements.expressions[i] = get_possible_array_const(arr.elements.expressions[i], tn.element_type); return arr; } else if (expr is SyntaxTree.record_const && tn is common_type_node) { common_type_node ctn = tn as common_type_node; SyntaxTree.record_const rec = expr as SyntaxTree.record_const; for (int i = 0; i < rec.rec_consts.Count; i++) { if (i < ctn.fields.Count) rec.rec_consts[i].val = get_possible_array_const(rec.rec_consts[i].val, ctn.fields[i].type); } return rec; } } catch { } return expr; } private bool is_delegate_wrapper_with_generics(type_node tn) { var del = tn as delegated_methods; if (del == null) return false; if (del.proper_methods[0].ret_type != null && del.proper_methods[0].ret_type.is_generic_parameter) return true; return false; } public override void visit(SyntaxTree.var_def_statement _var_def_statement) { var_def_statement_converting = true; if (_var_def_statement.vars_type != null && _var_def_statement.vars_type is procedure_header) { var ph = _var_def_statement.vars_type as procedure_header; if (ph.parameters != null) foreach (var x in ph.parameters.params_list) { if (x.inital_value != null) AddError(get_location(x.inital_value), "DEFAULT_PARAMS_IN_DELEGATE_TYPE"); // SSM bug fix #1463 } } context.static_variable_converted = _var_def_statement.var_attr == SyntaxTree.definition_attribute.Static ? true : false; if (_var_def_statement.vars_type == null && _var_def_statement.inital_value is SyntaxTree.function_lambda_definition fld) { if (fld.formal_parameters != null && fld.formal_parameters.params_list.Select(x => x.vars_type).Any(x=>x is lambda_inferred_type)) AddError(get_location(_var_def_statement.inital_value), "IMPOSSIBLE_TO_INFER_TYPES_IN_LAMBDA"); if (fld.return_type is lambda_inferred_type) AddError(get_location(_var_def_statement.inital_value), "IMPOSSIBLE_TO_INFER_TYPES_IN_LAMBDA"); if (fld.return_type == null) _var_def_statement.vars_type = new procedure_header(fld.formal_parameters, null, null, false, false, null, null, _var_def_statement.source_context); else _var_def_statement.vars_type = new function_header(fld.formal_parameters, null, null, null, fld.return_type, _var_def_statement.source_context); //else // AddError(get_location(_var_def_statement.inital_value), "IMPOSSIBLE_TO_INFER_TYPES_IN_LAMBDA"); //lroman// } if (_var_def_statement.vars_type == null && _var_def_statement.inital_value is SyntaxTree.pascal_set_constant pc) { if (pc.values==null || pc.values.Count == 0) AddError(get_location(_var_def_statement.inital_value), "IMPOSSIBLE_TO_INFER_SET_TYPE"); } bool is_event = _var_def_statement.is_event; if (context.converting_block() == block_type.type_block && context.converted_type.IsInterface && !is_event) { AddError(get_location(_var_def_statement), "INVALID_INTERFACE_MEMBER"); } if (is_event && context.converting_block() == block_type.type_block && context.converted_type.IsInterface && (_var_def_statement.vars_type is function_header || _var_def_statement.vars_type is procedure_header)) AddError(get_location(_var_def_statement.vars_type), "ANONYMOUS_DELEGATE_IN_INTERFACE_NOT_ALLOWED"); type_node tn = null; expression_node inital_value = null; if (_var_def_statement.vars_type != null) { tn = convert_strong(_var_def_statement.vars_type); if (tn.type_special_kind != SemanticTree.type_special_kind.array_kind && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper && !tn.BaseFullName.StartsWith("System.Tuple") && _var_def_statement.inital_value is SyntaxTree.array_const ac) { AddError(get_location(_var_def_statement), "IMPOSSIBLE_TO_CONVERT_ARRAY_CONST_TO_{0}", tn); } //LambdaHelper.InferTypesFromVarStmt(tn, _var_def_statement.inital_value as SyntaxTree.function_lambda_definition, this); //lroman// if (tn.IsStatic && _var_def_statement.vars.idents[0].name != yieldSelf) // SSM 10/07/19 fix #1639 в статическом классе можно только фиктивное поле с именем StringConstants.yieldSelf описать - для того чтобы посмотреть на семантике его тип!!! AddError(get_location(_var_def_statement), "VARIABLES_OF_STATIC_CLASS_NOT_ALLOWED"); var fld1 = _var_def_statement.inital_value as SyntaxTree.function_lambda_definition; if (fld1 != null) { MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(fld1); LambdaHelper.InferTypesFromVarStmt(tn, fld1, this); //lroman// fld1.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //SSM 12.2017 } ref_type_node rt = tn as ref_type_node; if (rt != null) { if (type_section_converting) { RefTypesForCheckPointersTypeForDotNetFramework.Add(rt); } else { CheckPointersTypeForDotNetFramework(rt.pointed_type, get_location(_var_def_statement.vars_type)); } } if (is_event && !tn.IsDelegate) AddError(get_location(_var_def_statement.vars_type), "EVENT_TYPE_MUST_BE_DELEGATE"); check_for_type_allowed(tn,get_location(_var_def_statement.vars_type)); if (_var_def_statement.vars_type is function_header || _var_def_statement.vars_type is procedure_header) check_delegate_on_generic_parameters(tn as common_type_node, get_location(_var_def_statement.vars_type)); if (context.converting_block() == block_type.type_block && context.converted_type.is_value_type && _var_def_statement.var_attr != SyntaxTree.definition_attribute.Static) CheckForCircuralInRecord(tn, get_location(_var_def_statement.vars_type)); if (_var_def_statement.inital_value != null) if (is_event) AddError(new NotSupportedError(get_location(_var_def_statement.inital_value))); else { _var_def_statement.inital_value = get_possible_array_const(_var_def_statement.inital_value,tn); var ivc = convert_strong(_var_def_statement.inital_value); inital_value = convert_strong_to_constant_or_function_call_for_varinit(ivc, tn); if (!tn.IsDelegate && tn != SystemLibrary.SystemLibrary.object_type && inital_value is typed_expression && _var_def_statement.inital_value is addressed_value) { method_call mc = new method_call(); mc.dereferencing_value = _var_def_statement.inital_value as addressed_value; ivc = convert_strong(mc); inital_value = convert_strong_to_constant_or_function_call_for_varinit(ivc, tn); } } } else { if (is_event) AddError(get_location(_var_def_statement), "EVENT_MUST_HAVE_TYPE"); var ex = convert_strong(_var_def_statement.inital_value); expression_node cn = convert_strong_to_constant_or_function_call_for_varinit(ex); if (cn is constant_node) (cn as constant_node).SetType(DeduceType(cn.type, get_location(_var_def_statement.inital_value))); inital_value = cn; tn = inital_value.type; if (tn is null_type_node) AddError(cn.location, "CAN_NOT_DEDUCE_TYPE_{0}", tn.name); if (context.converting_block() == block_type.type_block && context.converted_type.is_value_type && _var_def_statement.var_attr != SyntaxTree.definition_attribute.Static) CheckForCircuralInRecord(tn, get_location(_var_def_statement)); } if (inital_value != null && inital_value is typed_expression) { inital_value = convert_typed_expression_to_function_call(inital_value as typed_expression); tn = inital_value.type; if (inital_value is typed_expression) { base_function_call bfc = ((inital_value as typed_expression).type as delegated_methods).proper_methods[0]; if (bfc.function.is_generic_function && _var_def_statement.vars_type == null) { AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null); } foreach (parameter p in bfc.simple_function_node.parameters) { if (p.type.is_generic_parameter || is_instance_of_generic_parameter(p.type)) AddError(get_location(_var_def_statement), "ANONYMOUS_DELEGATES_WITH_GENERIC_PARAMS_NOT_ALLOWED"); } if (bfc.simple_function_node.return_value_type != null && (bfc.simple_function_node.return_value_type.is_generic_parameter || is_instance_of_generic_parameter(bfc.simple_function_node.return_value_type))) AddError(get_location(_var_def_statement), "ANONYMOUS_DELEGATES_WITH_GENERIC_PARAMS_NOT_ALLOWED"); common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); tn = del; inital_value = convertion_data_and_alghoritms.explicit_convert_type(inital_value, del); inital_value.type = tn; } else if (inital_value is base_function_call) { base_function_call bfc = inital_value as base_function_call; if (bfc.function.is_generic_function && _var_def_statement.vars_type == null) { AddError(inital_value.location, "CAN_NOT_DEDUCE_TYPE_{0}", null); } } } foreach (SyntaxTree.ident id in _var_def_statement.vars.idents) { location lid = get_location(id); SemanticTree.polymorphic_state ps = SemanticTree.polymorphic_state.ps_common; if (_var_def_statement.var_attr == SyntaxTree.definition_attribute.Static) ps = SemanticTree.polymorphic_state.ps_static; if (!is_event) { var_definition_node vdn = context.add_var_definition(id.name, lid, ps); assign_doc_info(vdn,_var_def_statement); if (_var_def_statement.attributes != null) { make_attributes_for_declaration(_var_def_statement, vdn); } } else { event_node ce = null; if (context.converted_type != null && context.converted_type.IsInterface) ps = SemanticTree.polymorphic_state.ps_virtual_abstract; if (context.converted_type != null) ce = context.add_event_definition(id.name, lid, tn, ps, context.converted_type.IsInterface); else if (context.top_function == null) ce = context.add_namespace_event(id.name, lid, tn); else AddError(lid, "EVENT_MUST_BE_IN_CLASS_OR_NAMESPACE"); assign_doc_info(ce,_var_def_statement); if (_var_def_statement.attributes != null) { make_attributes_for_declaration(_var_def_statement, ce); } } } if (context.converted_type != null && context.converting_block() == block_type.type_block && context.converted_type.IsStatic && _var_def_statement.var_attr != definition_attribute.Static) AddError(get_location(_var_def_statement), "STATIC_CLASSES_CANNOT_NON_STATIC_MEMBERS"); var_def_statement_converting = false; context.static_variable_converted = false; if (is_event) return; context.save_var_definitions(); context.restore_var_definitions(); context.close_var_definition_list(tn, inital_value); if (!SemanticRulesConstants.ManyVariablesOneInitializator && _var_def_statement.inital_value != null && _var_def_statement.vars.idents.Count > 1) AddError(get_location(_var_def_statement.inital_value), "ONE_VARIABLE_ONE_INITIALIZATOR"); } private void CheckForCircularityInPointers(ref_type_node left, type_node right, location loc) { if (left == null || right == null) return; if (left == right) // #ErrorRefactoringProblem // AddError(loc, "CIRCULARITY_IN_POINTER"); // Если заменить этой строкой следующую, то при запуске bin\TestRunner.exe это приложение зацикливается, что сопровождается утечкой памяти AddError(new CircuralityInPointer(loc)); if (right is ref_type_node) CheckForCircularityInPointers(left, (right as ref_type_node).pointed_type, loc); else if (right.type_special_kind == SemanticTree.type_special_kind.array_kind || right.type_special_kind == SemanticTree.type_special_kind.array_wrapper) CheckForCircularityInPointers(left,right.element_type,loc); } private void CheckForCircuralInRecord(type_node tn, location loc) { if (tn == context.converted_type || tn.original_generic == context.converted_type) { AddError(loc, "CIRCULARITY_IN_RECORD"); } if (tn is common_type_node) { common_type_node ctn = tn as common_type_node; if (ctn.is_value_type) { foreach (class_field fld in ctn.fields) if (fld.polymorphic_state != SemanticTree.polymorphic_state.ps_static) CheckForCircuralInRecord(fld.type, loc); } else { foreach (class_field fld in ctn.fields) if (fld.polymorphic_state != SemanticTree.polymorphic_state.ps_static && fld.type is simple_array) CheckForCircuralInRecord((fld.type as simple_array).element_type, loc); } } } //Пытается вывести тип private type_node DeduceType(type_node tn, location loc) { if (tn is undefined_type || tn is null_type_node) { if (tn is ArrayConstType) return convertion_data_and_alghoritms.type_constructor.create_unsized_array(((ArrayConstType)tn).element_type, 1, loc); AddError(loc, "CAN_NOT_DEDUCE_TYPE_{0}", tn.name); } return tn; } public override void visit(SyntaxTree.ident_list _ident_list) { throw new NotSupportedError(get_location(_ident_list)); } public override void visit(SyntaxTree.variable_definitions _variable_definitions) { bool is_event = false; foreach (SyntaxTree.var_def_statement vds in _variable_definitions.var_definitions) { convertion_data_and_alghoritms.check_node_parser_error(vds); if (vds.is_event && !is_event) is_event = true; else if (is_event) vds.is_event = true; vds.visit(this); } } public override void visit(SyntaxTree.named_type_reference _named_type_reference) { var loc = get_location(_named_type_reference); type_node tn = find_type(_named_type_reference, loc); return_value(tn); } public override void visit(SyntaxTree.type_definition _type_definition) { throw new NotSupportedError(get_location(_type_definition)); } public override void visit(SyntaxTree.addressed_value _addressed_value) { throw new NotSupportedError(get_location(_addressed_value)); } private addressed_expression ident_address_reciving(SymbolInfo si, SyntaxTree.ident _ident) { location lloc = get_location(_ident); definition_node dn = null; if (!internal_is_assign) dn = context.check_name_node_type(_ident.name, si, lloc, general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node); else dn = context.check_name_node_type(_ident.name, si, lloc, general_node_type.variable_node, general_node_type.property_node, general_node_type.event_node, general_node_type.constant_definition); if (dn.general_node_type == general_node_type.constant_definition) AddError(get_location(_ident), "CAN_NOT_ASSIGN_TO_CONSTANT_OBJECT"); switch (dn.general_node_type) { case general_node_type.variable_node: { local_variable lv = dn as local_variable; if (lv != null && (lv.function is common_method_node)) { //self variable if ((lv.function as common_method_node).self_variable == lv) { AddError(lloc, "VARIABLE_{0}_READONLY", lv.name); } } return create_variable_reference(dn, lloc); } case general_node_type.property_node: { property_node pn = (property_node)dn; if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { static_property_reference spr = new static_property_reference(pn, lloc); return spr; } //this_node thisnode=new this_node(context.converted_type,lloc); if (pn.comprehensive_type.Scope == null && pn is compiled_property_node) (pn.comprehensive_type as compiled_type_node).init_scope(); non_static_property_reference nspr = new non_static_property_reference(pn, GetCurrentObjectReference(pn.comprehensive_type.Scope, pn, lloc), lloc); return nspr; } case general_node_type.event_node: { if (dn.semantic_node_type == semantic_node_type.compiled_event) { compiled_event ce = (compiled_event)dn; if (ce.is_static) { static_event_reference ser = new static_event_reference(ce, get_location(_ident)); return ser; } nonstatic_event_reference nser = new nonstatic_event_reference( GetCurrentObjectReference(ce.comprehensive_type.Scope, ce, lloc), ce, lloc); return nser; } else if (dn.semantic_node_type == semantic_node_type.common_event) { common_event ce = (common_event)dn; if (ce.is_static) { static_event_reference ser = new static_event_reference(ce, get_location(_ident)); return ser; } nonstatic_event_reference nser = new nonstatic_event_reference( GetCurrentObjectReference(ce.comprehensive_type.Scope, ce, lloc), ce, lloc); return nser; } else if (dn.semantic_node_type == semantic_node_type.common_namespace_event) { common_namespace_event cne = (common_namespace_event)dn; static_event_reference ser = new static_event_reference(cne, get_location(_ident)); return ser; } break; } } return null; } private expression_node ident_value_reciving(List sil, SyntaxTree.ident _ident) { //SymbolInfo si=blocks.find(_ident.name); location lloc = get_location(_ident); definition_node dn = context.check_name_node_type(_ident.name, sil?.FirstOrDefault(), get_location(_ident), general_node_type.variable_node, general_node_type.function_node, general_node_type.property_node, general_node_type.constant_definition, general_node_type.event_node); switch (dn.general_node_type) { case general_node_type.constant_definition: { constant_definition_node cdn = (constant_definition_node)dn; if (cdn.const_value is array_const || cdn.const_value is record_constant || cdn.const_value is common_namespace_function_call_as_constant) { return create_constant_reference(cdn,lloc); } if (cdn.const_value == null) AddError(new UndefinedNameReference(cdn.name,get_location(_ident))); constant_node cn = cdn.const_value.get_constant_copy(get_location(_ident)); if (cn != null) return cn; return cdn.const_value; } case general_node_type.variable_node: { local_variable lv = dn as local_variable; if (lv != null && (lv.function is common_method_node)) { //self variable if ((lv.function as common_method_node).self_variable == lv) //return new this_node((lv.function as common_method_node).cont_type, lloc); return new this_node(lv.type, lloc); //return GetCurrentObjectReference((lv.function as common_method_node).cont_type.Scope, lloc); } return create_variable_reference(dn, lloc); } case general_node_type.function_node: { //return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(), // si,lloc,blocks.converted_type,blocks.top_function,false); if (SystemUnitAssigned && SystemLibrary.SystemLibInitializer.PascalABCVersion.Equal(sil)) { return new string_const_node(RevisionClass.FullVersion, get_location(_ident)); } if (sil.FirstOrDefault().sym_info == SystemLibrary.SystemLibInitializer.NewProcedure.sym_info) { AddError(lloc, "EXPECTED_TYPE_AFTER_NEW"); } if (sil.FirstOrDefault().sym_info == SystemLibrary.SystemLibInitializer.DisposeProcedure.sym_info) { AddError(lloc, "CANNOT_GET_POINTER_TO_DISPOSE"); } if (sil.FirstOrDefault().sym_info is common_method_node && (sil.FirstOrDefault().sym_info as common_method_node).is_constructor) return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(), sil, lloc, context.converted_type, context.top_function, false); if (!(sil.FirstOrDefault().sym_info is common_in_function_function_node)) { var ex = sil.FirstOrDefault().sym_info as basic_function_node; //if (ex != null && ex.name.ToLower() == "exit") // return new basic_function_call(ex, ex.location); return make_delegate_wrapper(null, sil, lloc, ((sil.FirstOrDefault().sym_info is common_method_node) && ((common_method_node)sil.FirstOrDefault().sym_info).IsStatic)); } return convertion_data_and_alghoritms.create_full_function_call(new expressions_list(), sil, lloc,context.converted_type,context.top_function,false); } case general_node_type.property_node: { property_node pn = (property_node)dn; function_node fn = pn.get_function; if (fn == null) { AddError(new ThisPropertyCanNotBeReaded(pn, lloc)); } if (pn.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { return create_static_method_call(fn, lloc, pn.comprehensive_type, false); } check_property_no_params(pn, lloc); //this_node thisnode = new this_node(context.converted_type, lloc); if (pn.comprehensive_type.Scope == null && pn is compiled_property_node) (pn.comprehensive_type as compiled_type_node).init_scope(); return create_not_static_method_call(fn, GetCurrentObjectReference(pn.comprehensive_type.Scope, fn, lloc), lloc, false); } case general_node_type.event_node: { if (dn.semantic_node_type == semantic_node_type.compiled_event) { compiled_event ce = (compiled_event)dn; if (ce.is_static) { static_event_reference ser = new static_event_reference(ce, get_location(_ident)); return ser; } nonstatic_event_reference nser = new nonstatic_event_reference( new this_node(context.converted_type, lloc), ce, lloc); return nser; } else if (dn.semantic_node_type == semantic_node_type.common_event) { common_event ce = (common_event)dn; if (ce.is_static) { static_event_reference ser = new static_event_reference(ce, get_location(_ident)); return ser; } nonstatic_event_reference nser = new nonstatic_event_reference( new this_node(context.converted_type, lloc), ce, lloc); return nser; } else if (dn.semantic_node_type == semantic_node_type.common_namespace_event) { common_namespace_event cne = (common_namespace_event)dn; if (_compiled_unit.namespaces.IndexOf(cne.namespace_node) != -1) { static_event_reference ser = new static_event_reference(cne, get_location(_ident)); return ser; } else AddError(get_location(_ident), "EVENT_{0}_MUST_BE_IN_LEFT_PART", cne.name); } break; } } return null; } private expression_node create_constant_reference(constant_definition_node cdn, location loc) { if (cdn is namespace_constant_definition) return new namespace_constant_reference(cdn as namespace_constant_definition,loc); else if (cdn is function_constant_definition) return new function_constant_reference(cdn as function_constant_definition,loc); else return cdn.const_value; } private List find_in_base(SyntaxTree.inherited_message ident) { if (context.converted_type == null) { AddError(get_location(ident), "INHERITED_EXPECTED_IN_CLASS"); } if (context.converted_type.base_type == null) { AddError(get_location(ident), "NO_BASE_CLASS_DEFINED_BUT_INHERITED_MEET"); } common_method_node cmn = context.converted_func_stack.Last() as common_method_node; if (cmn == null) { AddError(get_location(ident), "NAME_IN_BASE_CLASS_MUST_BE_METHOD"); } List sil = null; if (cmn.is_constructor) sil = context.converted_type.base_type.find_in_type(default_constructor_name, context.CurrentScope); else sil = context.converted_type.base_type.find_in_type(cmn.name, context.CurrentScope); if (sil != null) { while (sil.Count != 0) { if (!cmn.is_constructor) { if (sil.FirstOrDefault().sym_info is function_node && convertion_data_and_alghoritms.function_eq_params_and_result(sil.FirstOrDefault().sym_info as function_node, cmn)) return sil; } else { if (sil.FirstOrDefault().sym_info is function_node && convertion_data_and_alghoritms.function_eq_params(sil.FirstOrDefault().sym_info as function_node, cmn)) return sil; } sil.RemoveAt(0); } sil = null; } if (cmn.is_constructor) AddError(get_location(ident), "NO_CONSTRUCTOR_IN_BASE_CLASS_WITH_SAME_PARAMETERS"); else AddError(get_location(ident), "NAME_IN_BASE_CLASS_MUST_BE_METHOD"); return sil; /*if (si == null) { throw new UndefinedNameReference(name, get_location(ident)); } if (!(si.sym_info is common_method_node) && !(si.sym_info is compiled_function_node)) { throw new NameInBaseClassMustBeMethod(name, get_location(ident)); } common_function_node cfn = si.sym_info as common_function_node;*/ } private List find_in_base(SyntaxTree.inherited_ident ident) { if (context.converted_type == null) { AddError(get_location(ident), "INHERITED_EXPECTED_IN_CLASS"); } if (context.converted_type.base_type == null) { AddError(get_location(ident), "NO_BASE_CLASS_DEFINED_BUT_INHERITED_MEET"); } string name = ident.name; if (string.IsNullOrEmpty(name)) name = context.converted_func_stack.Last().name; List sil = context.converted_type.base_type.find_in_type(name, context.CurrentScope); if (sil == null) { sil = context.converted_namespace.find(name); if (sil != null) AddError(get_location(ident), "CLASS_MEMBER_{0}_EXPECTED", name); else AddError(new UndefinedNameReference(name, get_location(ident))); } return sil; } private addressed_expression inherited_ident_address_reciving(SyntaxTree.inherited_ident _ident) { List sil = find_in_base(_ident); return ident_address_reciving(sil?.FirstOrDefault(), _ident); } private addressed_expression ident_address_reciving(SyntaxTree.ident _ident) { if ((context.converting_block() == block_type.function_block) && (context.top_function.return_variable != null)) { List sil = context.top_function.scope.FindOnlyInScope(_ident.name); // почему-то не находит локальную переменную с этим именем // тут баг #2401 // context.find_only_in_namespace(_ident.name); // это было закомментировано 10.01.21 if (sil == null) { int comp = SystemLibrary.SystemLibrary.string_comparer.Compare(_ident.name, context.top_function.name); if (comp == 0) // мы нашли функцию и ее имя совпадает с ident { List mysi = context.find(_ident.name); if (mysi != null && mysi[0].sym_info is function_node) { local_variable lv = context.top_function.return_variable; return new local_variable_reference(lv, 0, get_location(_ident)); } } } } List idsi = context.find(_ident.name); return ident_address_reciving(idsi?.FirstOrDefault(), _ident); } internal addressed_expression create_variable_reference(definition_node dn, location lloc) { switch (dn.semantic_node_type) { case semantic_node_type.local_variable: { local_variable lv = (local_variable)dn; if (context.converting_block() == block_type.function_block) { return new local_variable_reference(lv, convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(lv.function.scope, context.top_function.scope), lloc); } else if (context.converting_block() == block_type.namespace_block) { return new local_variable_reference(lv, 0, lloc); } else { throw new CompilerInternalError("Invalid block type"); } } case semantic_node_type.namespace_variable: { namespace_variable nv = (namespace_variable)dn; return new namespace_variable_reference(nv, lloc); } case semantic_node_type.class_field: { class_field cf = (class_field)dn; if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static) { return new static_class_field_reference(cf, lloc); } expression_node obj = GetCurrentObjectReference(cf.cont_type.Scope,cf, lloc); //new this_node(context.converted_type, lloc); return new class_field_reference(cf, obj, lloc); } case semantic_node_type.common_parameter: { if (context.in_parameters_block) AddError(new ParameterReferenceInDefaultParameterNotAllowed(lloc)); common_parameter cpar = (common_parameter)dn; return new common_parameter_reference(cpar, convertion_data_and_alghoritms.symbol_table.GetRelativeScopeDepth(cpar.common_function.scope, context.top_function.scope), lloc); } case semantic_node_type.local_block_variable: { return new local_block_variable_reference((local_block_variable)dn, lloc); } case semantic_node_type.compiled_variable_definition: { compiled_variable_definition cvd = dn as compiled_variable_definition; if (cvd.polymorphic_state == SemanticTree.polymorphic_state.ps_static) return new static_compiled_variable_reference(cvd, lloc); expression_node obj = GetCurrentObjectReference(cvd.cont_type.Scope, cvd, lloc); //new this_node(context.converted_type, lloc); return new compiled_variable_reference(cvd, obj, lloc); } default: throw new NotSupportedError(lloc); } return null; } private expression_node ident_value_reciving(SyntaxTree.ident _ident) { List sil = context.find(_ident.name); return ident_value_reciving(sil, _ident); } private expression_node inherited_message_value_reciving(SyntaxTree.inherited_message _ident) { List sil = find_in_base(_ident); bool constr = false; if (sil != null) if (sil.FirstOrDefault().sym_info is common_method_node) { if ((sil.FirstOrDefault().sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); constr = (sil.FirstOrDefault().sym_info as common_method_node).is_constructor; } else if (sil.FirstOrDefault().sym_info is compiled_function_node) { if ((sil.FirstOrDefault().sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); } else if (sil.FirstOrDefault().sym_info is compiled_constructor_node) { constr = true; } location loc = get_location(_ident); function_node fn = sil.FirstOrDefault().sym_info as function_node; base_function_call bfc = null; common_function_node cfn = context.converted_func_stack.Last(); int depth = context.converted_func_stack.Count-1; if (!constr) { if (fn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { bfc = create_not_static_method_call(fn,new this_node(context.converted_type,loc),loc,true); if (bfc is common_method_call) (bfc as common_method_call).virtual_call = false; else (bfc as compiled_function_call).virtual_call = false; } else if (fn is common_method_node) bfc = create_static_method_call(fn,loc,(fn as common_method_node).cont_type,true); else if (fn is compiled_function_node) bfc = create_static_method_call(fn,loc,(fn as compiled_function_node).cont_type,true); else throw new NotSupportedError(loc); } else { if (!context.allow_inherited_ctor_call && !context.can_call_inherited_ctor_call(convertion_data_and_alghoritms.statement_list_stack_first())) AddError(loc, "INHERITED_CONSTRUCTOR_CALL_MUST_BE_FIRST"); expressions_list exprs = new expressions_list(); foreach (common_parameter cp in cfn.parameters) { exprs.AddElement(new common_parameter_reference(cp,depth,loc)); } if (fn is common_method_node) { common_constructor_call ccc = create_constructor_call((fn as common_method_node).cont_type,exprs,loc, null, true) as common_constructor_call; ccc._new_obj_awaited = false; return ccc; } else if (fn is compiled_constructor_node) { compiled_constructor_call ccc = create_constructor_call((fn as compiled_constructor_node).compiled_type,exprs,loc, null, true) as compiled_constructor_call; ccc._new_obj_awaited = false; return ccc; } else throw new NotSupportedError(loc); } foreach (common_parameter cp in cfn.parameters) { bfc.parameters.AddElement(new common_parameter_reference(cp,depth,loc)); } return bfc; } private expression_node inherited_ident_value_reciving(SyntaxTree.inherited_ident _ident) { List sil = find_in_base(_ident); if (sil != null) if (sil.FirstOrDefault().sym_info is common_method_node) { if ((sil.FirstOrDefault().sym_info as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); } else if (sil.FirstOrDefault().sym_info is compiled_function_node) { if ((sil.FirstOrDefault().sym_info as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract) AddError(get_location(_ident), "CANNOT_CALL_ABSTRACT_METHOD"); } return ident_value_reciving(sil, _ident); } private semantic_node ident_semantic_reciving(SyntaxTree.ident _ident) { List si_left = context.find(_ident.name); return ident_semantic_reciving(si_left, _ident); } private semantic_node inherited_ident_semantic_reciving(SyntaxTree.inherited_ident _ident) { List sil = find_in_base(_ident); return ident_semantic_reciving(sil, _ident); } private semantic_node ident_semantic_reciving(List si_left, SyntaxTree.ident _ident) { //SymbolInfo si_left=blocks.find(_ident.name); location lloc = get_location(_ident); if (si_left == null) { AddError(new UndefinedNameReference(_ident.name, lloc)); } definition_node dn = context.check_name_node_type(_ident.name, si_left?.FirstOrDefault(), get_location(_ident), general_node_type.constant_definition, general_node_type.function_node, general_node_type.namespace_node, general_node_type.property_node, general_node_type.type_node, general_node_type.variable_node, general_node_type.unit_node); switch (dn.general_node_type) { case general_node_type.constant_definition: case general_node_type.function_node: case general_node_type.property_node: case general_node_type.variable_node: { return ident_value_reciving(si_left, _ident); } case general_node_type.namespace_node: { //throw new CompilerInternalError("Unsupported now."); return dn; } case general_node_type.type_node: { type_node tn = dn as type_node; //dot_node_as_type_ident(tn,id_right,mot); return tn; } case general_node_type.unit_node: { //throw new CompilerInternalError("Unsupproted now."); //throw new NotSupportedError(get_location(_ident)); return dn; } } return null; } public override void visit(SyntaxTree.ident _ident) { if (_ident.name.IndexOf('.') != -1) { var arr = _ident.name.Split('.'); var dn = new dot_node(new ident(_ident.name.Substring(0, _ident.name.LastIndexOf('.')), _ident.source_context), new ident(arr[arr.Length - 1], _ident.source_context)); dn.visit(this); return; } var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: return_addressed_value(ident_address_reciving(_ident)); break; case motivation.expression_evaluation: return_value(ident_value_reciving(_ident)); break; //case motivation.symbol_info_reciving: return_symbol_value(blocks.find(_ident.name));break; case motivation.semantic_node_reciving: return_semantic_value(ident_semantic_reciving(_ident)); break; default: throw new NotSupportedError(get_location(_ident)); } return; } public override void visit(SyntaxTree.subprogram_body _subprogram_body) { throw new NotSupportedError(get_location(_subprogram_body)); } public override void visit(SyntaxTree.statement _statement) { throw new NotSupportedError(get_location(_statement)); } public override void visit(SyntaxTree.double_const _double_const) { expression_node en = new double_const_node(_double_const.val, get_location(_double_const)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: throw new CompilerInternalError("Addres receiving from constant"); case motivation.expression_evaluation: return_value(en); break; case motivation.semantic_node_reciving: return_semantic_value(en); break; } //return_value(en); return; } public override void visit(SyntaxTree.bigint_const bi) { var names = new List { new ident("System"), new ident("Numerics"), new ident("BigInteger") }; var ntr = new named_type_reference(names, bi.source_context); var ne = new new_expr(ntr, new expression_list(new uint64_const(bi.val)),bi.source_context); visit(ne); } public override void visit(SyntaxTree.int32_const int32) { //таблица целых констант на уровне синтаксиса // - 0 + // 32--------16----8----|----8----16--------32----------------64(bits) // [ int64 )[ int32 ]( int64 ]( uint64 ] //таблица целых констант на уровне семантики(???) // - 0 + // 32--------16----8----|----8----16--------32----------------64(bits) // [ long )[ int )[byte](int]( long ]( ulong ] //Отлюченно временно (из-за ошибок временно алгоритмах выбора оперетора?) /*if(int32.val>=byte.MinValue && int32.val<=byte.MaxValue) return_value(new byte_const_node((byte)int32.val, get_location(int32))); else*/ expression_node en = null; /* if ((int32.val >= byte.MinValue) && (int32.val <= byte.MaxValue)) { en = new byte_const_node((byte)int32.val, get_location(int32)); } else { en = new int_const_node(int32.val, get_location(int32)); } */ en = SystemLibrary.static_executors.make_int_const(int32.val, get_location(int32)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: throw new CompilerInternalError("Address receiving from constant"); case motivation.expression_evaluation: return_value(en); break; case motivation.semantic_node_reciving: return_semantic_value(en); break; } //return_value(en); return; } public override void visit(SyntaxTree.int64_const int64) { expression_node en = new long_const_node(int64.val, get_location(int64)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: throw new CompilerInternalError("Addres receiving from constant"); case motivation.expression_evaluation: return_value(en); break; case motivation.semantic_node_reciving: return_semantic_value(en); break; } //return_value(en); return; } public override void visit(SyntaxTree.uint64_const uint64) { //TODO добавить обработку // :-) //throw new CompilerInternalError("Числа UInt64 доступны только в PascalABC.NET Professional Edition"); expression_node en = new ulong_const_node(uint64.val, get_location(uint64)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: throw new CompilerInternalError("Addres receiving from constant"); case motivation.expression_evaluation: return_value(en); break; case motivation.semantic_node_reciving: return_semantic_value(en); break; } return; } public override void visit(SyntaxTree.bool_const _bool_const) { expression_node en = new bool_const_node(_bool_const.val, get_location(_bool_const)); var mot = motivation_keeper.motivation; motivation_keeper.reset(); switch (mot) { case motivation.address_receiving: throw new CompilerInternalError("Address receiving from constant"); case motivation.expression_evaluation: return_value(en); break; case motivation.semantic_node_reciving: return_semantic_value(en); break; } //return_value(en); return; } public override void visit(SyntaxTree.const_node _const_node) { throw new NotSupportedError(get_location(_const_node)); } public override void visit(SyntaxTree.un_expr _un_expr) { expression_node exp = convert_strong(_un_expr.subnode); expression_node res = find_operator(_un_expr.operation_type, exp, get_location(_un_expr)); return_value(res); } public override void visit(SyntaxTree.bin_expr _bin_expr) { expression_node left = convert_strong(_bin_expr.left); expression_node right = convert_strong(_bin_expr.right); // SSM 04/12/24 - массивы нельзя умножать и вычитать. Это запрещено т.к. в библиотеку добавлены arr * set и arr - set if (left.type != null && left.type.type_special_kind == type_special_kind.array_kind && right.type != null && right.type.type_special_kind == type_special_kind.array_kind && (_bin_expr.operation_type == Operators.Multiplication || _bin_expr.operation_type == Operators.Minus) ) { AddError(get_location(_bin_expr), "OPERATOR_{0}_CAN_NOT_BE_APPLIED_TO_TYPES_{1}_AND_{2}", name_reflector.get_name(_bin_expr.operation_type), left.type, right.type); } if (_bin_expr.operation_type == Operators.In) try_convert_typed_expression_to_function_call(ref left); expression_node res = find_operator(_bin_expr.operation_type, left, right, get_location(_bin_expr)); if (res.type is undefined_type) AddError(get_location(_bin_expr), "OPERATOR_RETURN_TYPE_UNDEFINED_{0}", name_reflector.get_name(_bin_expr.operation_type)); if (res.type.type_special_kind == SemanticTree.type_special_kind.base_set_type) { if (left.type.element_type == right.type.element_type) res.type = left.type; else if (type_table.compare_types(left.type, right.type) == type_compare.greater_type) res.type = left.type; else if (type_table.compare_types(left.type, right.type) == type_compare.less_type) res.type = right.type; else if (type_table.compare_types(left.type, right.type) == type_compare.non_comparable_type) res.type = context.create_set_type(SystemLibrary.SystemLibrary.object_type, get_location(_bin_expr)); } //ssyy, 15.05.2009 switch (_bin_expr.operation_type) { case PascalABCCompiler.SyntaxTree.Operators.Equal: case PascalABCCompiler.SyntaxTree.Operators.NotEqual: if (left.type.is_generic_parameter && right.type.is_generic_parameter) { compiled_static_method_call cfc = new compiled_static_method_call( SystemLibrary.SystemLibrary.object_equals_method, get_location(_bin_expr)); cfc.parameters.AddElement(left); cfc.parameters.AddElement(right); if (_bin_expr.operation_type == PascalABCCompiler.SyntaxTree.Operators.NotEqual) { res = new basic_function_call(SystemLibrary.SystemLibrary.bool_not as basic_function_node, get_location(_bin_expr), cfc); } else { res = cfc; } } else if (left is static_event_reference) { if ((left as static_event_reference).en is compiled_event) AddError(left.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (left as static_event_reference).en.name); type_node eventContainingType = ((left as static_event_reference).en as common_event).cont_type; // context.converted_type содержит generic definition, если это generic тип // поэтому берём original_generic при необходимости if (eventContainingType.is_generic_type_instance) eventContainingType = eventContainingType.original_generic; if (context.converted_type != null && context.converted_type != eventContainingType && !context.converted_type.name.Contains("<>local_variables_class") ) AddError(left.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (left as static_event_reference).en.name); } else if (right is static_event_reference) { if ((right as static_event_reference).en is compiled_event) AddError(right.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (right as static_event_reference).en.name); if (context.converted_type != null && context.converted_type != ((right as static_event_reference).en as common_event).cont_type) AddError(right.location, "EVENT_{0}_MUST_BE_IN_LEFT_PART", (right as static_event_reference).en.name); } break; } return_value(res); } private void check_property_no_params(property_node pn, location loc) { if (pn.parameters.Count != 0) { AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pn.name); } } private void check_property_params(static_property_reference pr, location loc) { if (pr.property.parameters.Count != pr.fact_parametres.Count) { AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pr.property.name); } } private void check_property_params(non_static_property_reference pr, location loc) { if (pr.property.parameters.Count != pr.fact_parametres.Count) { AddError(loc, "PROPERTY_{0}_REFERENCE_WITH_INVALID_PARAMS_COUNT", pr.property.name); } } private SyntaxTree.procedure_call ConvertEventOperationToProcedureCall(SyntaxTree.assign _assign) { SyntaxTree.ident event_name = _assign.to as SyntaxTree.ident; SyntaxTree.dot_node dot = _assign.to as SyntaxTree.dot_node; if (dot != null) event_name = dot.right as SyntaxTree.ident; if (event_name == null) AddError(new EventNameExpected(get_location(_assign.to))); string format; if (_assign.operator_type == PascalABCCompiler.SyntaxTree.Operators.AssignmentSubtraction) format = StringConstants.event_remove_method_nameformat; else format = StringConstants.event_add_method_nameformat; SyntaxTree.ident add_name = new SyntaxTree.ident(string.Format(format, event_name.name)); add_name.source_context = event_name.source_context; if (dot != null) dot.right = add_name; SyntaxTree.expression_list exprlist = new SyntaxTree.expression_list(); exprlist.expressions.Add(_assign.from); exprlist.source_context = _assign.to.source_context; SyntaxTree.method_call add_methcall = new SyntaxTree.method_call(exprlist); if (dot != null) add_methcall.dereferencing_value = dot; else add_methcall.dereferencing_value = add_name; add_methcall.source_context = _assign.source_context; SyntaxTree.procedure_call add_proccall = new SyntaxTree.procedure_call(add_methcall); add_proccall.source_context = _assign.source_context; return add_proccall; } private SyntaxTree.procedure_call ConvertOperatorToProcedureCall(SyntaxTree.assign _assign) { SyntaxTree.ident operator_name = new PascalABCCompiler.SyntaxTree.ident(name_reflector.get_name(_assign.operator_type)); operator_name.source_context = _assign.to.source_context; SyntaxTree.dot_node dot = new PascalABCCompiler.SyntaxTree.dot_node(_assign.to, operator_name); dot.source_context = _assign.to.source_context; SyntaxTree.expression_list exprlist = new SyntaxTree.expression_list(); exprlist.expressions.Add(_assign.from); exprlist.source_context = _assign.to.source_context; SyntaxTree.method_call add_methcall = new SyntaxTree.method_call(exprlist); add_methcall.dereferencing_value = dot; add_methcall.source_context = _assign.source_context; SyntaxTree.procedure_call add_proccall = new SyntaxTree.procedure_call(add_methcall); add_proccall.source_context = _assign.source_context; return add_proccall; } private expression_node ConstructDecExpr(expression_node en, location loc) { int_const_node one = new int_const_node(1, loc); return find_operator(SyntaxTree.Operators.Minus, en, one, loc); } private void check_field_reference_for_assign(class_field_reference expr, location loc) { if (expr.obj is namespace_constant_reference || expr.obj is function_constant_reference) AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); else if (expr.obj is class_field_reference) check_field_reference_for_assign(expr.obj as class_field_reference,loc); else if (expr.obj is simple_array_indexing) check_expression_for_assign((expr.obj as simple_array_indexing).simple_arr_expr,loc); } private void check_expression_for_assign(expression_node expr, location loc) { if (expr is namespace_constant_reference || expr is function_constant_reference) AddError(loc, "LEFT_SIDE_CANNOT_BE_ASSIGNED_TO"); else if (expr is class_field_reference) check_field_reference_for_assign(expr as class_field_reference,loc); else if (expr is simple_array_indexing) check_expression_for_assign((expr as simple_array_indexing).simple_arr_expr,loc); } public override void visit(SyntaxTree.expression _expression) { throw new NotSupportedError(get_location(_expression)); } public void visit_statement_list_internal(SyntaxTree.statement_list _statement_list) { statements_list stl = new statements_list(get_location(_statement_list), get_location_with_check(_statement_list.left_logical_bracket), get_location_with_check(_statement_list.right_logical_bracket)); for (var i = 0; i < _statement_list.subnodes.Count; i++) // SSM 13.10.16 - поменял т.к. собираюсь менять узлы в процессе обхода { statement syntax_statement = _statement_list.subnodes[i]; try { statement_node semantic_statement = convert_strong(syntax_statement); if (semantic_statement != null) { if (stl.statements.Count > 0 && stl.statements[0] is basic_function_call && i == 2) { base_function_call bfc = stl.statements[0] as basic_function_call; if (bfc.type != null && bfc.type.name.Contains("<>local_variables_class") && (semantic_statement is compiled_constructor_call || semantic_statement is common_constructor_call) && context.converted_func_stack.Count > 0 && context.converted_func_stack.Peek() is common_method_node && (context.converted_func_stack.Peek() as common_method_node).is_constructor) stl.statements.AddElementFirst(semantic_statement); else stl.statements.AddElement(semantic_statement); } else stl.statements.AddElement(semantic_statement); } context.allow_inherited_ctor_call = false; } catch (Errors.Error ex) { if (ThrowCompilationError || ex is MemberIsNotDeclaredInType || ex is UndefinedNameReference)//TODO: add interface throw ex; else ErrorsList.Add(ex); } } return_value(stl); } public override void visit(SyntaxTree.statement_list _statement_list) { if (_statement_list.IsInternal) // можно два if поставить перед push и pop здесь!!! { visit_statement_list_internal(_statement_list); return; } #region MikhailoMMX, обработка omp parallel section bool isGenerateParallel = false; bool isGenerateSequential = true; if (OpenMP.SectionsFound) //если в программе есть хоть одна директива parallel sections - проверяем: if (DirectivesToNodesLinks.ContainsKey(_statement_list) && OpenMP.IsParallelSectionsDirective(DirectivesToNodesLinks[_statement_list])) { //перед этим узлом есть директива parallel sections if (CurrentParallelPosition == ParallelPosition.Outside) //входим в самый внешний параллельный sections { var f = _statement_list.DescendantNodes().OfType().FirstOrDefault(); if (f != null) AddError(get_location(f), "OPENMP_CONTROLLED_CONSTRUCTIONS_CANNOT_CONTAIN_LAMBDAS"); //сгенерировать сначала последовательную ветку, затем параллельную //устанавливаем флаг и продолжаем конвертирование, считая, что конвертируем последовательную ветку isGenerateParallel = true; CurrentParallelPosition = ParallelPosition.InsideSequential; //в конце за счет флага вернем состояние обратно и сгенерируем и параллельную ветку тоже } else //уже генерируем одну из веток if (CurrentParallelPosition == ParallelPosition.InsideParallel) { isGenerateParallel = true; isGenerateSequential = false; } //else //флаг isGenerateParallel не установлен, параллельная ветка не сгенерируется } #endregion statements_list stl = new statements_list(get_location(_statement_list), get_location_with_check(_statement_list.left_logical_bracket), get_location_with_check(_statement_list.right_logical_bracket)); convertion_data_and_alghoritms.statement_list_stack_push(stl); for (var i = 0; i < _statement_list.subnodes.Count; i++) // SSM 13.10.16 - поменял т.к. собираюсь менять узлы в процессе обхода { statement syntax_statement = _statement_list.subnodes[i]; try { if (for_intellisense) { if (syntax_statement is assign && !(context.converted_func_stack.FirstOrDefault() != null && context.converted_func_stack.Peek().return_value_type is undefined_type) || syntax_statement is procedure_call || syntax_statement is raise_statement) { if (lambdaProcessingState != LambdaProcessingState.TypeInferencePhase && !(new LambdaSearcher(syntax_statement).CheckIfContainsLambdas())) continue; } } statement_node semantic_statement = convert_strong(syntax_statement); if (semantic_statement != null) { if (stl.statements.Count > 0 && stl.statements[0] is basic_function_call && i == 2) { base_function_call bfc = stl.statements[0] as basic_function_call; if (bfc.type != null && bfc.type.name.Contains("<>local_variables_class") && (semantic_statement is compiled_constructor_call && !(semantic_statement as compiled_constructor_call).new_obj_awaited() || semantic_statement is common_constructor_call && !(semantic_statement as common_constructor_call).new_obj_awaited()) && context.converted_func_stack.Count > 0 && context.converted_func_stack.Peek() is common_method_node && (context.converted_func_stack.Peek() as common_method_node).is_constructor) stl.statements.AddElementFirst(semantic_statement); else stl.statements.AddElement(semantic_statement); } else stl.statements.AddElement(semantic_statement); } context.allow_inherited_ctor_call = false; } catch (Errors.Error ex) { if (ex is CompilationErrorWithLocation && (ex as CompilationErrorWithLocation).loc == null) (ex as CompilationErrorWithLocation).loc = get_location(syntax_statement); if (!for_intellisense && (ThrowCompilationError || ex is MemberIsNotDeclaredInType || ex is UndefinedNameReference))//TODO: add interface throw ex; else ErrorsList.Add(ex); } catch (Exception ex) { if (!for_intellisense) throw ex; } } convertion_data_and_alghoritms.statement_list_stack.Pop(); #region MikhailoMMX, обработка omp parallel sections //флаг был установлен только если это самый внешний parallel sections и нужно сгенерировать обе ветки //или если это вложенный parallel sections, нужно сгенерировать обе ветки, но без проверки на OMP_Available //Последовательная ветка только что сгенерирована, теперь меняем состояние и генерируем параллельную if (isGenerateParallel) { CurrentParallelPosition = ParallelPosition.InsideParallel; statements_list omp_stl = OpenMP.TryConvertSections(stl, _statement_list, this); CurrentParallelPosition = ParallelPosition.Outside; if (omp_stl != null) { return_value(omp_stl); return; } } #endregion return_value(stl); } public override void visit(SyntaxTree.syntax_tree_node _tree_node) { throw new NotSupportedError(get_location(_tree_node)); } private bool has_dll_import_attribute(common_function_node cfn) { foreach (attribute_node attr in cfn.attributes) { if (attr.attribute_type == SystemLibrary.SystemLibrary.dllimport_type) return true; } return false; } private bool is_pinvoke(SyntaxTree.proc_block bl) { if (bl is SyntaxTree.external_directive) { return true; } return false; } private attribute_node get_dll_import_attribute(common_function_node cfn) { foreach (attribute_node attr in cfn.attributes) { if (attr.attribute_type == SystemLibrary.SystemLibrary.dllimport_type) return attr; } return null; } public override void visit(SyntaxTree.external_directive _external_directive) { string module_name = ""; string name = ""; if (context.converted_func_stack.Count > 1) AddError(context.top_function.loc, "EXTERNAL_METHOD_CANNOT_BE_NESTED"); if (context.converted_func_stack.Peek() is common_method_node && (context.converted_func_stack.Peek() as common_method_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(context.top_function.loc, "EXTERNAL_METHOD_SHOULD_BE_STATIC"); if (context.converted_func_stack.Peek().is_generic_function) AddError(context.top_function.loc, "EXTERNAL_METHOD_CANNOT_BE_GENERIC"); if (context.converted_func_stack.Peek() is common_method_node && (context.converted_func_stack.Peek() as common_method_node).common_comprehensive_type.is_generic_type_definition) AddError(context.top_function.loc, "EXTERNAL_METHOD_CANNOT_BE_DECLARED_IN_GENERIC_TYPE"); if (_external_directive.modulename == null) { if (!has_dll_import_attribute(context.top_function)) { AddError(context.top_function.loc, "FUNCTION_MUST_HAVE_DLLIMPORT_ATTRIBUTE"); } else { location loc2 = get_location(_external_directive); pinvoke_statement pinv_stmt = new pinvoke_statement(loc2); //statement_node_list sal = new statement_node_list(loc); //sal.AddElement(ext_stmt); statements_list sl2 = new statements_list(loc2); sl2.statements.AddElement(pinv_stmt); //return_value(sl); context.code = sl2; return; } } if (has_dll_import_attribute(context.top_function)) { AddError(get_location(_external_directive.modulename), "FUNCTION_MUST_HAVE_ONLY_EXTERNAL_STATEMENT"); } if (_external_directive.modulename is SyntaxTree.string_const) { module_name = ((SyntaxTree.string_const)_external_directive.modulename).Value; } else if (_external_directive.modulename is SyntaxTree.ident) { //throw new CompilerInternalError("Unsupported now"); //throw new NotSupportedError(get_location(_external_directive)); expression_node en = convert_strong(_external_directive.modulename as SyntaxTree.ident); if (en is string_const_node) module_name = (en as string_const_node).constant_value; else AddError(get_location(_external_directive.modulename), "STRING_CONSTANT_EXPECTED"); } else AddError(get_location(_external_directive.modulename), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED"); if (string.IsNullOrEmpty(module_name)) AddError(get_location(_external_directive.modulename), "DLLNAME_CANNOT_BE_EMPTY"); if (_external_directive.name == null) { name = context.converted_func_stack.Peek().name; } else if (_external_directive.name is SyntaxTree.string_const) { name = ((SyntaxTree.string_const)_external_directive.name).Value; } else if (_external_directive.name is SyntaxTree.ident) { expression_node en = convert_strong(_external_directive.name as SyntaxTree.ident); if (en is string_const_node) name = (en as string_const_node).constant_value; else AddError(get_location(_external_directive.name), "STRING_CONSTANT_EXPECTED"); } else { //throw new CompilerInternalError("Unsupported now"); AddError(get_location(_external_directive.name), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED"); } location loc = get_location(_external_directive); external_statement ext_stmt = new external_statement(module_name, name, loc); //statement_node_list sal = new statement_node_list(loc); //sal.AddElement(ext_stmt); statements_list sl = new statements_list(loc); sl.statements.AddElement(ext_stmt); //return_value(sl); context.code = sl; } public override void visit(SyntaxTree.unit_or_namespace _name_space) { throw new NotSupportedError(get_location(_name_space)); } public override void visit(SyntaxTree.using_list _using_list) { throw new NotSupportedError(get_location(_using_list)); } public override void visit(SyntaxTree.jump_stmt _return_stmt) { if (_return_stmt.JumpType != PascalABCCompiler.SyntaxTree.JumpStmtType.Return) { throw new NotSupportedError(get_location(_return_stmt)); } if (_return_stmt.expr == null) { if (context.top_function.return_value_type != null && context.top_function.return_value_type != SystemLibrary.SystemLibrary.void_type) { AddError(get_location(_return_stmt), "FUNCTION_SHOULD_RETURN_VALUE"); ret.return_value(new empty_statement(null)); return; } ret.return_value(new return_node(null, null)); } else { type_node rettype = context.top_function.return_value_type; if (rettype == null || rettype == SystemLibrary.SystemLibrary.void_type) { AddError(get_location(_return_stmt.expr), "FUNCTION_SHOULD_NOT_RETURN_VALUE"); ret.return_value(new empty_statement(null)); return; } expression_node en = convert_strong(_return_stmt.expr); en = convertion_data_and_alghoritms.convert_type(en, rettype); ret.return_value(new return_node(en, get_location(_return_stmt.expr))); } } public override void visit(SyntaxTree.loop_stmt _loop_stmt) { throw new NotSupportedError(get_location(_loop_stmt)); } private bool IsGetEnumerator(type_node tn, ref type_node elem_type) { if (tn == null || tn is null_type_node || tn.ImplementingInterfaces == null) return false; compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(StringConstants.IEnumerableInterfaceName)); if (tn == ctn) return true; foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) { if (itn == ctn) { elem_type = tn.element_type; if (elem_type != null) return true; function_node get_enumerator_func = null; List sil = ctn.find_in_type(StringConstants.GetEnumeratorMethodName); if(sil != null) foreach(SymbolInfo si in sil) { if (get_enumerator_func != null) break; get_enumerator_func = si.sym_info as function_node; if (get_enumerator_func.parameters.Count == 0) break; get_enumerator_func = null; } elem_type = (get_enumerator_func.return_value_type.find_first_in_type(StringConstants.CurrentPropertyName).sym_info as property_node).get_function.return_value_type; return true; } } return false; } private bool IsIEnumerableInterface(Type t) { var IEnumType = typeof(IEnumerable); var IEnumTypedType = typeof(IEnumerable<>); var isIEnumType = (t == IEnumType); var isIEnumTypedType = t.IsGenericType && (t.GetGenericTypeDefinition() == IEnumTypedType ); return isIEnumType || isIEnumTypedType; } private bool IsIEnumeratorInterface(Type t) { var IEnumType = typeof(IEnumerator); var IEnumTypedType = typeof(IEnumerator<>); var isIEnumType = (t == IEnumType); var isIEnumTypedType = t.IsGenericType && (t.GetGenericTypeDefinition() == IEnumTypedType ); return isIEnumType || isIEnumTypedType; } private Type ChooseIEnumerableInterfaceInCompiledType(Type compiledType) { var IEnumType = typeof(IEnumerable); var IEnumTypedType = typeof(IEnumerable<>); // если тип является интерфейсом IEnumerable или IEnumerable то берём его if (IsIEnumerableInterface(compiledType)) return compiledType; // иначе ищем подходящие интерфейсы в иерархии var filteredInterfaces = compiledType.FindInterfaces( (item, _) => IsIEnumerableInterface(item), null ); var genericInterfaceCount = filteredInterfaces.Count(item => item.IsGenericType); if (compiledType.IsInterface) { // интерфейс наследует несколько IEnumerable с разными T // невозможно выбрать. требуется явное приведение if (genericInterfaceCount > 1) return null; if (genericInterfaceCount == 1) return filteredInterfaces.First(item => item.IsGenericType); else return IEnumType; } // для класса/записи необходимо учитывать явные реализации GetEnumerator var methods = compiledType.GetMethods().Where(item => item.Name == "GetEnumerator" && item.GetParameters().Length == 0 && IsIEnumeratorInterface(item.ReturnType) ).ToArray(); switch (methods.Length) { case 0: // тип реализует явно несколько IEnumerable // невозможно выбрать. требуется явное приведение if (genericInterfaceCount > 1) return null; // тип реализует и IEnumerable и IEnumerable явно // выбираем IEnumerable if (genericInterfaceCount == 1) return filteredInterfaces.First(item => item.IsGenericType); // явно реализует IEnumerable else return IEnumType; case 1: var method = methods[0]; if (!method.ReturnType.IsGenericType) return IEnumType; else { var elementType = method.ReturnType.GetGenericArguments().First(); return IEnumTypedType.MakeGenericType(elementType); } default: // в типе наследнике перекрыли GetEnumerator // невозможно точно выбрать метод return null; } } private bool IsIEnumerableInterface(type_node t) { compiled_type_node orig; if (t is compiled_type_node) orig = t as compiled_type_node; else if (t is compiled_generic_instance_type_node) orig = (t as compiled_generic_instance_type_node).original_generic as compiled_type_node; else return false; return IsIEnumerableInterface(orig.compiled_type); } /// /// Собирает интерфейсы, реализованные типом и его предками /// private IEnumerable CollectInterfacesFromTypeNode(type_node node) { do { foreach (var item in node.ImplementingInterfaces) yield return (type_node)item; node = node.base_type; } while (node != null); } private bool IsIEnumeratorInterface(type_node t) { compiled_type_node orig; if (t is compiled_type_node) orig = t as compiled_type_node; else if (t is compiled_generic_instance_type_node) orig = (t as compiled_generic_instance_type_node).original_generic as compiled_type_node; else return false; return IsIEnumeratorInterface(orig.compiled_type); } private type_node ChooseIEnumerableInterfaceInTypeNode(type_node node) { var IEnumType = compiled_type_node.get_type_node( typeof(IEnumerable) ); var IEnumTypedType = compiled_type_node.get_type_node( typeof(IEnumerable<>) ); var filteredInterfaces = CollectInterfacesFromTypeNode(node) .Where(item => IsIEnumerableInterface(item)) .ToArray(); var genericInterfaceCount = filteredInterfaces.Count(item => item.is_generic_type_instance); if (node.IsInterface) { // интерфейс наследует несколько IEnumerable с разными T // невозможно выбрать. требуется явное приведение if (genericInterfaceCount > 1) return null; if (genericInterfaceCount == 1) return filteredInterfaces.First(item => item.is_generic_type_instance); else return IEnumType; } var commonType = (common_type_node)node; var methods = commonType.methods.Where(item => item.name.Equals("GetEnumerator", StringComparison.OrdinalIgnoreCase) && item.parameters.Count == 0 && IsIEnumeratorInterface(item.return_value_type) ).ToArray(); switch (methods.Length) { case 0: // тип реализует явно несколько IEnumerable // невозможно выбрать. требуется явное приведение if (genericInterfaceCount > 1) return null; // тип реализует и IEnumerable и IEnumerable явно // выбираем IEnumerable if (genericInterfaceCount == 1) return filteredInterfaces.First(item => item.is_generic_type_instance); // явно реализует IEnumerable else return IEnumType; case 1: var method = methods[0]; if (!method.return_value_type.is_generic_type_instance) return IEnumType; else return IEnumTypedType.get_instance(method.return_value_type.instance_params); default: // в типе наследнике перекрыли GetEnumerator // невозможно точно выбрать метод return null; } } private type_node RestoreTypesInGeneric(Type orig, IList genericArgs) { if (!orig.IsGenericType) throw new InvalidOperationException(); var actualTypes = new List(); foreach (var declaredType in orig.GetGenericArguments()) { type_node actualType; if (declaredType.IsGenericParameter) actualType = genericArgs[declaredType.GenericParameterPosition]; else if (declaredType.IsGenericType) actualType = RestoreTypesInGeneric(declaredType, genericArgs); else actualType = compiled_type_node.get_type_node(declaredType); actualTypes.Add(actualType); } var result = compiled_type_node.get_type_node( orig.GetGenericTypeDefinition() ); return result.get_instance(actualTypes); } public bool FindIEnumerableElementType(type_node tn, ref type_node elem_type, out bool sys_coll_ienum) { sys_coll_ienum = false; // поиск в типе, объявленном в другой сборке // и тип и типоаргументы объявлены в другой сборке // Dictionary: tn = compiled_type_node // IEnumerable: tn = compiled_type_node // // тип объявлен в другой сборке, а типоаргументы в коде // Dictionary: tn = compiled_generic_instance_type_node // IEnumerable: tn = compiled_generic_instance_type_node (например в generic подпрогамме) if (tn is compiled_type_node || tn is compiled_generic_instance_type_node) { compiled_type_node orig; if (tn is compiled_type_node) orig = tn as compiled_type_node; else orig = (tn as compiled_generic_instance_type_node).original_generic as compiled_type_node; // непосредственно тип, от котоого разворачивается foreach Type ct = orig.compiled_type; var supportsEnumeration = typeof(IEnumerable).IsAssignableFrom(ct); if (!supportsEnumeration) return false; // для массива if (tn.element_type != null) { elem_type = tn.element_type; if (ct.GetArrayRank() > 1) sys_coll_ienum = true; return true; } // в иных случаях ищем подходящий интерфейс var desiredInterface = ChooseIEnumerableInterfaceInCompiledType(ct); if (desiredInterface == null) return false; // обнаружен IEnumerable if (!desiredInterface.IsGenericType) { elem_type = SystemLibrary.SystemLibrary.object_type; sys_coll_ienum = true; return true; } var foundElementType = desiredInterface.GetGenericArguments().First(); if (tn is compiled_type_node) elem_type = compiled_type_node.get_type_node(foundElementType); else { // для "tn is compiled_generic_instance_type_node" необходимо восстановить стёртые типы // tn.instance_params содержит фактические типоаргументы (их может быть несколько) // чтобы взять нужный, проверяем позицию через .GenericParameterPosition if (foundElementType.IsGenericParameter) { var ind = foundElementType.GenericParameterPosition; elem_type = tn.instance_params[ind]; } else { // значит элемент последовательности сам является generic типом // при чём его типоаргументы могут быть как из tn.instance_params, так и самостоятельными // IEnumerable< IEnumerable > // IEnumerable< Dictionary > // // а также глубоко вложенными IEnumerable< IEnumerable> > elem_type = RestoreTypesInGeneric(foundElementType, tn.instance_params); } } return true; } // поиск в типе, объявленном в коде // также сюда попадают set of T даже если они подтягиваются из библиотеки else { var supportsEnumeration = CollectInterfacesFromTypeNode(tn).Any(IsIEnumerableInterface); if (!supportsEnumeration) return false; // массивы и set of T if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.typed_file) { elem_type = tn.element_type; if ((tn as common_type_node).rank != 1) sys_coll_ienum = true; return true; } var desiredInterface = ChooseIEnumerableInterfaceInTypeNode(tn); if (desiredInterface == null) return false; if (!desiredInterface.is_generic_type_instance) { elem_type = SystemLibrary.SystemLibrary.object_type; sys_coll_ienum = true; } else elem_type = desiredInterface.instance_params[0]; return true; } } public ident GenIdentName() { return new ident(generatedNamesManager.GenerateName("$GenId")); } public override void visit(SyntaxTree.addressed_value_funcname _addressed_value_funcname) { throw new NotSupportedError(get_location(_addressed_value_funcname)); } public override void visit(SyntaxTree.named_type_reference_list _named_type_reference_list) { throw new NotSupportedError(get_location(_named_type_reference_list)); } public override void visit(SyntaxTree.template_param_list _template_param_list) { throw new NotSupportedError(get_location(_template_param_list)); } public override void visit(double_question_node node) { expression_node condition = convert_strong(node.left); convertion_data_and_alghoritms.convert_type(new null_const_node(null_type_node.get_type_node(), condition.location), condition.type); expression_node left = condition; expression_node right = convert_strong(node.right); if (condition is null_const_node) convertion_data_and_alghoritms.convert_type(new null_const_node(null_type_node.get_type_node(), right.location), right.type); try_convert_typed_expression_to_function_call(ref left); try_convert_typed_expression_to_function_call(ref right); if (left is null_const_node && right.type.is_value_type) { if (right.type is compiled_type_node) { var rt = right.type as compiled_type_node; if (!rt.compiled_type.IsGenericType || rt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) { right = convert_strong(ToNullable(node.right)); } } } else if (right is null_const_node && left.type.is_value_type) { if (left.type is compiled_type_node) { var lt = left.type as compiled_type_node; if (!lt.compiled_type.IsGenericType || lt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) { left = convert_strong(ToNullable(node.left)); } } } /*var typeComparisonResult = type_table.compare_types(left.type, right.type); if (typeComparisonResult == type_compare.greater_type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else left = convertion_data_and_alghoritms.convert_type(left, right.type);*/ if (left is null_const_node) { left = convertion_data_and_alghoritms.convert_type(left, right.type); } else { delegated_methods del_left = left.type as delegated_methods; delegated_methods del_right = right.type as delegated_methods; if (del_left != null && del_right != null && del_left.empty_param_method == null && del_right.empty_param_method == null) { base_function_call bfc = del_left.proper_methods[0]; common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); right = convertion_data_and_alghoritms.explicit_convert_type(right, del); left = convertion_data_and_alghoritms.explicit_convert_type(left, del); } else { var rtl = type_table.get_convertions(right.type, left.type); var ltr = type_table.get_convertions(left.type, right.type); if (ltr.first != null && rtl.first == null) { left = convertion_data_and_alghoritms.convert_type(left, right.type); } else if (ltr.first == null && rtl.first != null) { right = convertion_data_and_alghoritms.convert_type(right, left.type); } else { // если оба типа - целые if (convertion_data_and_alghoritms.is_value_int_type(left.type) && convertion_data_and_alghoritms.is_value_int_type(right.type)) { var lub = convertion_data_and_alghoritms.least_upper_bound_value_int_type(left.type, right.type); if (lub == left.type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else if (lub == right.type) left = convertion_data_and_alghoritms.convert_type(left, right.type); else { right = convertion_data_and_alghoritms.convert_type(right, lub); left = convertion_data_and_alghoritms.convert_type(right, lub); } } else if (left.type == SystemLibrary.SystemLibrary.float_type && right.type == SystemLibrary.SystemLibrary.double_type) left = convertion_data_and_alghoritms.convert_type(left, right.type); else if (right.type == SystemLibrary.SystemLibrary.float_type && left.type == SystemLibrary.SystemLibrary.double_type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else if (left.type == right.type) { } else // Это было - для совместимости. Что-то может не учтено { right = convertion_data_and_alghoritms.convert_type(right, left.type); } } } } //right = convertion_data_and_alghoritms.convert_type(right, left.type); return_value(new double_question_colon_expression(left, right, get_location(node))); } public override void visit(SyntaxTree.question_colon_expression node) { expression_node condition = convert_strong(node.condition); condition = convertion_data_and_alghoritms.convert_type(condition, SystemLibrary.SystemLibrary.bool_type); expression_node left = convert_strong(node.ret_if_true); expression_node right = convert_strong(node.ret_if_false); try_convert_typed_expression_to_function_call(ref left); try_convert_typed_expression_to_function_call(ref right); if (left is null_const_node && right.type.is_value_type) { if (right.type is compiled_type_node) { var rt = right.type as compiled_type_node; if (!rt.compiled_type.IsGenericType || rt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) { right = convert_strong(ToNullable(node.ret_if_false)); } } } else if (right is null_const_node && left.type.is_value_type) { if (left.type is compiled_type_node) { var lt = left.type as compiled_type_node; if (!lt.compiled_type.IsGenericType || lt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) { left = convert_strong(ToNullable(node.ret_if_true)); } } } /*var typeComparisonResult = type_table.compare_types(left.type, right.type); if (typeComparisonResult == type_compare.greater_type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else left = convertion_data_and_alghoritms.convert_type(left, right.type);*/ if (left is null_const_node) { left = convertion_data_and_alghoritms.convert_type(left, right.type); } else { delegated_methods del_left = left.type as delegated_methods; delegated_methods del_right = right.type as delegated_methods; if (del_left != null && del_right != null && (del_left.empty_param_method == null && del_right.empty_param_method == null || del_left.empty_param_method.ret_type == null && del_right.empty_param_method.ret_type == null)) { base_function_call bfc = del_left.proper_methods[0]; common_type_node del = convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); context.converted_namespace.types.AddElement(del); right = convertion_data_and_alghoritms.explicit_convert_type(right, del); left = convertion_data_and_alghoritms.explicit_convert_type(left, del); } else { var rtl = type_table.get_convertions(right.type, left.type); var ltr = type_table.get_convertions(left.type, right.type); if (ltr.first != null && rtl.first == null) { left = convertion_data_and_alghoritms.convert_type(left, right.type); left.type = right.type; } else if (ltr.first == null && rtl.first != null) { right = convertion_data_and_alghoritms.convert_type(right, left.type); right.type = left.type; } else { // если оба типа - целые if (convertion_data_and_alghoritms.is_value_int_type(left.type) && convertion_data_and_alghoritms.is_value_int_type(right.type)) { var lub = convertion_data_and_alghoritms.least_upper_bound_value_int_type(left.type, right.type); if (lub == left.type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else if (lub == right.type) left = convertion_data_and_alghoritms.convert_type(left, right.type); else { right = convertion_data_and_alghoritms.convert_type(right, lub); left = convertion_data_and_alghoritms.convert_type(left, lub); } } else if (left.type == SystemLibrary.SystemLibrary.float_type && right.type == SystemLibrary.SystemLibrary.double_type) left = convertion_data_and_alghoritms.convert_type(left, right.type); else if (right.type == SystemLibrary.SystemLibrary.float_type && left.type == SystemLibrary.SystemLibrary.double_type) right = convertion_data_and_alghoritms.convert_type(right, left.type); else if (left.type == right.type) { } else // Это было - для совместимости. Что-то может не учтено { right = convertion_data_and_alghoritms.convert_type(right, left.type); } } } } //right = convertion_data_and_alghoritms.convert_type(right, left.type); return_value(new question_colon_expression(condition, left, right, get_location(node))); } Dictionary delegate_cache = new Dictionary(); public List visit_type_list(List types) { List tparams = new List(); foreach (SyntaxTree.type_definition id in types) { type_node tn = null; if ((id is function_header || id is procedure_header) && delegate_cache.ContainsKey(id) && !type_synonym_instancing) tn = delegate_cache[id]; else tn = convert_strong(id); if (tn == null) { AddError(get_location(id), "TYPE_NAME_EXPECTED"); } if ((id is function_header || id is procedure_header) && !delegate_cache.ContainsKey(id) && !type_synonym_instancing) { delegate_cache[id] = tn; } tparams.Add(tn); } return tparams; } public List visit_type_list_with_check(List types, List gpe_list, bool where_checking) { List tparams = new List(); foreach (SyntaxTree.type_definition id in types) { type_node tn = convert_strong(id); CompilationErrorWithLocation not_useful = generic_parameter_eliminations.check_type_generic_useful(tn, get_location(id)); if (not_useful != null) { AddError(not_useful); } tparams.Add(tn); } //Проверяем типы на соответствие ограничениям int i; if (where_checking) { CompilationErrorWithLocation err = generic_parameter_eliminations.check_type_list(tparams, gpe_list, false, out i); if (err != null) { err.loc = get_location(types[i]); AddError(err); } } return tparams; } public type_node get_generic_instance(SymbolInfo si, List type_pars) { type_node node = si.sym_info as type_node; compiled_type_node comp_node = node as compiled_type_node; List lgpe = null; if (!context.skip_check_where_sections) { lgpe = (comp_node == null) ? (node as common_type_node).parameters_eliminations : comp_node.parameters_eliminations; } List tparams = visit_type_list_with_check(type_pars, lgpe, !context.skip_check_where_sections); return node.get_instance(tparams); } public SymbolInfo ConvertTypeToInstance(SymbolInfo si, List type_pars, location loc) { if (si == null) return null; template_class tclass = si.sym_info as template_class; if (tclass == null) { generic_indicator gi = si.sym_info as generic_indicator; if (gi != null) { AddError(loc, "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", gi.generic.name, gi.generic.generic_params.Count); } return null; } //Формируем список параметров инстанцирования List tparams = visit_type_list(type_pars); type_node t = instance_any(tclass, tparams, loc); return new SymbolInfo(t); } public override void visit(SyntaxTree.template_type_reference _template_type_reference) { int last_num = _template_type_reference.name.names.Count; string typename = _template_type_reference.name.names[last_num - 1].name; location loc = get_location(_template_type_reference); List sil; List tparams; //Обрабатываем generic-типы int tcount = _template_type_reference.params_list.params_list.Count; string temp_name = _template_type_reference.name.names[last_num - 1].name; if (!_template_type_reference.name.names[last_num - 1].name.Contains(StringConstants.generic_params_infix)) // SSM 26.03.14 _template_type_reference.name.names[last_num - 1].name += StringConstants.generic_params_infix + tcount; sil = context.find_definition_node(_template_type_reference.name, loc); // Временное исправление для однообразной записи синонимов типов в pcu, пока не реализована обработка // объявления обобщенных синонимов типов в visit(type_declaration) EVA 07.03.2026 if (type_synonym_instancing) _template_type_reference.name.names[last_num - 1].name = temp_name; if (sil != null) { type_node rez_type = sil?.FirstOrDefault().sym_info as type_node; foreach (type_definition td in _template_type_reference.params_list.params_list) if (td is named_type_reference && (td as named_type_reference).names.Count > 0 && (td as named_type_reference).names[0].name == "") { return_value(rez_type); return; } rez_type = get_generic_instance(sil?.FirstOrDefault(), _template_type_reference.params_list.params_list); if (context.skip_check_where_sections) { generic_instance_type_node gitn = rez_type as generic_instance_type_node; if (gitn != null) { context.possible_incorrect_instances.Add( new type_instance_and_location(gitn, loc)); } } return_value(rez_type); return; } _template_type_reference.name.names[last_num - 1].name = temp_name; sil = context.find_definition_node(_template_type_reference.name, loc); if (sil == null) { check_possible_generic_names(_template_type_reference.name, loc); AddError(new UndefinedNameReference(typename, loc)); } template_class tclass = sil.FirstOrDefault().sym_info as template_class; if (tclass == null) { generic_indicator gi = sil.FirstOrDefault().sym_info as generic_indicator; if (gi != null) { AddError(get_location(_template_type_reference), "TYPE_{0}_HAS_{1}_GENERIC_PARAMETERS", typename, gi.generic.generic_params.Count); } AddError(get_location(_template_type_reference), "{0}_IS_NOT_TEMPLATE_CLASS", typename); } foreach (type_definition td in _template_type_reference.params_list.params_list) if (td is named_type_reference && (td as named_type_reference).names.Count > 0 && (td as named_type_reference).names[0].name == "") { if (tclass.type_dec.type_def is template_type_reference) { template_type_reference ttr = new template_type_reference((tclass.type_dec.type_def as template_type_reference).name, _template_type_reference.params_list, _template_type_reference.source_context); ttr.names = (tclass.type_dec.type_def as template_type_reference).names; if (ttr.name.names.Count >= 1 && ttr.name.names[ttr.name.names.Count - 1].name.IndexOf('`') != -1) ttr.name.names[ttr.name.names.Count - 1].name = ttr.name.names[ttr.name.names.Count - 1].name.Substring(0, ttr.name.names[ttr.name.names.Count - 1].name.IndexOf('`')); return_value(convert_strong(ttr)); return; } else if (tclass.type_dec.type_def is named_type_reference) { return_value(convert_strong(tclass.type_dec.type_def)); return; } } //Формируем список параметров инстанцирования tparams = visit_type_list(_template_type_reference.params_list.params_list); type_node t = instance_any(tclass, tparams, get_location(_template_type_reference), _template_type_reference); return_value(t); } public type_node instance_any(template_class tc, List template_params, location loc, template_type_reference ttr=null) { common_type_node t = instance(tc, template_params, loc, ttr); if (tc.is_synonym) { return t.fields[0].type; } return t; } bool type_synonym_instancing = false; public common_type_node instance(template_class tc, List template_params, location loc, template_type_reference used_ttr = null) { //Проверяем, что попытка инстанцирования корректна SyntaxTree.class_definition cl_def = tc.type_dec.type_def as SyntaxTree.class_definition; SyntaxTree.template_type_name ttn = tc.type_dec.type_name as SyntaxTree.template_type_name; #if (DEBUG) if (!tc.is_synonym) { if (cl_def == null) { throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No body definition in template class."); } if (cl_def.template_args == null || cl_def.template_args.idents == null) { throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No template arguments in syntax tree."); } } else { if (ttn == null) { throw new PascalABCCompiler.TreeConverter.CompilerInternalError("No template name."); } } #endif List template_formals = (tc.is_synonym) ? ttn.template_args.idents : cl_def.template_args.idents; if (template_formals.Count != ttn.template_args.idents.Count) { AddError(loc, "TEMPLATE_ARGUMENTS_COUNT_MISMATCH"); } if (!tc.is_synonym) { foreach (type_node tnode in template_params) { if (depended_from_generic_parameter(tnode)) { AddError(loc, "TEMPLATES_AND_GENERICS_ARE_INCOMPATIBLE"); } } } //А вдруг такая инстанция уже есть - вернём её string inst_name = tc.CreateTemplateInstance(template_params, loc); List sil = tc.cnn.scope.FindOnlyInScope(inst_name); if (sil != null) { return (common_type_node)sil.FirstOrDefault().sym_info; } //Переходим в место описания шаблона common_namespace_node current_namespace = context.converted_namespace; context.converted_namespace = tc.cnn; common_type_node current_type = context.converted_type; context.converted_type = null; template_class current_template = context.converted_template_type; context.converted_template_type = null; compiled_type_node current_compiled_type = context.converted_compiled_type; context.converted_compiled_type = null; common_function_node_stack current_funk_stack = context.converted_func_stack; context.converted_func_stack = new common_function_node_stack(); //Думаю, это будет работать //DarkStar statement_list_stack statement_list_stack = convertion_data_and_alghoritms.statement_list_stack; convertion_data_and_alghoritms.statement_list_stack = new statement_list_stack(); bool current_cur_meth_not_in_class = current_converted_method_not_in_class_defined; current_converted_method_not_in_class_defined = false; SymbolInfo current_last_created_function = context.last_created_function; context.last_created_function = null; bool current_record_created = _record_created; _record_created = false; SemanticTree.field_access_level current_fal = context.get_field_access_level(); string current_doc = current_document; current_document = tc.cur_document; bool current_body_exists = body_exists; body_exists = false; bool current_allow_inherited_ctor_call = context.allow_inherited_ctor_call; bool current_is_direct_type_decl = is_direct_type_decl; is_direct_type_decl = false; context.allow_inherited_ctor_call = false; bool current_type_section_converting = type_section_converting; type_section_converting = true; SemanticTree.field_access_level curr_fal = context.get_field_access_level(); List current_var_defs = context.var_defs; context.var_defs = new List(); Dictionary current_member_decls = context.member_decls; context.member_decls = new Dictionary(); //подменяем using-список using_namespace_list current_using_list = new using_namespace_list(); foreach (using_namespace un in using_list) { current_using_list.AddElement(un); } using_list.Clear(); foreach (using_namespace un in tc.using_list) { using_list.AddElement(un); } context.converted_type = null; context.enter_code_block_without_bind(); common_type_node ctn; bool interface_creating = false; //Создаём инстанцию шаблона if (tc.is_synonym) { ctn = context.create_type(inst_name, get_location(ttn)); } else { if (cl_def.keyword == SyntaxTree.class_keyword.Record) { ctn = context.create_record_type(get_location(tc.type_dec.type_name), inst_name, generatedNamesManager); } else { interface_creating = (cl_def.keyword == PascalABCCompiler.SyntaxTree.class_keyword.Interface); ctn = context.advanced_create_type(inst_name, get_location(tc.type_dec.type_name), interface_creating); } } ctn.original_template = tc; bool indefinite = false; foreach (type_node tn in template_params) { indefinite = indefinite || tn.depended_from_indefinite; } ctn.SetDependedFromIndefinite(indefinite); tc.instance_params.Add(ctn, template_params); //Ставим в соответствие формальным параметрам шаблона фактические for (int i = 0; i < template_params.Count; i++) { ctn.Scope.AddSymbol(template_formals[i].name, new SymbolInfo(template_params[i])); } //Разбор тела класса if (tc.is_synonym) { Dictionary saved_sc_dict = new Dictionary(); saved_sc_dict.Add(tc.type_dec.type_def, tc.type_dec.type_def.source_context); tc.type_dec.type_def.source_context = loc; if (tc.type_dec.type_def is template_type_reference) { template_type_reference ttr = tc.type_dec.type_def as template_type_reference; for (int i = 0; i < ttr.params_list.params_list.Count; i++) { var prm = ttr.params_list.params_list[i]; saved_sc_dict.Add(prm, prm.source_context); if (used_ttr != null && i < used_ttr.params_list.params_list.Count) prm.source_context = used_ttr.params_list.params_list[i].source_context; else prm.source_context = loc; } } type_synonym_instancing = true; type_node synonym_value = convert_strong(tc.type_dec.type_def); type_synonym_instancing = false; foreach (type_definition td in saved_sc_dict.Keys) td.source_context = saved_sc_dict[td]; ctn.fields.AddElement(new class_field(StringConstants.synonym_value_name, synonym_value, ctn, PascalABCCompiler.SemanticTree.polymorphic_state.ps_static, PascalABCCompiler.SemanticTree.field_access_level.fal_public, null)); } else { if (cl_def.keyword == SyntaxTree.class_keyword.Record) { _record_created = true; } bool tmp_direct = is_direct_type_decl; is_direct_type_decl = true; hard_node_test_and_visit(cl_def); is_direct_type_decl = tmp_direct; //Разбор методов, описанных вне класса if (!interface_creating) { type_section_converting = false; foreach (procedure_definition_info pdi in tc.external_methods) { if (context.converted_namespace != pdi.nspace) { context.converted_namespace = pdi.nspace; using_namespace_list ulist = (pdi.nspace == tc.cnn) ? tc.using_list : tc.using_list2; using_list.Clear(); foreach (using_namespace un in ulist) { using_list.AddElement(un); } template_class.AddUsingListToScope(context.converted_namespace.scope, ulist); } //Заменяем в дереве метода имя шаблонного класса на имя инстанции string tmp_name = pdi.proc.proc_header.name.class_name.name; pdi.proc.proc_header.name.class_name.name = inst_name; hard_node_test_and_visit(pdi.proc); //Обратная замена pdi.proc.proc_header.name.class_name.name = tmp_name; } foreach (common_method_node cmn in ctn.methods) { if (cmn.function_code == null) { //AddError(cmn.loc, "FUNCTION_PREDEFINITION_WITHOUT_DEFINITION"); AddError(new FunctionPredefinitionWithoutDefinition(cmn, cmn.loc)); } } } } //Прыжок обратно context.leave_code_block(); context.converted_namespace = current_namespace; context.converted_type = current_type; context.converted_template_type = current_template; context.set_field_access_level(current_fal); context.converted_func_stack = current_funk_stack; context.converted_compiled_type = current_compiled_type; convertion_data_and_alghoritms.statement_list_stack = statement_list_stack; current_document = current_doc; body_exists = current_body_exists; _record_created = current_record_created; context.last_created_function = current_last_created_function; is_direct_type_decl = current_is_direct_type_decl; context.allow_inherited_ctor_call = current_allow_inherited_ctor_call; current_converted_method_not_in_class_defined = current_cur_meth_not_in_class; context.set_field_access_level(curr_fal); type_section_converting = current_type_section_converting; context.member_decls = current_member_decls; context.var_defs = current_var_defs; using_list.Clear(); foreach (using_namespace un in current_using_list) { using_list.AddElement(un); } return ctn; } private SyntaxTree.addressed_value convert_named_type_reference_to_addressed_value(SyntaxTree.named_type_reference ntr) { SyntaxTree.addressed_value adrv = ntr.names[0]; for (int i = 1; i < ntr.names.Count; i++) adrv = new SyntaxTree.dot_node(adrv, ntr.names[i]); return adrv; } public base_function_call create_constructor_call(type_node tn, expressions_list exprs, location loc, Tuple> lambdas_info = null, bool inherited_call=false) { if (tn.IsInterface) { AddError(loc, "INTERFACE_{0}_CONSTRUCTOR_CALL", tn.name); } if (tn.IsStatic) { AddError(loc, "STATIC_CONSTRUCTOR_CALL"); } if (tn.IsAbstract && !inherited_call) { AddError(loc, "ABSTRACT_CONSTRUCTOR_{0}_CALL", tn.name); } List sil = tn.find_in_type(default_constructor_name, context.CurrentScope); //tn.Scope); // SSM 06.01.26 - это позволяет учитывать только конструкторы при наличии других функций Create. К сожалению, этого недостаточно // т.к. всё равно статическая и экземплярная Create не различаются и кидается ошибка при t.Create // Надо это улучшать //sil = sil.FindAll(si => si.sym_info is common_method_node cmn && cmn.is_constructor); delete_inherited_constructors(ref sil, tn); if (sil == null) AddError(loc, "CONSTRUCTOR_NOT_FOUND"); function_node fnn = null; try { #region Если встретились лямбды в фактических параметрах, то выбираем нужную функцию из перегруженных, выводим типы, отмечаем флаг в лямбдах, говорящий о том, что мы их реально обходим //lroman// if (lambdas_info != null && lambdas_info.Item1) { LambdaHelper.processingLambdaParametersForTypeInference++; var syntax_nodes_parameters = lambdas_info.Item2; // SSM 21.05.14 - попытка обработать перегруженные функции с параметрами-лямбдами с различными возвращаемыми значениями List spf = null; try { function_node fn = convertion_data_and_alghoritms.select_function(exprs, sil, loc, syntax_nodes_parameters); int exprCounter = 0; foreach (SyntaxTree.expression en in syntax_nodes_parameters) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var enLambda = (SyntaxTree.function_lambda_definition)en; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, enLambda, this); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; exprs[exprCounter] = convert_strong(en); enLambda.lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; exprCounter++; } } } catch (SeveralFunctionsCanBeCalled sf) { spf = sf.set_of_possible_functions; // Возможны несколько перегруженных версий - надо выводить дальше в надежде что какие-то уйдут и останется одна } Exception lastmultex = null; if (spf != null) // пытаемся инстанцировать одну за другой и ошибки гасим try { // exprs - глобальная, поэтому надо копировать int spfnum = -1; // spfnum - первый номер правильно инстанцированной. Пока -1. Если потом встретился второй, то тоже ошибка int GoodVersionsCount = 0; int GoodVersionsCountWithSameResType = 0; for (int i = 0; i < spf.Count; i++) { function_node fn = spf[i]; try { int exprCounter = 0; expressions_list exprs1 = new expressions_list(); exprs1.AddRange(exprs); // сделали копию foreach (SyntaxTree.expression en in syntax_nodes_parameters) { if (!(en is SyntaxTree.function_lambda_definition)) { exprCounter++; continue; } else { var fld = en as SyntaxTree.function_lambda_definition; var lambdaName = fld.lambda_name; //lroman Сохранять имя необходимо var fl = fld.lambda_visit_mode; // запомнили типы параметров лямбды - SSM object[] realparamstype = new object[fld.formal_parameters.params_list.Count]; // здесь хранятся выведенные типы лямбд или null если типы явно заданы for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK == null) realparamstype[k] = null; else realparamstype[k] = laminftypeK.real_type; } // запоминаем реальный тип возвращаемого значения если он не указан явно (это должен быть any_type или null если он указан явно) - он может измениться при следующем вызове, поэтому мы его восстановим var restype = fld.return_type as SyntaxTree.lambda_inferred_type; object realrestype = null; if (restype != null) realrestype = restype.real_type; LambdaHelper.InferTypesFromVarStmt(fn.parameters[exprCounter].type, fld, this); fld.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing; //lroman fld.lambda_name = LambdaHelper.GetAuxiliaryLambdaName(lambdaName, generatedNamesManager); // поправляю имя. Думаю, назад возвращать не надо. ПРОВЕРИТЬ! //contextChanger.SaveContextAndUpToNearestDefSect(); try { exprs1[exprCounter] = convert_strong(en); type_node resexprtype = fld.RealSemTypeOfResExpr as type_node; type_node resformaltype = fld.RealSemTypeOfResult as type_node; var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } /*var tt = fn.parameters[exprCounter].type as compiled_type_node; if (tt != null && tt.compiled_type.FullName.ToLower().StartsWith("system.func")) { resformaltype = tt.instance_params[tt.instance_params.Count - 1]; // Последний параметр в записи Func - тип возвращаемого значения var bbb = resexprtype == resformaltype; // только в одном случае должно быть true - эту версию и надо выбирать. Если в нескольких, то неоднозначность if (bbb) { GoodVersionsCountWithSameResType += 1; spfnum = i; // здесь запоминаем индекс потому что он точно подойдет. Тогда ниже он запоминаться не будет. } }*/ } catch { throw; } finally { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, en as function_lambda_definition); // восстанавливаем сохраненный тип возвращаемого значения if (restype != null) restype.real_type = realrestype; // восстанавливаем сохраненные типы параметров лямбды, которые не были заданы явно for (var k = 0; k < fld.formal_parameters.params_list.Count; k++) { var laminftypeK = fld.formal_parameters.params_list[k].vars_type as SyntaxTree.lambda_inferred_type; if (laminftypeK != null) laminftypeK.real_type = realparamstype[k]; } fld.lambda_name = lambdaName; //lroman Восстанавливаем имена fld.lambda_visit_mode = fl; } //contextChanger.RestoreCurrentContext(); exprCounter++; } } /*if (spfnum >= 0) // два удачных инстанцирования - плохо. Может, одно - с более близким типом возвращаемого значения, тогда это плохо - надо доделать, но пока так { spfnum = -2; break; }*/ if (GoodVersionsCountWithSameResType == 0) spfnum = i; // здесь запоминаем индекс только если нет подошедших, совпадающих по типу возвращаемого значения GoodVersionsCount += 1; for (int j = 0; j < exprs.Count; j++) // копируем назад если всё хорошо exprs[j] = exprs1[j]; } catch (Exception e) { // если сюда попали, значит, не вывели типы в лямбде и надо эту инстанцию пропускать //contextChanger.RestoreCurrentContext(); lastmultex = e; } } if (GoodVersionsCount > 1 && GoodVersionsCountWithSameResType != 1) // подошло много, но не было ровно одной с совпадающим типом возвращаемого значения throw new SeveralFunctionsCanBeCalled(loc, spf); if (GoodVersionsCount == 0) // было много, но ни одна не подошла из-за лямбд { throw lastmultex; //throw new NoFunctionWithSameArguments(subloc2, false); } var kk = 0; foreach (SyntaxTree.expression en in syntax_nodes_parameters) //lroman окончательно подставить типы в лямбды { if (!(en is SyntaxTree.function_lambda_definition)) { kk++; continue; } else { LambdaHelper.InferTypesFromVarStmt(spf[spfnum].parameters[kk].type, en as SyntaxTree.function_lambda_definition, this); exprs[kk] = convert_strong(en); kk++; } } } // SSM 21.05.14 end LambdaHelper.processingLambdaParametersForTypeInference--; fnn = convertion_data_and_alghoritms.select_function(exprs, sil, loc); } //lroman// #endregion else { List syntax_nodes_parameters = lambdas_info?.Item2; // SSM 23/02/26 - передаю в select_function чтобы можно было обработать именованные аргументы fnn = convertion_data_and_alghoritms.select_function(exprs, sil, loc, syntax_nodes_parameters); } } catch (NoFunctionWithSameParametresNum e) { e.is_constructor = true; throw; } return create_static_method_call_with_params(fnn, loc, tn, false, exprs, inherited_call); } private expression_node clip_expression_if_need(expression_node expr, type_node tn) { if (!(tn is short_string_type_node) && tn.type_special_kind != SemanticTree.type_special_kind.set_type) return expr; if (tn is short_string_type_node) { return convertion_data_and_alghoritms.create_simple_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringProcedure.sym_info as function_node,null,convertion_data_and_alghoritms.convert_type(expr,SystemLibrary.SystemLibrary.string_type),new int_const_node((tn as short_string_type_node).Length,null)); } else if (tn.type_special_kind == SemanticTree.type_special_kind.set_type && tn.element_type != null) { ordinal_type_interface oti = tn.element_type.get_internal_interface(internal_interface_kind.ordinal_interface) as ordinal_type_interface; if (oti != null) { base_function_call cmc = null; if (SystemLibrary.SystemLibInitializer.ClipFunction.sym_info is common_namespace_function_node) cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as common_namespace_function_node, null); else cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(oti.lower_value.get_constant_copy(null)); cmc.parameters.AddElement(oti.upper_value.get_constant_copy(null)); cmc.ret_type = tn; return cmc; } else if (tn.element_type.type_special_kind == SemanticTree.type_special_kind.short_string) { base_function_call cmc = null; if (SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info is common_namespace_function_node) cmc = new common_namespace_function_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as common_namespace_function_node, null); else cmc = new compiled_static_method_call(SystemLibrary.SystemLibInitializer.ClipShortStringInSetFunction.sym_info as compiled_function_node, null); cmc.parameters.AddElement(expr); cmc.parameters.AddElement(new int_const_node((tn.element_type as short_string_type_node).Length, null)); cmc.ret_type = tn; return cmc; } } return expr; } public override void visit(SyntaxTree.new_expr _new_expr) { type_node tn = ret.visit(_new_expr.type); if (tn is generic_instance_type_node gitn) // SSM 07/08/19 #2070 { gitn.SetIsAbstract(gitn.original_generic.IsAbstract, gitn.original_generic.AbstractReason); } //if (tn == SystemLibrary.SystemLibrary.void_type) // AddError(new VoidNotValid(get_location(_new_expr.type))); if (tn.IsDelegate && !_new_expr.new_array) AddError(get_location(_new_expr), "CONSTRUCTOR_CALL_FOR_DELEGATE_TYPES_IS_FORBIDDEN"); check_for_type_allowed(tn,get_location(_new_expr.type)); location loc = get_location(_new_expr); expressions_list exprs = null; var lambdas_are_in_parameters = false; var syntax_nodes_parameters = _new_expr.params_list == null ? new List() : _new_expr.params_list.expressions; if (_new_expr.params_list != null) { exprs = new expressions_list(); foreach (SyntaxTree.expression en in _new_expr.params_list.expressions) { if (en is SyntaxTree.function_lambda_definition) { lambdas_are_in_parameters = true; ((SyntaxTree.function_lambda_definition)en).lambda_visit_mode = LambdaVisitMode.VisitForInitialMethodCallProcessing; } exprs.AddElement(convert_strong(en)); } } else exprs = new expressions_list(); if (_new_expr.new_array) { check_using_static_class(tn, get_location(_new_expr.type)); //if (exprs.Count == 1) { //new typename[size] type_node atn = convertion_data_and_alghoritms.type_constructor.create_unsized_array(tn, exprs.Count, loc); //тип элементов typeof_operator to = new typeof_operator(tn, loc); List lst = new List(); //размер for (int i=0; i 1) { foreach (expression_node expr in lst) if (!(expr is int_const_node)) AddError(expr.location, "CONSTANT_EXPRESSION_EXPECTED"); if (_new_expr.array_init_expr.elements == null) AddError(get_location(_new_expr.array_init_expr), "ARRAY_CONST_EXPECTED"); _new_expr.array_init_expr = get_possible_array_const(_new_expr.array_init_expr,atn) as SyntaxTree.array_const; expression_node e = convert_strong(_new_expr.array_init_expr); if (e is array_initializer) { array_initializer tmp = e as array_initializer; for (int i=0; i>(lambdas_are_in_parameters, syntax_nodes_parameters))); } public override void visit(SyntaxTree.name_assign_expr node) { var ex = convert_strong(node.expr); // на этом уровне имя никак не учитывать. Оно учтется ТОЛЬКО в select_function return_value(ex); } public override void visit(SyntaxTree.where_type_specificator_list node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.where_definition node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.where_definition_list node) { throw new NotSupportedError(get_location(node)); } private bool can_evaluate_size(type_node tn) { if (tn is compiled_type_node ctn1) { if (tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper || tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.short_string || tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file || tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.array_kind) return true; if (tn.type_special_kind == SemanticTree.type_special_kind.diap_type || tn.type_special_kind == SemanticTree.type_special_kind.enum_kind) return true; if (tn.IsPointer) return true; if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance) return false; /*if (ctn1.compiled_type == typeof(System.IntPtr) || ctn1.compiled_type == typeof(System.UIntPtr)) return false;*/ } if (tn is common_type_node) { common_type_node ctn = tn as common_type_node; if (ctn.type_special_kind == SemanticTree.type_special_kind.diap_type || ctn.type_special_kind == SemanticTree.type_special_kind.enum_kind) return true; if (tn.type_special_kind == SemanticTree.type_special_kind.array_wrapper || tn.type_special_kind == SemanticTree.type_special_kind.set_type || tn.type_special_kind == SemanticTree.type_special_kind.short_string || tn.type_special_kind == SemanticTree.type_special_kind.typed_file || tn.type_special_kind == SemanticTree.type_special_kind.text_file || tn.type_special_kind == SemanticTree.type_special_kind.binary_file || tn.type_special_kind == SemanticTree.type_special_kind.array_kind) return true; if (tn.IsPointer) return true; if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance) return false; foreach (class_field cf in ctn.fields) if (!cf.IsStatic && cf.type != tn) if (!can_evaluate_size(cf.type)) return false; } return true; } private expression_node make_sizeof_operator(type_node tn, location loc) { return new sizeof_operator(tn,loc); } public override void visit(SyntaxTree.sizeof_operator node) { if (node.type_def != null && node.type_def is SyntaxTree.named_type_reference) { SyntaxTree.named_type_reference ntr = node.type_def as SyntaxTree.named_type_reference; type_node tn = find_type(ntr, get_location(ntr)); switch (tn.type_special_kind) { case SemanticTree.type_special_kind.enum_kind: if (tn is compiled_type_node ctn) { return_value(new int_const_node(System.Runtime.InteropServices.Marshal.SizeOf(ctn.compiled_type.GetEnumUnderlyingType()), get_location(ntr))); break; } else { return_value(new int_const_node(sizeof(int), get_location(ntr))); break; } default: if (tn.is_generic_parameter || tn.is_generic_type_definition || tn.is_generic_type_instance) { AddError(get_location(ntr), "OPERATOR_SIZEOF_CAN_NOT_BE_USED_WITH_GENERIC_TYPE"); } if (!can_evaluate_size(tn)) AddError(get_location(ntr), "CANNOT_EVALUATE_SIZE", tn.name); return_value(make_sizeof_operator(tn, get_location(node))); break; } } else throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.typeof_operator node) { return_value(new typeof_operator(find_type(node.type_name, get_location(node.type_name)), get_location(node))); } public override void visit(SyntaxTree.compiler_directive node) { if (node.Name.text.ToLower() == StringConstants.compiler_directive_faststrings) { SemanticRulesConstants.FastStrings = true; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_zerobasedstrings) { var paramOnOff = node.Directive.text.ToLower(); if (paramOnOff == "on" || paramOnOff == "") SemanticRulesConstants.ZeroBasedStrings = true; else if (paramOnOff == "off") SemanticRulesConstants.ZeroBasedStrings = false; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_zerobasedstrings_ON) { SemanticRulesConstants.ZeroBasedStrings = true; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_zerobasedstrings_OFF) { SemanticRulesConstants.ZeroBasedStrings = false; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_nullbasedstrings_ON) { SemanticRulesConstants.ZeroBasedStrings = true; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_nullbasedstrings_OFF) { SemanticRulesConstants.ZeroBasedStrings = false; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_initstring_as_empty_ON) { SemanticRulesConstants.InitStringAsEmptyString = true; return; } if (node.Name.text.ToLower() == StringConstants.compiler_directive_initstring_as_empty_OFF) { SemanticRulesConstants.InitStringAsEmptyString = false; return; } if (node.Name.text == StringConstants.compiler_directive_platformtarget && node.Directive.text.ToLower() == "native") { SemanticRulesConstants.GenerateNativeCode = true; return; } } public override void visit(SyntaxTree.operator_name_ident node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.var_statement node) { visit(node.var_def); ret.reset(); // SSM 19.01.17 не возвращать семантическое значение т.к. ничего не нужно добавлять в текущий список операторов!! } // создать словарик чтобы для одного _visitor.context.CurrentScope.ScopeNum и для одного letVarExpr // мы заходили в этот visit один раз private Dictionary> letDict = new Dictionary>(); // можно попробовать в одно ПИ не добавлять дважды - хранить словарь (let-переменная, номера ПИ в кот добавлена) public override void visit(SyntaxTree.let_var_expr let_expr) { if (letDict.ContainsKey(let_expr) && letDict[let_expr].Contains(context.CurrentScope.ScopeNum)) return; if (!letDict.ContainsKey(let_expr)) letDict[let_expr] = new List(); letDict[let_expr].Add(context.CurrentScope.ScopeNum); var exn = (expression_node)convert_strong(let_expr.ex); var sav = new semantic_addr_value(exn); var vds = new var_statement(let_expr.id, sav, let_expr.source_context); if (let_expr.visit_var) { visit(vds.var_def); //let_expr.visit_var = false; } else { } return_value(exn); } public override void visit(SyntaxTree.expression_as_statement node) { return_value((statement_node)convert_strong(node.expr)); } private base_function_call make_base_constructor_call(function_node fn, out compiled_constructor_node pconstr, out common_method_node mconstr) { mconstr = fn as common_method_node; pconstr = fn as compiled_constructor_node; if (mconstr != null && mconstr.is_constructor) return new common_constructor_call(mconstr, null) { _new_obj_awaited = false }; else if (pconstr != null) return new compiled_constructor_call(pconstr, null) { _new_obj_awaited = false }; return null; } //ssyy public void generate_inherit_constructors() { common_type_node _ctn = context.converted_type; if (_ctn == null) { throw new CompilerInternalError("Can generate inherited constructors only in class."); } if (_ctn.IsStatic) return; { var fn = _ctn.base_type.find_in_type(default_constructor_name, _ctn.base_type.Scope) ?.Select(si => si.sym_info).OfType() .FirstOrDefault(_fn => _fn.parameters.Count == 0); var base_constructor_call = make_base_constructor_call(fn, out _, out _); if (base_constructor_call != null) foreach (var cmn in _ctn.methods) if (cmn.is_constructor && !cmn.IsStatic) { // Если тело есть - это значит что этот конструктор уже полностью откомпилирован, потому что объявлен в предыдущем теле partial класса // На случай если базовый класс указан только в заголовке текущего тела partial класса - надо подменить вызов базового конструктора if (cmn.function_code is statements_list st_lst) { var param_c = st_lst.statements[0] is common_constructor_call mconstr ? mconstr.parameters.Count : st_lst.statements[0] is compiled_constructor_call pconstr ? pconstr.parameters.Count : throw new NotSupportedException(); // Первый вызов это в любом случае конструктор, но если я что то не учёл - надо будет добавить ещё условия на предыдущей строчке // Внимание: Пустым конструктором подменяем только пустой конструктор. Если был вызван конструктор с параметрами - это уже правильный конструктор правильного предка, то есть: // - Или конструктор, вызванный вручную // - Или дефолтный конструктор, копирующий конструктор предка (который должен существовать, то есть предок уже указан) if (param_c != 0) continue; st_lst.statements[0] = base_constructor_call; } else if (cmn.function_code != null) throw new NotSupportedException(); // Сомневаюсь что это возможно, но если в будущем станет возможно - надо будет обработать по-особому } } if (_ctn.has_user_defined_constructor) { //Пользователь определил хотя бы один конструктор, никакие конструкторы не наследуем. return; } //Получили список процедур предка, имеющих имя Create List sil = _ctn.base_type.find_in_type(default_constructor_name, _ctn.base_type.Scope); delete_inherited_constructors(ref sil, _ctn.base_type); if (sil != null) { foreach(SymbolInfo si in sil) { function_node fn = si.sym_info as function_node; var base_constructor_call = make_base_constructor_call(fn, out var pconstr, out var mconstr); //Если это конструктор... if (base_constructor_call != null) { //Генерируем унаследованный конструктор location loc = null; SemanticTree.polymorphic_state ps; if (mconstr != null) { loc = mconstr.loc; ps = mconstr.polymorphic_state; } else //значит (pconstr != null) { ps = pconstr.polymorphic_state; } if (pconstr != null) context.set_field_access_level(pconstr.field_access_level); else context.set_field_access_level(mconstr.field_access_level); // Иначе partial классам генерирует кучу копий дефолтных конструкторов if (_ctn.methods.Any(m => m.is_constructor && m.name == default_constructor_name && m.parameters.Count == fn.parameters.Count && m.parameters.Zip(fn.parameters, (par1, par2) => par1.type == par2.type).All(b => b) )) continue; var gen_constr = context.create_function(default_constructor_name, loc) as common_method_node; gen_constr.polymorphic_state = ps; gen_constr.is_overload = true; gen_constr.is_constructor = true; gen_constr.field_access_level = fn.field_access_level; if (_ctn.IsPartial) context.last_created_function.symbol_kind = symbol_kind.sk_overload_function; gen_constr.return_value_type = _ctn; foreach (parameter par in fn.parameters) { //(ssyy) Интересно, зачем это. concrete_parameter_type cpt = (par.parameter_type == SemanticTree.parameter_type.var) ? concrete_parameter_type.cpt_var : concrete_parameter_type.cpt_none; common_parameter c_p = new common_parameter(par.name, par.parameter_type, gen_constr, cpt, null); c_p.type = par.type; c_p.set_param_is_params(par.is_params); c_p.inital_value = par.inital_value; gen_constr.parameters.AddElement(c_p); c_p.default_value = par.default_value; } foreach (parameter p in gen_constr.parameters) { base_constructor_call.parameters.AddElement( create_variable_reference(p, null)); } statements_list snlist = new statements_list(null); snlist.statements.AddElement(base_constructor_call); snlist.statements.AddElement(new empty_statement(null)); gen_constr.function_code = snlist; context.leave_block(); if (fn.parameters.Count == 0 || fn.parameters[0].default_value != null) { _ctn.has_default_constructor = true; } } } } } //\ssyy //ssyy public void generate_inherited_from_base_and_interface_function(common_type_node ctype, function_node func) { common_method_node gen_func = context.create_function(func.name, null) as common_method_node; gen_func.polymorphic_state = SemanticTree.polymorphic_state.ps_common; gen_func.newslot_awaited = true; gen_func.is_final = true; gen_func.is_overload = true; gen_func.field_access_level = SemanticTree.field_access_level.fal_public; gen_func.return_value_type = func.return_value_type; //gen_func.return_variable = func.retu foreach (parameter par in func.parameters) { concrete_parameter_type cpt = (par.parameter_type == SemanticTree.parameter_type.value) ? concrete_parameter_type.cpt_const : concrete_parameter_type.cpt_var; common_parameter c_p = new common_parameter(par.name, par.parameter_type, gen_func, cpt, null); c_p.type = par.type; c_p.set_param_is_params(par.is_params); c_p.inital_value = par.inital_value; gen_func.parameters.AddElement(c_p); } local_variable lv = new local_variable(StringConstants.self_word, gen_func.cont_type, gen_func, null); gen_func.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(lv)); gen_func.self_variable = lv; base_function_call bfc; this_node tn = null; common_method_node commn = func as common_method_node; if (commn != null) { tn = new this_node(commn.comperehensive_type as type_node, null); bfc = new common_method_call(commn, tn, null); } else { compiled_function_node compn = func as compiled_function_node; tn = new this_node(compn.comperehensive_type as type_node, null); bfc = new compiled_function_call(compn, tn, null); } foreach (parameter p in gen_func.parameters) { bfc.parameters.AddElement( create_variable_reference(p, null)); } //Это запретит чистку стека bfc.last_result_function_call = true; statements_list snlist = new statements_list(null); snlist.statements.AddElement(bfc); snlist.statements.AddElement(new empty_statement(null)); gen_func.function_code = snlist; context.pop_top_function(); //context.leave_block(); } //\ssyy private Dictionary WaitedRefTypes = new Dictionary(); internal ref_type_node GetWaitedRefType(string name, location loc) { ref_type_node rtn = null; if (WaitedRefTypes.TryGetValue(name, out rtn)) return rtn; rtn = new ref_type_node(null); rtn.PointedTypeName = name; rtn.loc = loc; WaitedRefTypes.Add(name, rtn); return rtn; } internal List RefTypesForCheckPointersTypeForDotNetFramework = new List(); void ProcessRefTypesForCheckPointersTypeForDotNetFramework() { foreach (ref_type_node rtn in RefTypesForCheckPointersTypeForDotNetFramework) if (SemanticRulesConstants.StrongPointersTypeCheckForDotNet) CheckPointersTypeForDotNetFramework(rtn.pointed_type, rtn.loc); RefTypesForCheckPointersTypeForDotNetFramework.Clear(); } internal void CheckWaitedRefTypes(type_node tn) { ref_type_node rtn = null; if (WaitedRefTypes.TryGetValue(tn.name, out rtn)) { if (SemanticRulesConstants.StrongPointersTypeCheckForDotNet) RefTypesForCheckPointersTypeForDotNetFramework.Add(rtn); rtn.SetPointedType(tn); WaitedRefTypes.Remove(tn.name); } } internal void EnterTypeDeclarationsSection() { type_section_converting = true; } internal void LeaveTypeDeclarationsSection() { type_section_converting = false; if (context.types_predefined.Count > 0 && !context.namespace_converted) { AddError(context.types_predefined[0].loc, "NO_TYPE_{0}_DEFINITION", context.types_predefined[0].name); } foreach (string Name in WaitedRefTypes.Keys) WaitedRefTypes[Name].SetPointedType(find_type(Name, WaitedRefTypes[Name].loc)); foreach (ref_type_node rtn in WaitedRefTypes.Values) CheckForCircularityInPointers(rtn, rtn.pointed_type,rtn.loc); ProcessRefTypesForCheckPointersTypeForDotNetFramework(); WaitedRefTypes.Clear(); } internal void ProcessCheckPointersInRecord() { ProcessRefTypesForCheckPointersTypeForDotNetFramework(); } public override void visit(SyntaxTree.c_scalar_type node) { Type t = null; switch (node.scalar_name) { case SyntaxTree.c_scalar_type_name.tn_void: t = typeof(void); break; case SyntaxTree.c_scalar_type_name.tn_char: t = typeof(char); break; case SyntaxTree.c_scalar_type_name.tn_double: t = typeof(double); break; case SyntaxTree.c_scalar_type_name.tn_float: t = typeof(float); break; case SyntaxTree.c_scalar_type_name.tn_int: t = (node.sign == SyntaxTree.c_scalar_sign.unsigned) ? typeof(UInt32) : typeof(Int32); break; case SyntaxTree.c_scalar_type_name.tn_long: case SyntaxTree.c_scalar_type_name.tn_long_int: t = (node.sign == SyntaxTree.c_scalar_sign.unsigned) ? typeof(UInt64) : typeof(Int64); break; case SyntaxTree.c_scalar_type_name.tn_short: case SyntaxTree.c_scalar_type_name.tn_short_int: t = typeof(Int16); break; } ret.return_value(compiled_type_node.get_type_node(t)); } public override void visit(SyntaxTree.c_module node) { string namespace_name = ""; location loc = null; // if (_program_module.program_name != null) // { // namespace_name = _program_module.program_name.prog_name.name; // loc = get_location(_program_module.program_name.prog_name); // if (namespace_name.ToLower() != System.IO.Path.GetFileNameWithoutExtension(_program_module.file_name).ToLower()) // throw new ProgramNameMustBeEqualProgramFileName(loc); // } _compiled_unit = new common_unit_node(); _compiled_unit.compiler_directives = ConvertDirectives(node); //PrepareDirectives(_compiled_unit.compiler_directives); //using_list.AddRange(interface_using_list); //weak_node_test_and_visit(_program_module.using_namespaces); //weak_node_test_and_visit(node.used_units); //compiled_main_unit=new unit_node(); //SymbolTable.Scope[] used_units=new SymbolTable.Scope[used_assemblyes.Count+1]; SymbolTable.Scope[] used_units = build_referenced_units(ReferencedUnits,true); _compiled_unit.scope = convertion_data_and_alghoritms.symbol_table.CreateUnitInterfaceScope(used_units, namespace_name); common_namespace_node cnsn = context.create_namespace(namespace_name, _compiled_unit, _compiled_unit.scope, loc); cnsn.is_main = true; //compiled_program=new program_node(); //compiled_program.units.Add(compiled_main_unit); reset_for_interface(); UpdateUnitDefinitionItemForUnit(_compiled_unit); //_program_module.program_block.visit(this); //hard_node_test_and_visit(_program_module.program_block); //context.check_labels(context.converted_namespace.labels); //TODO: Доделать. //common_namespace_function_node main_function = new common_namespace_function_node(StringConstants.temp_main_function_name, // null, null, cnsn, null); //main_function.function_code = context.code; //cnsn.functions.AddElement(main_function); weak_node_test_and_visit(node.defs); bool main_not_found = true; foreach (function_node fn in cnsn.functions) { if (fn.name == StringConstants.c_main_function_name) { _compiled_unit.main_function = fn as common_namespace_function_node; //context.apply_special_local_vars(_compiled_unit.main_function); main_not_found = false; break; } } if (main_not_found) { AddError(get_location(node), "NO_MAIN_FUNCTION"); } context.leave_block(); //_compiled_unit.main_function = main_function; } public override void visit(SyntaxTree.declarations_as_statement node) { //throw new NotSupportedError(get_location(node)); node.defs.visit(this); return_value(new empty_statement(null)); } public override void visit(SyntaxTree.array_size node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.enumerator node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.enumerator_list node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.c_for_cycle node) { //throw new NotSupportedError(get_location(node)); location loc1 = get_location(node.expr1); statements_list head_stmts = new statements_list(loc1); convertion_data_and_alghoritms.statement_list_stack_push(head_stmts); //statement_node sn_init = convert_weak((SyntaxTree.statement)node.expr1); // SSM 12/06/15 - всё равно c-узлы никому не нужны statement_node sn_init = convert_weak(node.expr1); // SSM 12/06/15 expression_node sn_cond = convert_weak(node.expr2); //statement_node sn_next = convert_weak((SyntaxTree.statement)node.expr3); // SSM 12/06/15 statement_node sn_next = convert_weak(node.expr3); // SSM 12/06/15 CheckToEmbeddedStatementCannotBeADeclaration(node.stmt); for_node fn = new for_node(sn_init, sn_cond, null, sn_next, null, get_location(node)); context.enter_in_cycle(fn); statements_list slst = new statements_list(get_location(node.stmt)); convertion_data_and_alghoritms.statement_list_stack_push(slst); context.enter_code_block_with_bind(); fn.body = convert_strong(node.stmt); context.leave_code_block(); slst = convertion_data_and_alghoritms.statement_list_stack.Pop(); if (slst.statements.Count > 0 || slst.local_variables.Count > 0) { slst.statements.AddElement(fn.body); fn.body = slst; } context.leave_cycle(); head_stmts = convertion_data_and_alghoritms.statement_list_stack.Pop(); head_stmts.statements.AddElement(fn); return_value(head_stmts); /*slst = convertion_data_and_alghoritms.statement_list_stack.pop(); if (slst.statements.Count > 0 || slst.local_variables.Count > 0) { slst.statements.AddElement(fn.body); fn.body = slst; } context.cycle_stack.pop();*/ //ret.return_value(slst); } public override void visit(SyntaxTree.switch_stmt node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.type_definition_attr node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.type_definition_attr_list node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.lock_stmt node) { expression_node lock_object = convert_strong(node.lock_object); //Нужно ли это??? if (lock_object.type.semantic_node_type == semantic_node_type.delegated_method) try_convert_typed_expression_to_function_call(ref lock_object); if (/*lock_object.type == null ||*/ !lock_object.type.is_class) AddError(get_location(node.lock_object), "EXPRESSION_IN_LOCK_STATEMENT_RETURNED_NOT_A_REFERENCE_TYPE", lock_object.type); CheckToEmbeddedStatementCannotBeADeclaration(node.stmt); statement_node stmt = convert_strong(node.stmt); return_value(new lock_statement(lock_object, stmt, get_location(node))); } public override void visit(SyntaxTree.compiler_directive_list node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.compiler_directive_if node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.documentation_comment_list node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.documentation_comment_section node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.documentation_comment_tag node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.documentation_comment_tag_param node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.token_taginfo node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.declaration_specificator node) { throw new NotSupportedError(get_location(node)); } public override void visit(SyntaxTree.ident_with_templateparams _ident_with_templateparams) { SyntaxTree.expression ex = _ident_with_templateparams.name; SyntaxTree.ident id_ex = _ident_with_templateparams.name as SyntaxTree.ident; dot_node dn = _ident_with_templateparams.name as dot_node; int par_count = _ident_with_templateparams.template_params.params_list.Count; if (id_ex != null) { SymbolInfo type_si = context.find_first(id_ex.name + StringConstants.generic_params_infix + par_count.ToString()); if (type_si != null) { return_value(get_generic_instance(type_si, _ident_with_templateparams.template_params.params_list)); return; } type_si = context.find_first(id_ex.name); if (type_si != null && type_si.sym_info.general_node_type == general_node_type.template_type) { template_class tc = type_si.sym_info as template_class; List tpars = visit_type_list(_ident_with_templateparams.template_params.params_list); return_value(instance_any(tc, tpars, get_location(_ident_with_templateparams))); return; } } else if (dn != null && dn.right is ident) { semantic_node sn = convert_semantic_strong(dn.left); id_ex = dn.right as SyntaxTree.ident; type_node tn = null; namespace_node nn = null; unit_node un = null; switch (sn.general_node_type) { case general_node_type.expression: tn = (sn as expression_node).type; break; case general_node_type.type_node: tn = sn as type_node; break; case general_node_type.namespace_node: nn = sn as namespace_node; break; case general_node_type.unit_node: un = sn as unit_node; break; default: AddError(get_location(dn.left), "EXPECTED_ANOTHER_KIND_OF_OBJECT"); break; } List type_sil = null; if (tn != null) { type_sil = tn.find_in_type(id_ex.name + StringConstants.generic_params_infix + par_count.ToString()); } else if (nn != null) { type_sil = nn.find(id_ex.name + StringConstants.generic_params_infix + par_count.ToString()); } else if (un != null) { type_sil = un.find_only_in_namespace(id_ex.name + StringConstants.generic_params_infix + par_count.ToString()); } if (type_sil != null) { return_value(get_generic_instance(type_sil?.FirstOrDefault(), _ident_with_templateparams.template_params.params_list)); return; } if (tn != null) { type_sil = tn.find_in_type(id_ex.name); } else if (nn != null) { type_sil = nn.find(id_ex.name); } else if (un != null) { type_sil = un.find_only_in_namespace(id_ex.name); } if (type_sil != null && type_sil.FirstOrDefault().sym_info.general_node_type == general_node_type.template_type) { template_class tc = type_sil.FirstOrDefault().sym_info as template_class; List tpars = visit_type_list(_ident_with_templateparams.template_params.params_list); return_value(instance_any(tc, tpars, get_location(_ident_with_templateparams))); return; } dot_node dn2 = new dot_node(dn.left, new ident_with_templateparams(dn.right, _ident_with_templateparams.template_params, dn.right.source_context), dn.source_context); ex = dn2; } expression_node adr = ret.visit(ex); typed_expression te = adr as typed_expression; if (te != null) { delegated_methods dm = te.type as delegated_methods; if (dm != null) { List ptypes = visit_type_list(_ident_with_templateparams.template_params.params_list); base_function_call_list bfcl = new base_function_call_list(); common_method_node cnode; compiled_function_node comp_node; function_node fnode; int generic_count = 0; foreach (base_function_call bfc in dm.proper_methods) { if (bfc.simple_function_node.is_generic_function) { generic_count++; } } bool one_function = false; switch (generic_count) { case 0: AddError(get_location(_ident_with_templateparams), "TRIANGLE_BRACKETS_NOT_ALLOWED_WITH_COMMON_FUNCTIONS"); break; case 1: one_function = true; break; default: one_function = false; break; } foreach (base_function_call bfc in dm.proper_methods) { if (!bfc.simple_function_node.is_generic_function) { continue; } switch (bfc.semantic_node_type) { case semantic_node_type.common_namespace_function_call: common_namespace_function_node cnfn = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)) as common_namespace_function_node; if (cnfn != null) { bfcl.AddElement(new common_namespace_function_call(cnfn, bfc.location)); } break; case semantic_node_type.common_method_call: cnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)) as common_method_node; if (cnode != null) { bfcl.AddElement(new common_method_call(cnode, (bfc as common_method_call).obj, bfc.location)); } break; case semantic_node_type.compiled_function_call: fnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)); cnode = fnode as common_method_node; if (cnode != null) { bfcl.AddElement(new common_method_call(cnode, (bfc as compiled_function_call).obj, bfc.location)); } else { comp_node = fnode as compiled_function_node; if (comp_node != null) { bfcl.AddElement(new compiled_function_call(comp_node, (bfc as compiled_function_call).obj, bfc.location)); } } break; case semantic_node_type.common_static_method_call: case semantic_node_type.compiled_static_method_call: fnode = bfc.simple_function_node.get_instance(ptypes, one_function, get_location(_ident_with_templateparams)); cnode = fnode as common_method_node; if (cnode != null) { bfcl.AddElement(new common_static_method_call(cnode, bfc.location)); } else { comp_node = fnode as compiled_function_node; if (comp_node != null) { bfcl.AddElement(new compiled_static_method_call(comp_node, bfc.location)); } } break; } } if (bfcl.Count == 0) { AddError(get_location(_ident_with_templateparams.template_params), "NO_FUNCTIONS_{0}_CAN_BE_USED_WITH_THIS_SPECIFICATION", dm.proper_methods[0].function.name); } delegated_methods dm1 = new delegated_methods(); dm1.proper_methods.AddRange(bfcl); typed_expression te1 = new typed_expression(dm1, te.location); return_value(te1); return; } } if (!(adr is compiled_static_method_call) && !(adr is common_static_method_call) && !(adr is common_namespace_function_call)) AddError(get_location(_ident_with_templateparams.name), "TRIANGLE_BRACKETS_NOT_AWAITED"); } public override void visit(SyntaxTree.template_type_name node) { //throw new NotSupportedError(get_location(node)); ident_with_templateparams id = new ident_with_templateparams(); if (node.name.IndexOf('`') != -1 ) id.name = new ident(node.name.Substring(0, node.name.IndexOf('`')), node.source_context); else id.name = new ident(node.name, node.source_context); id.template_params = new template_param_list(); for (int i = 0; i < node.template_args.Count; i++) id.template_params.Add(new named_type_reference(node.template_args[0] as SyntaxTree.ident, node.template_args[i].source_context)); id.visit(this); } public override void visit(SyntaxTree.default_operator _default_operator) { type_node tn = ret.visit(_default_operator.type_name); if (tn == null) { AddError(get_location(_default_operator), "TYPE_REFERENCE_EXPECTED"); } if (tn == SystemLibrary.SystemLibrary.void_type) { AddError(get_location(_default_operator.type_name), "INAVLID_TYPE"); } return_value(new default_operator_node(tn, get_location(_default_operator))); //throw new NotSupportedError(get_location(_default_operator)); } public override void visit(SyntaxTree.bracket_expr _bracket_expr) { _bracket_expr.expr.visit(this); } public override void visit(SyntaxTree.attribute _attribute) { } public override void visit(SyntaxTree.attribute_list _attribute_list) { } public override void visit(SyntaxTree.simple_attribute_list _simple_attribute_list) { } public override void visit(closure_substituting_node _closure_substituting_node) { visit(_closure_substituting_node.substitution); } public void MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(function_lambda_definition _function_lambda_definition) { // SSM 23/07/16 - вроде сделал лучше в LambdaHelper.InferTypesFromVarStmt, но пока везде удалять вызов этой функции не решаюсь - лень тестировать // SSM 18/04/16 попытка разрешить x->Print(x) var stl = _function_lambda_definition.proc_body as SyntaxTree.statement_list; if (_function_lambda_definition.return_type is lambda_inferred_type && stl != null && stl.list.Count == 1 && _function_lambda_definition.usedkeyword == 0) { var ass = stl.list[0] as assign; if (ass != null && ass.to is ident && (ass.to as ident).name.Equals(result_var_name, context.CurrentScope.StringComparison)) { var f = ass.from; if (f is method_call) { var ff = f as method_call; // Надо посмотреть, как это делается для преобразования типов T(x). А пока так expression_node qq = null; delegated_methods dm = null; common_type_node delegate_type = null; int err_cnt = ErrorsList.Count; try { // Видимо, дело только в лямбде. Попробовать всё обойти и найти захваченные параметры // Если они есть, то ничего не делать и выйти var vis = HasCapturedLambdaParameterInInternalLambdaBody.New(_function_lambda_definition); vis.ProcessNode(ff.dereferencing_value); if (vis.HasCapturedParameter) // SSM 28/01/2021 считать это функцией. Будет слабый вывод в редком числе случаев return; qq = convert_strong(ff.dereferencing_value); if (qq is exit_procedure && stl.list.Count == 1 || qq is local_block_variable_reference && qq.type is compiled_type_node && (qq.type as compiled_type_node).compiled_type == typeof(Action)) { // SSM #2172 27/06/20 - тело - это вызов exit stl.list[0] = new procedure_call(ff, ff.source_context); _function_lambda_definition.return_type = null; return; } dm = qq.type as delegated_methods; if (dm == null && qq.type != null && qq.type.IsDelegate) delegate_type = qq.type as common_type_node; } catch (Exception e) { if (ErrorsList.Count != err_cnt)//delete fake errors ErrorsList.RemoveRange(err_cnt, ErrorsList.Count - err_cnt); // Погасить все исключения. Значит, не вывелось, и в правой части лямбды - не вызов процедуры, а скорее всего приведение типа T(x) // К сожалению, сюда попадает случай a->a.Print() где a до более позднего этапа не определяется // Плохо, но лучше пока не получается } if (dm != null && dm.proper_methods != null && dm.proper_methods.Count > 0) { if (dm.proper_methods[0].ret_type == null && stl.expr_lambda_body) { // Очищаем от Result := stl.list[0] = new procedure_call(ff, ff.source_context); // заменить result := Print(x) на Print(x) _function_lambda_definition.return_type = null; } } else if (delegate_type != null) { function_node fn = delegate_type.find_in_type("Invoke")[0].sym_info as function_node; if (fn.return_value_type == null && stl.expr_lambda_body) { stl.list[0] = new procedure_call(ff, ff.source_context); _function_lambda_definition.return_type = null; } } } } else if (!stl.expr_lambda_body) // SSM 26.11.18 // значит, первый и единственный оператор - не присваивание и это лямбда - процедура! { var rns = new LambdaHelper.ResultNodesSearcher(_function_lambda_definition.proc_body); if (rns.exprList.Count == 0) // Значит, это процедура, т.к. в блоке begin-end нет ни одного result := ... { _function_lambda_definition.return_type = null; } else _function_lambda_definition.usedkeyword = 1; // значит, это наверняка функция } } else if (_function_lambda_definition.return_type is lambda_inferred_type && stl != null && stl.list.Count > 1 && _function_lambda_definition.usedkeyword == 0) { var rns = new LambdaHelper.ResultNodesSearcher(_function_lambda_definition.proc_body); if (rns.exprList.Count == 0) // Значит, это процедура, т.к. в блоке begin-end нет ни одного result := ... { _function_lambda_definition.return_type = null; } else _function_lambda_definition.usedkeyword = 1; // значит, это наверняка функция } } public expression ProcedureForLambdaAndVisit(function_lambda_definition lambdaDefinition, ident_list tempParsList, where_definition_list whereSection) { var procDecl = LambdaHelper.ConvertLambdaNodeToProcDefNode(lambdaDefinition); if (tempParsList != null) { procDecl.proc_header.template_args = tempParsList; } if (whereSection != null && whereSection.defs != null && whereSection.defs.Count != 0) { procDecl.proc_header.where_defs = whereSection; } if (context.func_stack.Count > 0 && context.func_stack.Peek().polymorphic_state == SemanticTree.polymorphic_state.ps_static || context.converted_type != null && context.converted_type.IsStatic) { procDecl.proc_header.class_keyword = true; if (procDecl.proc_header.proc_attributes == null) procDecl.proc_header.proc_attributes = new SyntaxTree.procedure_attributes_list(); procDecl.proc_header.proc_attributes.proc_attributes.Add(new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static)); } try { visit(procDecl); } catch (Exception e) { context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, true); throw; } context.remove_lambda_function(procDecl.proc_header.name.meth_name.name, false); return tempParsList == null ? (expression)procDecl.proc_header.name.meth_name : (expression)new ident_with_templateparams(procDecl.proc_header.name.meth_name, new template_param_list(tempParsList.idents.Select(l => SyntaxTreeBuilder.BuildSimpleType(l.name)).ToList())); } int ccc = 0; public override void visit(SyntaxTree.function_lambda_definition _function_lambda_definition) { #if DEBUG /*if (lambdaProcessingState == LambdaProcessingState.ClosuresProcessingPhase) { var s = new string (' ',ccc)+"begin " + _function_lambda_definition.lambda_name + " " + _function_lambda_definition.parameters.expressions[0] + "\n"; ccc += 2; System.IO.File.AppendAllText("d:\\bb3.txt", s); }*/ #endif //stl.list[0] = new procedure_call(ff, ff.source_context); - Это надо для превращения функции в процедуру //_function_lambda_definition.return_type = null; _function_lambda_definition.RealSemTypeOfResExpr = null; // После первого присваивания Result она будет содержать тип type_node в правой части Result _function_lambda_definition.RealSemTypeOfResult = null; try { stflambda.Push(_function_lambda_definition); if (_function_lambda_definition.substituting_node != null) { if (_function_lambda_definition.substituting_node is dot_node) { visit((dot_node)_function_lambda_definition.substituting_node); } else if (_function_lambda_definition.substituting_node is ident) { visit((ident)_function_lambda_definition.substituting_node); } else if (_function_lambda_definition.substituting_node is ident_with_templateparams) { visit((ident_with_templateparams)_function_lambda_definition.substituting_node); } return; } // Внутри makeProcedureForLambdaAndVisit делается procdecl или funcdecl и обходится. // Поэтому формальный параметр обходится точно!! //Func makeProcedureForLambdaAndVisit = ProcedureForLambdaAndVisit; switch (lambdaProcessingState) { case LambdaProcessingState.TypeInferencePhase: { MaybeConvertFunctionLambdaDefinitionToProcedureLambdaDefinition(_function_lambda_definition); if (_function_lambda_definition.lambda_visit_mode == LambdaVisitMode.VisitForAdvancedMethodCallProcessing) { ProcedureForLambdaAndVisit(_function_lambda_definition, null, null); if (!LambdaHelper.IsAuxiliaryLambdaName(_function_lambda_definition.lambda_name)) { LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, _function_lambda_definition); } } ret.return_value((semantic_node)LambdaHelper.GetTempFunctionNodeForTypeInference(_function_lambda_definition, this)); break; } case LambdaProcessingState.FinishPhase: { if (context.top_function != null && context.top_function.generic_params != null) { var pars = context.top_function.generic_params.Select(par => new ident(par.name)).ToList(); var whereSection = CapturedVariablesSubstitutor.GetWhereSection( generic_parameter_eliminations.make_eliminations_common( context.top_function.generic_params), pars); if (_function_lambda_definition.formal_parameters != null && _function_lambda_definition.formal_parameters.params_list.Count > 0) { for (var j = 0; j < _function_lambda_definition.formal_parameters.params_list.Count; j++) { if (_function_lambda_definition.formal_parameters.params_list[j].vars_type is lambda_inferred_type) { if ((_function_lambda_definition.formal_parameters.params_list[j].vars_type as lambda_inferred_type).real_type is type_node) { _function_lambda_definition.formal_parameters.params_list[j].vars_type = LambdaHelper.ConvertSemanticTypeToSyntaxType((type_node)(_function_lambda_definition.formal_parameters.params_list[j].vars_type as lambda_inferred_type).real_type); } } } } if (_function_lambda_definition.return_type is lambda_inferred_type) { if ((_function_lambda_definition.return_type as lambda_inferred_type).real_type is type_node) { _function_lambda_definition.return_type = LambdaHelper.ConvertSemanticTypeToSyntaxType((type_node)(_function_lambda_definition.return_type as lambda_inferred_type).real_type); } } var methodNameToVisit = (ident_with_templateparams)ProcedureForLambdaAndVisit(_function_lambda_definition, new ident_list(pars), whereSection); _function_lambda_definition.substituting_node = methodNameToVisit; visit(methodNameToVisit); } else { var methodNameToVisit = (ident)ProcedureForLambdaAndVisit(_function_lambda_definition, null, null); _function_lambda_definition.substituting_node = methodNameToVisit; visit(methodNameToVisit); } break; } case LambdaProcessingState.ClosuresProcessingPhase: { #if DEBUG //var s = "begin "+_function_lambda_definition.lambda_name + " "+ _function_lambda_definition.parameters.expressions[0] + "\n"; //System.IO.File.AppendAllText("d:\\bb17.txt", s); #endif ProcedureForLambdaAndVisit(_function_lambda_definition, null, null); LambdaHelper.RemoveLambdaInfoFromCompilationContext(context, _function_lambda_definition); ret.return_value((semantic_node)LambdaHelper.GetTempFunctionNodeForTypeInference(_function_lambda_definition, this)); break; } case LambdaProcessingState.ClosuresProcessingVisitGeneratedClassesPhase: { ProcedureForLambdaAndVisit(_function_lambda_definition, null, null); break; } case LambdaProcessingState.None: { if (context.converting_block() == block_type.namespace_block) { var methodNameToVisit = (ident)ProcedureForLambdaAndVisit(_function_lambda_definition, null, null); _function_lambda_definition.substituting_node = methodNameToVisit; visit(methodNameToVisit); } break; } } } finally { stflambda.Pop(); #if DEBUG /*if (lambdaProcessingState == LambdaProcessingState.ClosuresProcessingPhase) { ccc -= 2; var s = new string(' ', ccc) + "end " + _function_lambda_definition.lambda_name + " " + _function_lambda_definition.parameters.expressions[0] + "\n"; System.IO.File.AppendAllText("d:\\bb3.txt", s); }*/ #endif } } public override void visit(SyntaxTree.function_lambda_call _function_lambda_call) { SyntaxTree.op_type_node _op_type_node = new SyntaxTree.op_type_node(SyntaxTree.Operators.Assignment); for (int i = 0; i < _function_lambda_call.parameters.expressions.Count; i++) { SyntaxTree.assign _assign = new SyntaxTree.assign(_function_lambda_call.f_lambda_def.parameters.expressions[i] as SyntaxTree.addressed_value, _function_lambda_call.parameters.expressions[i] as SyntaxTree.expression, _op_type_node.type); ((SyntaxTree.statement_list)_function_lambda_call.f_lambda_def.proc_body).subnodes.Insert(0, _assign); _assign.source_context = _function_lambda_call.source_context; } SyntaxTree.expression_list el = new SyntaxTree.expression_list(); for (int i = 0; i < _function_lambda_call.f_lambda_def.formal_parameters.params_list.Count; i++) if (i < _function_lambda_call.parameters.expressions.Count) el.expressions.Add(_function_lambda_call.parameters.expressions[i]); else { el.expressions.Add(new SyntaxTree.ident(_function_lambda_call.f_lambda_def.formal_parameters.params_list[i].idents.idents[0].name, _function_lambda_call.source_context)); } SyntaxTree.method_call _method_call = new SyntaxTree.method_call(el); _method_call.source_context = _function_lambda_call.source_context; if (_method_call is SyntaxTree.dereference) { ((SyntaxTree.dereference)_method_call).dereferencing_value = (SyntaxTree.addressed_value)(new SyntaxTree.ident(_function_lambda_call.f_lambda_def.lambda_name, _function_lambda_call.source_context)); } _method_call.visit(this); } public void lambda_header_visit(SymbolInfo si, SyntaxTree.function_header _function_header, type_node tn1) { type_node tn = null; if (_function_header.return_type == null) { if (context.top_function.IsOperator) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); } if (_function_header.return_type != null) { check_parameter_on_complex_type(_function_header.return_type); if (tn1 != null) tn = tn1; else tn = convert_strong(_function_header.return_type); //if (tn == SystemLibrary.SystemLibrary.void_type) // AddError(new VoidNotValid(get_location(_function_header.return_type))); check_for_type_allowed(tn, get_location(_function_header.return_type)); } //(ssyy) moved up, так как при проверке аттрибута override надо знать тип возвращаемого значения context.top_function.return_value_type = tn; assign_doc_info(context.top_function, _function_header); if (_function_header.attributes != null) { make_attributes_for_declaration(_function_header, context.top_function); } if (context.converted_type != null && has_dll_import_attribute(context.top_function)) AddError(get_dll_import_attribute(context.top_function).location, "DLLIMPORT_ATTRIBUTE_CANNOT_BE_APPLIED_TO_METHOD"); if (_function_header.name.class_name != null) with_class_name = true; if (_function_header.class_keyword && !has_static_attr(_function_header.proc_attributes.proc_attributes)) { SyntaxTree.procedure_attribute pa = new SyntaxTree.procedure_attribute(PascalABCCompiler.SyntaxTree.proc_attribute.attr_static); pa.source_context = _function_header.source_context; _function_header.proc_attributes.proc_attributes.Add(pa); } weak_node_test_and_visit(_function_header.proc_attributes); if (context.top_function.IsOperator) { common_method_node cmmn = context.top_function as common_method_node; //if (cmmn == null) //{ // throw new OverloadOperatorMustBeStaticFunction(get_location(_function_header), context.top_function); //} if (cmmn != null && cmmn.polymorphic_state != SemanticTree.polymorphic_state.ps_static) { AddError(get_location(_function_header), "OVERLOADED_OPERATOR_MUST_BE_STATIC_FUNCTION"); } if (cmmn != null && (cmmn.name == StringConstants.implicit_operator_name || cmmn.name == StringConstants.explicit_operator_name)) if (!convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.comperehensive_type as type_node) && !convertion_data_and_alghoritms.eq_type_nodes(cmmn.comperehensive_type as type_node, cmmn.parameters[0].type)) { AddError(get_location(_function_header.return_type), "RETURN_VALUE_SHOULD_HAVE_TYPE_{0}", (cmmn.comperehensive_type as type_node).PrintableName); } else if (convertion_data_and_alghoritms.eq_type_nodes(tn, cmmn.parameters[0].type)) { AddError(get_location(_function_header), "CIRCURAL_TYPE_CONVERSION_DEFINITION"); } } with_class_name = false; if (context.top_function != null && context.top_function is common_namespace_function_node && (context.top_function as common_namespace_function_node).ConnectedToType != null && !context.top_function.IsOperator) { concrete_parameter_type cpt = concrete_parameter_type.cpt_none; SemanticTree.parameter_type pt = PascalABCCompiler.SemanticTree.parameter_type.value; if ((context.top_function as common_namespace_function_node).ConnectedToType.is_value_type) { cpt = concrete_parameter_type.cpt_var; pt = PascalABCCompiler.SemanticTree.parameter_type.var; } common_parameter cp = new common_parameter(StringConstants.self_word, (context.top_function as common_namespace_function_node).ConnectedToType, pt, context.top_function, cpt, null, null); context.top_function.parameters.AddElementFirst(cp); context.top_function.scope.AddSymbol(StringConstants.self_word, new SymbolInfo(cp)); } CheckOverrideOrReintroduceExpectedWarning(get_location(_function_header)); bool unique = context.close_function_params(body_exists); if (context.top_function.return_value_type == null) AddError(get_location(_function_header), "FUNCTION_NEED_RETURN_TYPE"); if (_function_header.where_defs != null) { if (unique) { visit_where_list(_function_header.where_defs); } else { AddError(get_location(_function_header.where_defs), "WHERE_SECTION_MUST_BE_ONLY_IN_FIRST_DECLARATION"); } } convertion_data_and_alghoritms.create_function_return_variable(context.top_function, si); /*if (_function_header.name != null && context.converted_compiled_type != null && context.top_function is common_namespace_function_node) { if (context.FindMethodToOverride(context.top_function as common_namespace_function_node) != null) AddError(new CanNotDeclareExtensionMethodAsOverrided(get_location(_function_header))); }*/ //TODO: Разобрать подробнее. if (!body_exists) { if ((context.top_function.semantic_node_type == semantic_node_type.common_method_node) || ((context.func_stack_size_is_one()) && (_is_interface_part))) { context.leave_block(); } } body_exists = false; } public override void visit(SyntaxTree.lambda_inferred_type lit) //lroman// { return_value(lit.real_type as type_node); } public override void visit(SyntaxTree.semantic_check sem) { if (sem == null) return; switch (sem.CheckName) { case "ExprIsInteger": var ex = (SyntaxTree.expression)sem.param[0]; expression_node en = convert_strong(ex); en.location = get_location(ex); if (en.type != SystemLibrary.SystemLibrary.integer_type) AddError(get_location(ex), "STRING_CONSTANT_OR_IDENTIFIER_EXPECTED"); break; case " ": break; case " ": break; } } public override void visit(SyntaxTree.same_type_node st) // SSM 22/06/13 { expression_node en = convert_strong(st.ex); if (en == null) AddError(get_location(st.ex),"CANNOT_EVALUATE_FUNCTION_TYPE"); return_value(en.type); } public type_node try_calc_expr_type(SyntaxTree.expression ex) // SSM 10.07.13 { try { expression_node en = convert_strong(ex); return en.type; } catch (Exception e) { return new undefined_type("#UndefType", null); } } public override void visit(SyntaxTree.semantic_type_node stn) { return_value(stn.type as type_node); } // SSM 10.01.16 впервые для реализации Tuple - t[0] public override void visit(SyntaxTree.semantic_addr_value sav) { return_value(sav.expr as expression_node); } public bool SameTypeAutoClasses(List names, List types, common_type_node t) { if (t.properties.Count() != names.Count()) return false; var tnames = t.properties.Select(tt => tt.name); return types.SequenceEqual(t.fields.Select(tt => tt.type)) && names.SequenceEqual(tnames, StringComparer.OrdinalIgnoreCase); //return true; } public override void visit(SyntaxTree.unnamed_type_object unn) // SSM 27.06.13 { var l = unn.ne_list; var names = l.name_expr.Select(x=>x.name).ToList(); var strnames = names.Select(id=>id.name).ToList(); // преобразование idents в строки /*var tt1 = l.name_expr[0].expr; var tse = convert_strong(tt1);*/ var semantic_exprs = l.name_expr.Select(x => convert_strong(x.expr)).ToList(); for (var i = 0; i < semantic_exprs.Count; i++) { var ex = semantic_exprs[i]; try_convert_typed_expression_to_function_call(ref ex); semantic_exprs[i] = ex; } var semantic_types = semantic_exprs.Select(x => x.type).ToList(); var types = semantic_types.Select(x => SyntaxTreeBuilder.BuildSemanticType(x)).ToList(); contextChanger.SaveContextAndUpToGlobalLevel(); var tt = context._cmn.types.Where(t => t.name.StartsWith("AnonymousType#")); // найти все анонимные типы, полученные в текущей компиляции var typ = tt.FirstOrDefault(t => SameTypeAutoClasses(strnames, semantic_types, t)); // найти структурно совпадающий уже существующий анонимный тип // Генерация глобальных описаний - перенесена с синтаксического уровня if (typ != null) unn.set_name(typ.name); // если нашли, то просто меняем имя на имя этого класса else { var td = SyntaxTreeBuilder.BuildAutoClass(unn.name(), names, types, unn.is_class); visit(td); } contextChanger.RestoreCurrentContext(); // Сахарный узел. Переадресация дальнейшей генерации узлу new_ex visit(unn.new_ex); } public override void visit(SyntaxTree.short_func_definition def) // SSM 20.07.13 { // Сахарный узел. Переадресация дальнейшей генерации узлу procedure_definition visit(def.procdef); } public override void visit(matching_expression _matching_expression) { throw new NotSupportedError(get_location(_matching_expression)); } public override void visit(SyntaxTree.sequence_type _sequence_type) // сахарный узел { var pt = _sequence_type.elements_type.DescendantNodes(TraversalType.PostOrder,null,true).FirstOrDefault(s => s is procedure_header); if (pt != null) { AddError(get_location(pt), "PROCEDURE_TYPE_SHOULD_BE_REPLACED_BY_TYPE_NAME_IN_THIS_CONTEXT"); } // SSM 11/05/15 sugared node var l = new List(); l.Add(new ident("?System")); l.Add(new ident("Collections")); l.Add(new ident("Generic")); l.Add(new ident("IEnumerable")); var tr = new template_type_reference(new named_type_reference(l), new template_param_list(_sequence_type.elements_type, _sequence_type.elements_type.source_context), _sequence_type.source_context); visit(tr); } public override void visit(SyntaxTree.modern_proc_type _modern_proc_type) // сахарный узел { if (_modern_proc_type.res != null) { var l = new List(); l.Add(new ident("?System")); l.Add(new ident("Func")); var t = new template_param_list(); if (_modern_proc_type.aloneparam != null) t.Add(_modern_proc_type.aloneparam); if (_modern_proc_type.el != null) { var en = _modern_proc_type.el; //if (en.enumerators.Count == 1) // AddError(get_location(en.enumerators[0].name), "ONE_TYPE_PARAMETER_MUSTBE_WITHOUT_PARENTHESES"); for (int i = 0; i < en.enumerators.Count; i++) { if (en.enumerators[i].value != null) AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER"); //if (!(en.enumerators[i].name is named_type_reference) && !(en.enumerators[i].name is array_type)) // AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER"); t.Add(en.enumerators[i].name); // ??????????????? } } t.Add(_modern_proc_type.res, _modern_proc_type.res.source_context); t.source_context = _modern_proc_type.source_context; var ttr = new template_type_reference(new named_type_reference(l), t, _modern_proc_type.source_context); visit(ttr); } else if (_modern_proc_type.aloneparam != null || _modern_proc_type.el != null) { var l = new List(); l.Add(new ident("?System")); l.Add(new ident("Action")); var t = new template_param_list(); if (_modern_proc_type.aloneparam != null) t.Add(_modern_proc_type.aloneparam); if (_modern_proc_type.el != null) { var en = _modern_proc_type.el; //if (en.enumerators.Count == 1) // AddError(get_location(en.enumerators[0].name), "ONE_TYPE_PARAMETER_MUSTBE_WITHOUT_PARENTHESES"); for (int i = 0; i < en.enumerators.Count; i++) { if (en.enumerators[i].value != null) AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER"); //if (!(en.enumerators[i].name is named_type_reference) && !(en.enumerators[i].name is array_type)) // AddError(get_location(en.enumerators[i].name), "ONE_TKIDENTIFIER"); t.Add(en.enumerators[i].name); } } t.source_context = _modern_proc_type.source_context; var ttr = new template_type_reference(new named_type_reference(l), t, _modern_proc_type.source_context); visit(ttr); } else { var l = new List(); l.Add(new ident("?System")); l.Add(new ident("Action")); var ntr = new named_type_reference(l); visit(ntr); } } // Это в куче мест надо. Потому что либо compiled_type_node, либо compiled_generic_instance_type_node // compiled_type_node если в записи A все типы NETовские // compiled_generic_instance_type_node если в записи A хоть один тип - паскалевский public Type ConvertSemanticTypeNodeToNETType(type_node tn) { if (tn is compiled_generic_instance_type_node) { var tnc = (tn as compiled_generic_instance_type_node); var itnc = tnc.original_generic as compiled_type_node; var tt = itnc.compiled_type; if (tt.IsGenericType) tt = tt.GetGenericTypeDefinition(); return tt; } else if (tn is compiled_type_node) { var itnc = (tn as compiled_type_node); var tt = itnc.compiled_type; if (tt.IsGenericType) tt = tt.GetGenericTypeDefinition(); return tt; } return null; } /*expression_list construct_expression_list_for_slice_expr(SyntaxTree.slice_expr sl) { // situation = 0 - ничего не пропущено // situation = 1 - пропущен from // situation = 2 - пропущен to // situation = 3 - пропущены from и to // Пропущенность кодируется тем, что в соответствующем поле - int.MaxValue // step может просто отсутствовать - это параметр по умолчанию в SystemSlice int situation = 0; if ((sl.from is int32_const) && (sl.from as int32_const).val == int.MaxValue) situation += 1; if ((sl.to is int32_const) && (sl.to as int32_const).val == int.MaxValue) situation += 2; var el = new SyntaxTree.expression_list(); el.Add(new int32_const(situation)); el.Add(sl.from); // Это плохо - считается 2 раза. Надо делать semantic_expr_node !!!? Нет!!! // Если там будет лямбда, то не будет работать - известно, что semantic_expr_node не работает с лямбдами // т.к. они несколько раз обходят код. el.Add(sl.to); if (sl.step != null) el.Add(sl.step); return el; }*/ // frninja 04/03/16 - для yield // frninja 06/06/16 - фикс для видимости private методов и полей с классов в том же модуле private unit_node GetUnknownIdentUnit(definition_node dn) { if (dn is class_field) { return ((dn as class_field).cont_type.comprehensive_namespace != null) ? (dn as class_field).cont_type.comprehensive_namespace.cont_unit : null; } else if (dn is common_method_node) { return ((dn as common_method_node).cont_type.comprehensive_namespace != null) ? (dn as common_method_node).cont_type.comprehensive_namespace.cont_unit : null; } else if (dn is common_property_node) { return ((dn as common_property_node).common_comprehensive_type.comprehensive_namespace != null) ? (dn as common_property_node).common_comprehensive_type.comprehensive_namespace.cont_unit : null; } return null; } // end frninja 06/06/16 private bool CheckIsStaticName(definition_node dn) { if (dn is class_field && (dn as class_field).polymorphic_state == SemanticTree.polymorphic_state.ps_static) return true; if (dn is common_method_node && (dn as common_method_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static) return true; if (dn is common_property_node && (dn as common_property_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static) return true; if (dn is compiled_function_node && (dn as compiled_function_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static) return true; if (dn is compiled_property_node && (dn as compiled_property_node).polymorphic_state == SemanticTree.polymorphic_state.ps_static) return true; return false; } private bool CheckUnknownIdentNeedsClassCapture(SyntaxTree.yield_unknown_ident _unk, out bool isStaticIdent) { string Consts__Self = yieldSelf; // Find semantic class containing iterator (yield-method) with unknown ident var iteratorContainingClass = context._ctn.fields.Where(f => f.name == Consts__Self).FirstOrDefault()?.type; //var iteratorContainingClass = context._cmn.types.Where(t => t.name == _unk.ClassName.name).First(); isStaticIdent = false; if (iteratorContainingClass != null) { // Search for unknown ident in class var found = iteratorContainingClass.find(_unk.UnknownID.name); if (found != null) { // class_field - поле класса // common_method_node - метод класса // common_property_node - свойство класса // че там с .NET как базовым? // compiled_function_node - метод базового .NET класса // compiled_property_node - свойство базового .NET класса // че с классом из другого модуля? // то же что и с классом из этого же var found_unit = found.FirstOrDefault(); isStaticIdent = CheckIsStaticName(found_unit.sym_info); if (found_unit.sym_info is class_field || found_unit.sym_info is class_constant_definition // SSM #2152 || found_unit.sym_info is common_method_node || found_unit.sym_info is common_property_node || found_unit.sym_info is compiled_function_node || found_unit.sym_info is compiled_property_node) { if (!isStaticIdent && _unk.IsYieldInStaticMethod) return false; // frninja 06/06/16 - фиксим private того же модуля if ((iteratorContainingClass is common_type_node) && this.GetUnknownIdentUnit(found_unit.sym_info) == (((iteratorContainingClass as common_type_node).comprehensive_namespace != null) ? (iteratorContainingClass as common_type_node).comprehensive_namespace.cont_unit : null)) { return true; } else if (found_unit.access_level != access_level.al_private) { return true; } } // common_namespace_function_node - глобальный метод } } return false; } private dot_node CaptureUnknownIdent(yield_unknown_ident unk, bool isStaticIdent = false) { if (isStaticIdent) { return new dot_node(unk.ClassName, unk.UnknownID); } return new dot_node(new dot_node(new ident("self"), new ident(yieldSelf)), unk.UnknownID); } private SyntaxTree.addressed_value_funcname ProcessUnknownIdent(yield_unknown_ident unk) { bool isStaticIdent; if (CheckUnknownIdentNeedsClassCapture(unk, out isStaticIdent)) { var uid = CaptureUnknownIdent(unk, isStaticIdent); return uid; } else { return unk.UnknownID; } } public override void visit(SyntaxTree.yield_node yn) { // надо что то сгенерировать, иначе выдается ложное предупреждение о недостижимом коде и проч. /*var ass = new assign("Result", new nil_const()); visit(ass); var pc = new procedure_call("exit"); visit(pc);*/ } // frninja - захват полей класса для yield public override void visit(SyntaxTree.yield_unknown_ident _unk) { ProcessUnknownIdent(_unk).visit(this); } public override void visit(SyntaxTree.yield_unknown_expression_type _unk_expr) { // Отвечает за типизацию всех переменных с автовыведением типа // Пробую сделать по-другому: перевести в auto_type и потом на присваивании перехватить var t = new semantic_type_node(new auto_type(get_location(_unk_expr))); t.visit(this); } // frninja 29/05/16 - выявляем тип перемнной в foreach public override void visit(SyntaxTree.yield_unknown_foreach_type _unk) { var t = new semantic_type_node(new ienumerable_auto_type(get_location(_unk))); t.visit(this); } public override void visit(SyntaxTree.dot_question_node dqn) { // a?.b AddError(get_location(dqn), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", dqn.GetType().Name); //var q = ConvertToQCE(dqn); //visit(q); } public override void visit(SyntaxTree.semantic_check_sugared_statement_node st) { /*if (st.visited) return; st.visited = true;*/ if (st.typ as System.Type == typeof(SyntaxTree.for_node)) // плохо то, что многие преобразования синт сахара могут использовать for_node { var expr1 = convert_strong(st.lst[0] as expression); var expr2 = convert_strong(st.lst[1] as expression); CheckOrdinaryType(expr1); CheckOrdinaryType(expr2); if (!convertion_data_and_alghoritms.can_convert_type(expr2,expr1.type)) AddError(new CanNotConvertTypes(expr2, expr2.type, expr1.type, expr2.location)); ; } else if (st.typ as System.Type == typeof(SyntaxTree.assign_tuple)) { var vars = st.lst[0] as SyntaxTree.addressed_value_list; var expr = st.lst[1] as SyntaxTree.expression; semantic_check_assign_tuple(vars, expr); } else if (st.typ as System.Type == typeof(SyntaxTree.assign_var_tuple)) { var idents = st.lst[0] as SyntaxTree.ident_list; var expr = st.lst[1] as SyntaxTree.expression; semantic_check_assign_var_tuple(idents, expr); } else if (st.typ as System.Type == typeof(SyntaxTree.loop_stmt)) { var expr = st.lst[0] as SyntaxTree.expression; semantic_check_loop_stmt(expr); } else if (st.typ as System.Type == typeof(SyntaxTree.foreach_stmt) && st.lst.Count == 3) // для NewRange Visitorа. Если будет перекрытие, то надоделать новые типы-маркеры { var expr = st.lst[0] as SyntaxTree.diapason_expr_new; var td = st.lst[1] as SyntaxTree.type_definition; var id = st.lst[2] as SyntaxTree.ident; semantic_check_for_new_range(expr, td, id); } /*else if (st.typ as System.Type == typeof(SyntaxTree.foreach_stmt) && st.lst.Count == 1) // для a.Indices. Пока непонятно, где описывать тип-маркер { var expr = st.lst[0] as SyntaxTree.expression; semantic_check_for_indices(expr); }*/ // Patterns else if (st.typ is SemanticCheckType && (SemanticCheckType)st.typ == SemanticCheckType.MatchedExpression) // Это безобразие - SemanticCheckType в TreeHelper.cs помещать!!! { var expr = st.lst[0] as expression; CheckMatchedExpression(expr); } else if (st.typ is SemanticCheckType && (SemanticCheckType)st.typ == SemanticCheckType.MatchedExpressionAndType) { var expr = st.lst[0] as expression; var type = st.lst[1] as type_definition; CheckIfCanBeMatched(expr, type); } else if (st.typ is SemanticCheckType && (SemanticCheckType)st.typ == SemanticCheckType.MatchedExpressionAndExpression) { var matchedExpr = st.lst[0] as expression; var patternExpr = st.lst[1] as expression; CheckIfCanBeMatched(matchedExpr, patternExpr); } else if (st.typ is SemanticCheckType && (SemanticCheckType)st.typ == SemanticCheckType.MatchedTuple) { var tuple = st.lst[0] as expression; var length = st.lst[1] as int32_const; CheckIfCanBeMatched(tuple, length); } // !Patterns // Slices else if (st.typ is SemanticCheckType && (SemanticCheckType)st.typ == SemanticCheckType.SliceAssignmentTypeCompatibility) { var to = st.lst[0] as expression; var from = st.lst[1] as expression; var mc = st.lst[2] as method_call; semantic_check_slice_assignment_types(to, from, mc); } else if (st.typ as System.Type == typeof(semantic_check_delegates_pointers_in_cached_function)) { var parameters = st.lst[0] as formal_parameters; var types = parameters.params_list.Select(p => p.vars_type); foreach (var tp in types) { var sem_type = convert_strong(tp); if (sem_type.IsDelegate) { AddError(sem_type.location, "FUNCTIONS_WITH_CACHE_ATTRIBUTE_SHOULD_NOT_HAVE_DELEGATES_AS_PARAMETERS"); break; } } } // !Slices else { AddError(get_location(st), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", (st.typ as System.Type)?.Name ?? "Unknown"); } ret.reset(); // обязательно очистить - этот узел в семантику ничего не должен приносить! ReplaceUsingParent(st, new PascalABCCompiler.SyntaxTree.empty_statement()); } public override void visit(SyntaxTree.semantic_check_sugared_var_def_statement_node st) { if (st.typ as System.Type == typeof(SyntaxTree.assign_var_tuple)) { var idents = st.lst[0] as SyntaxTree.ident_list; var expr = st.lst[1] as SyntaxTree.expression; semantic_check_assign_var_tuple(idents, expr); } else { AddError(get_location(st), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", (st.typ as System.Type)?.Name ?? "Unknown"); } ret.reset(); // обязательно очистить - этот узел в семантику ничего не должен приносить! } public override void visit(SyntaxTree.sugared_expression ex) { if (ex.sugared_expr is SyntaxTree.template_param_list tpl) // это в [Cache] { foreach (var tp in tpl.params_list) { var sem_type = convert_strong(tp); if (sem_type.IsPointer) { AddError(sem_type.location, "FUNCTIONS_WITH_CACHE_ATTRIBUTE_SHOULD_NOT_HAVE_POINTERS_AS_PARAMETERS"); break; } } } else { AddError(get_location(ex), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", ex.sugared_expr.GetType().Name); } ProcessNode(ex.new_expr); // обойти десахарное выражение - обязательно ProcessNode - visit нельзя! } public method_call ToNullable(expression e) { var dn = new dot_node(new ident(StringConstants.pascalSystemUnitName), new ident("DQNToNullable")); return new method_call(dn, new expression_list(e), e.source_context); } public override void visit(SyntaxTree.sugared_addressed_value av) { if (av.sugared_expr is SyntaxTree.diapason_expr_new) { semantic_check_method_call_as_diapason_expr(av.new_addr_value as SyntaxTree.method_call); } else if (av.sugared_expr is SyntaxTree.slice_expr slex) // и slice_expr_question { if (slex.slices == null) semantic_check_method_call_as_slice_expr(av.new_addr_value as SyntaxTree.method_call); else semantic_check_method_call_as_slice_expr_multi(av.new_addr_value as SyntaxTree.method_call); } else if (av.sugared_expr is SyntaxTree.dot_question_node) { var qce = av.new_addr_value as SyntaxTree.question_colon_expression; var av_cs = convert_strong(qce.ret_if_false); try_convert_typed_expression_to_function_call(ref av_cs); if (!type_table.is_with_nil_allowed(av_cs.type)) { var dn = new dot_node(new ident(StringConstants.pascalSystemUnitName), new ident("DQNToNullable")); (av.new_addr_value as SyntaxTree.question_colon_expression).ret_if_false = new method_call(dn, new expression_list((av.new_addr_value as SyntaxTree.question_colon_expression).ret_if_false), av.source_context); /*var avqce = av.new_addr_value as SyntaxTree.question_colon_expression; //var dn = new dot_node(new ident("PABCSystem"), new ident("DQNToNullable")); avqce.ret_if_false = ToNullable(avqce.ret_if_false); //new method_call(dn, new expression_list(avqce.ret_if_false), av.source_context);*/ } semantic_check_dot_question(av.new_addr_value as SyntaxTree.question_colon_expression); } else if (av.sugared_expr is SyntaxTree.bin_expr) // Это пришло от i in (2..5). Плохо, что могут быть другие bin_expr { semantic_check_method_call_as_inrange_expr(av.new_addr_value as SyntaxTree.method_call); } else { AddError(get_location(av), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", av.sugared_expr.GetType().Name); } ProcessNode(av.new_addr_value); // обойти десахарное } public bool IsTupleType(Type t) { return !t.IsArray && (t.FullName.StartsWith("System.Tuple") || t.FullName.StartsWith("System.ValueTuple")); } public bool IsKeyValuePairType(Type t) { return t.FullName.StartsWith("System.Collections.Generic.KeyValuePair`2"); } public bool IsSequenceType(Type t) { return t.Name.Equals("IEnumerable`1") || t.GetInterface("IEnumerable`1") != null; } /*private void CheckUnpacking(expression ex, out expression_node sem_ex, out bool IsTuple, out bool IsSequence, int countvars, syntax_tree_node stn) { sem_ex = convert_strong(ex); sem_ex = convert_if_typed_expression_to_function_call(sem_ex); var t = ConvertSemanticTypeNodeToNETType(sem_ex.type); if (t == null) AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); IsTuple = IsTupleType(t); IsSequence = !IsTuple && IsSequenceType(t); if (!IsTuple && !IsSequence) { AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); } if (IsTuple) { if (countvars > t.GetGenericArguments().Count()) AddError(get_location(stn), "TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT"); } } private addressed_value UnpackingExpr(int i, bool IsTuple, bool IsSequence, string tname) { addressed_value dn = null; if (IsTuple) dn = new dot_node(new ident(tname), new ident("Item" + (i + 1).ToString())); else if (IsSequence) { dn = new dot_node(new ident(tname), new ident("ElementAt")); var pars = new SyntaxTree.expression_list(new int32_const(i)); dn = new method_call(dn, pars); } return dn; }*/ public override void visit(SyntaxTree.assign_tuple asstup) // сахарный узел { AddError(get_location(asstup), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", asstup.GetType().Name); // На семантике тяжело делать сахар с определениями переменных, которые потом захватываются лямбдами: var (m,n) := t; ArrGen(x->x+m); // Перенесено на синтаксис с генерацией узла semantic_ith_element_of, разворачивающегося на семантике /*CheckUnpacking(asstup.expr, out var sem_ex, out var IsTuple, out var IsSequence, asstup.vars.variables.Count(), asstup.vars); var sem_node = new SyntaxTree.semantic_addr_value(sem_ex); // чтобы два раза не делать convert_strong //semantic_check_assign_tuple(asstup.vars, asstup.expr); var tname = "#temp_var" + UniqueNumStr(); var tt = new var_statement(new ident(tname), sem_node; // тут semantic_addr_value хранит на самом деле expr - просто неудачное название var st = new statement_list(); st.Add(tt); var n = asstup.vars.variables.Count(); for (var i = 0; i < n; i++) { var a = new assign(asstup.vars.variables[i], //new dot_node(new ident(tname), new ident("Item" + (i + 1).ToString())), UnpackingExpr(i, IsTuple, IsSequence, tname), Operators.Assignment, asstup.vars.variables[i].source_context); st.Add(a); } visit(st);*/ } public override void visit(SyntaxTree.assign_var_tuple assvartup) // сахарный узел { AddError(get_location(assvartup), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", assvartup.GetType().Name); // На семантике тяжело делать сахар с определениями переменных, которые потом захватываются лямбдами: var (m,n) := t; ArrGen(x->x+m); //CheckUnpacking(assvartup.expr, out var sem_ex, out var IsTuple, out var IsSequence, assvartup.idents.idents.Count(), assvartup.idents); /*var sem_ex = convert_strong(assvartup.expr); sem_ex = convert_if_typed_expression_to_function_call(sem_ex); var t = ConvertSemanticTypeNodeToNETType(sem_ex.type); if (t == null) AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); var IsTuple = false; var IsSequence = false; if (IsTupleType(t)) IsTuple = true; if (!IsTuple) { if (IsSequenceType(t)) IsSequence = true; } if (!IsTuple && !IsSequence) { AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); } if (IsTuple) { var nn = assvartup.idents.idents.Count(); if (nn > t.GetGenericArguments().Count()) AddError(get_location(assvartup.idents), "TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT"); }*/ // В зависимости от типа выражения по-разному распаковывать // Распаковывать можно только для кортежей или последовательностей // if IsTuple ... // if IsSequence ... // else AddError(либо кортеж либо последовательность) /*var sem_node = new SyntaxTree.semantic_addr_value(sem_ex); // чтобы два раза не делать convert_strong //semantic_check_assign_var_tuple(assvartup.idents, sem_node); var tname = "#temp_var" + UniqueNumStr(); var tt = new var_statement(new ident(tname), sem_node); var sl = new statement_list(); sl.Add(new SyntaxTree.empty_statement()); sl.Add(tt); var n = assvartup.idents.idents.Count(); for (var i = 0; i < n; i++) { var rr = assvartup.idents.idents[i] as ident; var a = new var_statement(rr, //new dot_node(new ident(tname),new ident("Item" + (i + 1).ToString())), //dn, UnpackingExpr(i, IsTuple, IsSequence, tname), assvartup.idents.idents[i].source_context ); sl.Add(a); } //assvartup.sl = sl; ReplaceStatementUsingParent(assvartup, sl.list); // добавляем пустой оператор чтобы здесь его пропустить, а обходить следующие //sl.IsInternal = true; //ReplaceUsingParent(assvartup, sl); // меняем один оператор на один. На 2 и 3 проходе лямбды обходится именно он //visit_statement_list_internal(sl);*/ } public override void visit(semantic_ith_element_of ith) { var IsSequence = false; var IsTuple = false; var IsKeyValuePair = false; var sem_ex = convert_strong(ith.id); sem_ex = convert_if_typed_expression_to_function_call(sem_ex); var t = ConvertSemanticTypeNodeToNETType(sem_ex.type); if (t == null) { bool bb; type_node elem_type = null; var b = FindIEnumerableElementType(sem_ex.type, ref elem_type, out bb); if (b) // Не очень понятно, зачем это нужно. И это точно не срабатывает IsSequence = true; else AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); } if (t != null) IsTuple = IsTupleType(t); if (t != null) IsKeyValuePair = !IsTuple && IsKeyValuePairType(t); if (t != null) IsSequence = !IsTuple && !IsKeyValuePair && IsSequenceType(t); if (!IsTuple && !IsSequence && !IsKeyValuePair) { AddError(sem_ex.location, "TUPLE_OR_SEQUENCE_EXPECTED"); } //addressed_value dn = null; var i = (ith.index as int32_const).val; if (IsTuple) { var dn = new dot_node(ith.id.TypedClone(), new ident("Item" + (i + 1).ToString())); ReplaceUsingParent(ith, dn); visit(dn); } else if (IsSequence) { var dn = new dot_node(ith.id.TypedClone(), new ident("ElementAt")); var pars = new SyntaxTree.expression_list(new int32_const(i)); var mc = new method_call(dn, pars); ReplaceUsingParent(ith, mc); visit(mc); } else if (IsKeyValuePair) { var meth_name = i == 0 ? "Key" : "Value"; var dn = new dot_node(ith.id.TypedClone(), new ident(meth_name)); ReplaceUsingParent(ith, dn); visit(dn); } } public override void visit(var_tuple_def_statement vtd) { AddError(get_location(vtd), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", vtd.GetType().Name); // На семантике тяжело делать сахар с определениями переменных, которые потом захватываются лямбдами: var (m,n) := t; ArrGen(x->x+m); // Состоит из var_def_statements. Некоторые являются var_tuple_def_statement // Их надо найти и сделать несколько секций variable_definitions - без семантических проверок. // Каждую var_tuple_def_statement надо заменить на assign_var_tuple - одну на секцию variable_definitions // А потом оставшаяся часть визитора сделает семантические проверки /*CheckUnpacking(vtd.inital_value, out var sem_ex, out var IsTuple, out var IsSequence, vtd.vars.idents.Count(), vtd.vars); var sem_node = new SyntaxTree.semantic_addr_value(sem_ex); // чтобы два раза не делать convert_strong //semantic_check_assign_var_tuple(vtd.vars, vtd.inital_value); var tname = "#temp_var" + UniqueNumStr(); //var vd = new List(); //vd.Add(new semantic_check_sugared_var_def_statement_node(typeof(assign_var_tuple), new List { vtd.vars, vtd.inital_value }, vtd.source_context)); // Это нужно для проверок на этапе преобразования в семантику //visit(vd[0]); var tt1 = new var_def_statement(new ident(tname), vtd.inital_value); ProcessNode(tt1); var nn = vtd.vars.idents.Count(); for (var i = 0; i < nn; i++) { var a = new var_def_statement(vtd.vars.idents[i], UnpackingExpr(i, IsTuple, IsSequence, tname), //new dot_node(new ident(tname), new ident("Item" + (i + 1).ToString())), vtd.vars.idents[i].source_context); ProcessNode(a); }*/ } public void ReplaceVarTupleDefStatementUsingParent(var_tuple_def_statement from, IEnumerable to) { foreach (var x in to) x.Parent = from.Parent; var sl = from.Parent as variable_definitions; if (sl != null) { sl.ReplaceInList(from, to); } } public override void visit(SyntaxTree.slice_expr sl) // сахарный узел { AddError(get_location(sl), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", sl.GetType().Name); /* // Преобразуется в вызов a.SystemSlice(situation,from,to,step) // Тип a должен быть array of T, List или string semcheck(sl); // Действия уровня синтаксиса. Можно вынести на синтаксический уровень как desugaring для сахарного узла var el = construct_expression_list_for_slice_expr(sl); var mc = new method_call(new dot_node(sl.v, new ident("SystemSlice", sl.v.source_context), sl.v.source_context), el, sl.source_context); visit(mc);*/ } public override void visit(SyntaxTree.slice_expr_question sl) // сахарный узел { AddError(get_location(sl), "SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR", sl.GetType().Name); /* // Преобразуется в вызов a.SystemSlice(situation,from,to,step) // Тип a должен быть array of T, List или string semcheck(sl); var el = construct_expression_list_for_slice_expr(sl); var mc = new method_call(new dot_node(sl.v, new ident("SystemSliceQuestion", sl.v.source_context), sl.v.source_context), el, sl.source_context); visit(mc);*/ } public override void visit(SyntaxTree.expression_with_let _ex_with_let) { } public override void visit(SyntaxTree.ref_var_def_statement rf) { } } }