public override void visit(procedure_definition pd) { hasYields = false; if (pd.proc_header is function_header) { mids = new FindMainIdentsVisitor(); } base.visit(pd); if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо. { return; } var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать LoweringVisitor.Accept(pd); var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code); cfa.Transform(); (pd.proc_body as block).program_code = cfa.res; // Конструируем определение класса var cct = GenClassesForYield(pd, dld.LocalDeletedDefs); // все удаленные описания переменных делаем описанием класса UpperNodeAs <declarations>().InsertBefore(pd, cct); mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }
public override void visit(procedure_definition pd) { // frninja // DEBUG for test // SORRY // Classification ISet<string> CollectedLocalsNames = new HashSet<string>(); ISet<string> CollectedFormalParamsNames = new HashSet<string>(); ISet<string> CollectedClassFieldsNames = new HashSet<string>(); ISet<string> CollectedClassMethodsNames = new HashSet<string>(); ISet<string> CollectedClassPropertiesNames = new HashSet<string>(); ISet<string> CollectedUnitGlobalsNames = new HashSet<string>(); ISet<var_def_statement> CollectedLocals = new HashSet<var_def_statement>(); ISet<var_def_statement> CollectedFormalParams = new HashSet<var_def_statement>(); // Map from ident idName -> captured ident idName IDictionary<string, string> CapturedLocalsNamesMap = new Dictionary<string, string>(); IDictionary<string, string> CapturedFormalParamsNamesMap = new Dictionary<string, string>(); hasYields = false; if (pd.proc_header is function_header) mids = new FindMainIdentsVisitor(); base.visit(pd); if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо. return; LoweringVisitor.Accept(pd); // frninja 16/11/15: перенес ниже чтобы работал захват для lowered for var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement // frninja 08/12/15 bool isClassMethod = IsClassMethod(pd); // Collect locals CollectedLocals.UnionWith(dld.LocalDeletedDefs); CollectedLocalsNames.UnionWith(dld.LocalDeletedDefs.SelectMany(vds => vds.vars.idents).Select(id => id.name)); // Collect formal params CollectFormalParams(pd, CollectedFormalParams); CollectFormalParamsNames(pd, CollectedFormalParamsNames); // Collect class fields CollectClassFieldsNames(pd, CollectedClassFieldsNames); // Collect class methods CollectClassMethodsNames(pd, CollectedClassMethodsNames); // Collect class properties CollectClassPropertiesNames(pd, CollectedClassPropertiesNames); // Collect unit globals CollectUnitGlobalsNames(pd, CollectedUnitGlobalsNames); // Create maps :: idName -> captureName CreateCapturedLocalsNamesMap(CollectedLocalsNames, CapturedLocalsNamesMap); CreateCapturedFormalParamsNamesMap(CollectedFormalParamsNames, CapturedFormalParamsNamesMap); // AHAHA test! ReplaceCapturedVariablesVisitor rcapVis = new ReplaceCapturedVariablesVisitor( CollectedLocalsNames, CollectedFormalParamsNames, CollectedClassFieldsNames, CollectedClassMethodsNames, CollectedClassPropertiesNames, CollectedUnitGlobalsNames, CapturedLocalsNamesMap, CapturedFormalParamsNamesMap, isClassMethod ); // Replace (pd.proc_body as block).program_code.visit(rcapVis); mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать // Обработать параметры! // Как? Ищем в mids formal_parametrs, но надо выделить именно обращение к параметрам - не полям класса, не глобальным переменным var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code); cfa.Transform(); (pd.proc_body as block).program_code = cfa.res; // Конструируем определение класса var cct = GenClassesForYield(pd, dld.LocalDeletedDefs, CapturedLocalsNamesMap, CapturedFormalParamsNamesMap); // все удаленные описания переменных делаем описанием класса //UpperNodeAs<declarations>().InsertBefore(pd, cct); if (isClassMethod) { var cd = UpperTo<class_definition>(); if ((object)cd != null) { var td = UpperTo<type_declarations>(); // Insert class predefenition! var iteratorClassPredef = new type_declaration(GetClassName(pd), new class_definition(null)); td.types_decl.Insert(0, iteratorClassPredef); foreach (var helperName in cct.types_decl.Select(ttd => ttd.type_name)) { var helperPredef = new type_declaration(helperName, new class_definition()); td.types_decl.Insert(0, helperPredef); } foreach (var helper in cct.types_decl) { td.types_decl.Add(helper); } //UpperTo<declarations>().InsertAfter(td, cct); } } else { UpperTo<declarations>().InsertBefore(pd, cct); } mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }
public override void visit(procedure_definition pd) { // frninja 14/06/16 - проверяем наличие yield у вложенных методов (и запрещаем ) CheckInnerMethodsWithYield(pd); if (!pd.has_yield) return; // frninja 05/06/16 - вставляем предописание если метод-итератор описан не в классе (обычная функция) чтоб работали рекурсивные вызовы // Нужен также для верной работы <yield_error> функции, проверяющей разные ошибки на этапе семантики // Как только уберу <yield_error>-функцию, от этого тоже можно избавиться bool methodPredefCreated = InsertGlobalIteratorMethodPredefinition(pd); // frninja 24/05/16 - оборачиваем одиночные операторы в begin..end AddBeginEndsVisitor.Accept(pd); /* // Проверяем проблемы имен для for CheckVariablesRedefenitionVisitor checkVarRedefVisitor = new CheckVariablesRedefenitionVisitor( new HashSet<string>( pd.proc_header.parameters != null ? pd.proc_header.parameters.params_list.SelectMany(fp => fp.idents.idents.Select(id => id.name)) : Enumerable.Empty<string>())); pd.visit(checkVarRedefVisitor); */ // Выносим выражение из yield в отдельную переменную ReplaceYieldExprByVarVisitor.Accept(pd); // Раскрываем операторы yield sequence. На семантике они не существуют LoweringYieldSequenceVisitor.Accept(pd); // frninja 31/05/16 - добавляем метод-хелпер, возьмет на себя проверку разных ошибок уже существующим бэкендом CreateErrorCheckerHelper(pd); // SSM 14/07/16 - переставил до переименования переменных чтобы отлавливались ошибки одинаковых имен в разных пространствах имен // SSM - можно сделать спец визитор, который бы отлавливал дубли имен - тогда этого не надо // Переименовываем одинаковые имена в мини-ПИ: begin var a := 1 end; begin var a := 1 end; RenameSameBlockLocalVarsVisitor.Accept(pd); // SSM 01/08/16 - надо захватить и переименовать еще все формальные параметры. // Это решит проблему их изменения в pd при следующем вызове запроса. var bb = pd.proc_body as block; if (pd.proc_header.parameters != null) { var fpids = pd.proc_header.parameters.params_list.SelectMany(tp => tp.idents.idents); foreach (var v in fpids) { var vds = new var_statement(new ident("$fp_"+v.name, v.source_context), v); bb.program_code.AddFirst(vds); } } // Теперь lowering LoweringVisitor.Accept(pd); // frninja 13/04/16 - убираем лишние begin..end DeleteRedundantBeginEnds.Accept(pd); // Обработка метода для корректного захвата локальных переменных и их типов // - это уже не надо - иногда можно включать чтобы посмотреть, что собой представляет функция после Loweringа //IEnumerable<var_def_statement> localsClonesCollection; //CreateLocalVariablesTypeProxies(pd, out localsClonesCollection); // frninja 16/11/15: перенес ниже чтобы работал захват для lowered for var dld = MoveAllLocalDefsToLists.Accept(pd); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement // Строим отображение из локальных переменных клона оригинального метода в локальные переменные основного метода //Dictionary<var_def_statement, var_def_statement> localsCloneMap = CreateLocalsClonesMap(dld.LocalDeletedDefs, localsClonesCollection); // frninja 08/12/15 // Выполняем захват имён IDictionary<string, string> CapturedLocalsNamesMap; IDictionary<string, string> CapturedFormalParamsNamesMap; ReplaceCapturedVariables(pd, dld.LocalDeletedDefs, out CapturedLocalsNamesMap, out CapturedFormalParamsNamesMap); //mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать // Обработать параметры! // Как? Ищем в mids formal_parametrs, но надо выделить именно обращение к параметрам - не полям класса, не глобальным переменным var cfa = new ConstructFiniteAutomata(pd.proc_body as block); cfa.Transform(); (pd.proc_body as block).program_code = cfa.res; // Конструируем определение класса var cct = GenClassesForYield(pd, dld.LocalDeletedDefs, CapturedLocalsNamesMap, CapturedFormalParamsNamesMap/*, localsCloneMap*/); // все удаленные описания переменных делаем описанием класса // Вставляем классы-хелперы InsertYieldHelpers(pd, cct); // frninja 20/05/16 - фикс для повторного обхода pd.has_yield = false; // frninja 05/06/16 - убираем where-секцию у описания метода. Они уже скопированы куда надо /*if (methodPredefCreated) { pd.proc_header.where_defs = null; }*/ //mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }
public override void visit(procedure_definition pd) { if (pd.proc_header.name.meth_name.name.StartsWith(YieldConsts.YieldHelperMethodPrefix)) return; //var isExtension = IsExtensionMethod(pd); hasYields = false; if (pd.proc_header is function_header) mids = new FindMainIdentsVisitor(); base.visit(pd); if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо. return; // Проверяем проблемы имен для for CheckVariablesRedefenitionVisitor checkVarRedefVisitor = new CheckVariablesRedefenitionVisitor( new HashSet<string>( pd.proc_header.parameters != null ? pd.proc_header.parameters.params_list.SelectMany(fp => fp.idents.idents.Select(id => id.name)) : Enumerable.Empty<string>())); pd.visit(checkVarRedefVisitor); // Переименовываем одинаковые имена в мини-ПИ RenameSameBlockLocalVarsVisitor renameLocalsVisitor = new RenameSameBlockLocalVarsVisitor(); pd.visit(renameLocalsVisitor); // Теперь lowering LoweringVisitor.Accept(pd); // frninja 13/04/16 - убираем лишние begin..end DeleteRedundantBeginEnds deleteBeginEndVisitor = new DeleteRedundantBeginEnds(); pd.visit(deleteBeginEndVisitor); // Обработка метода для корректного захвата локальных переменных и их типов yield_locals_type_map_helper localsTypeMapHelper; IEnumerable<var_def_statement> localsClonesCollection; CreateLocalVariablesTypeProxies(pd, out localsClonesCollection, out localsTypeMapHelper); // frninja 16/11/15: перенес ниже чтобы работал захват для lowered for var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement // Строим отображение из локальных переменных клона оригинального метода в локальные переменные основного метода Dictionary<var_def_statement, var_def_statement> localsCloneMap = CreateLocalsClonesMap(dld.LocalDeletedDefs, localsClonesCollection); // frninja 08/12/15 // Выполняем захват имён IDictionary<string, string> CapturedLocalsNamesMap; IDictionary<string, string> CapturedFormalParamsNamesMap; ReplaceCapturedVariables(pd, dld.LocalDeletedDefs, out CapturedLocalsNamesMap, out CapturedFormalParamsNamesMap); mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать // Обработать параметры! // Как? Ищем в mids formal_parametrs, но надо выделить именно обращение к параметрам - не полям класса, не глобальным переменным var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code); cfa.Transform(); (pd.proc_body as block).program_code = cfa.res; // Конструируем определение класса var cct = GenClassesForYield(pd, dld.LocalDeletedDefs, CapturedLocalsNamesMap, CapturedFormalParamsNamesMap, localsCloneMap, localsTypeMapHelper); // все удаленные описания переменных делаем описанием класса // Вставляем классы-хелперы InsertYieldHelpers(pd, cct); mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }
public override void visit(procedure_definition pd) { hasYields = false; if (pd.proc_header is function_header) mids = new FindMainIdentsVisitor(); base.visit(pd); if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо. return; var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны // В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать LoweringVisitor.Accept(pd); var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code); cfa.Transform(); (pd.proc_body as block).program_code = cfa.res; // Конструируем определение класса var cct = GenClassesForYield(pd, dld.LocalDeletedDefs); // все удаленные описания переменных делаем описанием класса UpperNodeAs<declarations>().InsertBefore(pd, cct); mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }