private static SyntaxTree.statement_list AssignArrs(SyntaxTree.array_type ArrFrom, SyntaxTree.addressed_value IdFrom, SyntaxTree.addressed_value IdTo) { SyntaxTree.statement_list OuterSTL = new PascalABCCompiler.SyntaxTree.statement_list(); SyntaxTree.statement_list InnerSTL = OuterSTL; List<List<SyntaxTree.diapason>> DiapasonsList = get_list_of_diapasons(ArrFrom); List<List<SyntaxTree.ident>> IdentsList = new List<List<PascalABCCompiler.SyntaxTree.ident>>(); int VarNum = 0; if (DiapasonsList == null) DiapasonsList = new List<List<PascalABCCompiler.SyntaxTree.diapason>>(); foreach (List<SyntaxTree.diapason> Diapasons in DiapasonsList) { bool IsDynamicArray = false; List<SyntaxTree.method_call> Lens = new List<PascalABCCompiler.SyntaxTree.method_call>(); if ((Diapasons.Count == 0) || (Diapasons[0] == null)) { //массив динамический, нужно делать setlength IsDynamicArray = true; SyntaxTree.procedure_call SetLenPC = new PascalABCCompiler.SyntaxTree.procedure_call(); SyntaxTree.method_call SetLenMC = new PascalABCCompiler.SyntaxTree.method_call(); SetLenMC.dereferencing_value = new SyntaxTree.ident("SetLength"); SetLenPC.func_name = SetLenMC; SyntaxTree.expression_list SetLenParamsExl = new PascalABCCompiler.SyntaxTree.expression_list(); SetLenMC.parameters = SetLenParamsExl; //индексное выражение для массива-приемника SyntaxTree.addressed_value IndexerTo = IdTo; foreach (List<SyntaxTree.ident> Idents in IdentsList) { SyntaxTree.indexer InnerInd = new PascalABCCompiler.SyntaxTree.indexer(); InnerInd.dereferencing_value = IndexerTo; SyntaxTree.expression_list IndexersExl = new PascalABCCompiler.SyntaxTree.expression_list(); foreach (SyntaxTree.ident Ident in Idents) IndexersExl.expressions.Add(new SyntaxTree.ident(Ident.name)); InnerInd.indexes = IndexersExl; IndexerTo = InnerInd; } //индексное выражение для массива-источника SyntaxTree.addressed_value IndexerFrom = IdFrom; foreach (List<SyntaxTree.ident> Idents in IdentsList) { SyntaxTree.indexer InnerInd = new PascalABCCompiler.SyntaxTree.indexer(); InnerInd.dereferencing_value = IndexerFrom; SyntaxTree.expression_list IndexersExl = new PascalABCCompiler.SyntaxTree.expression_list(); foreach (SyntaxTree.ident Ident in Idents) IndexersExl.expressions.Add(new SyntaxTree.ident(Ident.name)); InnerInd.indexes = IndexersExl; IndexerFrom = InnerInd; } SetLenParamsExl.expressions.Add(IndexerTo); //List<SyntaxTree.method_call> Lengths = new List<PascalABCCompiler.SyntaxTree.method_call>(); if (Diapasons.Count == 0) { SyntaxTree.method_call LengthMC = new PascalABCCompiler.SyntaxTree.method_call(); LengthMC.dereferencing_value = new SyntaxTree.ident("Length"); SyntaxTree.expression_list LenMCExl = new PascalABCCompiler.SyntaxTree.expression_list(); LengthMC.parameters = LenMCExl; LenMCExl.expressions.Add(IndexerFrom); SetLenParamsExl.expressions.Add(LengthMC); Lens.Add(LengthMC); } else { for (int i = 0; i < Diapasons.Count; ++i) { SyntaxTree.method_call LengthMC = new PascalABCCompiler.SyntaxTree.method_call(); LengthMC.dereferencing_value = new SyntaxTree.ident("Length"); SyntaxTree.expression_list LenMCExl = new PascalABCCompiler.SyntaxTree.expression_list(); LengthMC.parameters = LenMCExl; LenMCExl.expressions.Add(IndexerFrom); LenMCExl.expressions.Add(new SyntaxTree.int32_const(i)); SetLenParamsExl.expressions.Add(LengthMC); Lens.Add(LengthMC); } } InnerSTL.subnodes.Add(SetLenPC); } //к этому моменту вызов SetLength с параметрами сформирован //в Lens содержатся вызовы length по нужной размерности если массив динамический //теперь нужно создать циклы for и список переменных, по которым идут циклы List<SyntaxTree.ident> LoopIdents = new List<SyntaxTree.ident>(); for (int i = 0; i < Math.Max(Diapasons.Count, 1); ++i) { SyntaxTree.for_node ForNode = new PascalABCCompiler.SyntaxTree.for_node(); SyntaxTree.ident LoopVar = new PascalABCCompiler.SyntaxTree.ident("$i" + (VarNum++).ToString()); LoopIdents.Add(LoopVar); ForNode.loop_variable = LoopVar; ForNode.create_loop_variable = true; if (IsDynamicArray) { ForNode.initial_value = new SyntaxTree.int32_const(0); ForNode.finish_value = new PascalABCCompiler.SyntaxTree.bin_expr(Lens[i], new SyntaxTree.int32_const(1), PascalABCCompiler.SyntaxTree.Operators.Minus); } else { ForNode.initial_value = Diapasons[i].left; ForNode.finish_value = Diapasons[i].right; } InnerSTL.subnodes.Add(ForNode); ForNode.statements = new PascalABCCompiler.SyntaxTree.statement_list(); InnerSTL = ForNode.statements as SyntaxTree.statement_list; } IdentsList.Add(LoopIdents); } // к этому моменту создано гнездо циклов с установкой длины динамических массивов и перебором // вообще всех массивов. Осталось создать самое внутреннее присваивание SyntaxTree.addressed_value AssignIndexerFrom = IdFrom; SyntaxTree.addressed_value AssignIndexerTo = IdTo; foreach (List<SyntaxTree.ident> AssignIdents in IdentsList) { SyntaxTree.indexer FromIndexer = new PascalABCCompiler.SyntaxTree.indexer(); SyntaxTree.indexer ToIndexer = new PascalABCCompiler.SyntaxTree.indexer(); FromIndexer.dereferencing_value = AssignIndexerFrom; ToIndexer.dereferencing_value = AssignIndexerTo; SyntaxTree.expression_list Exl = new PascalABCCompiler.SyntaxTree.expression_list(); foreach (SyntaxTree.ident id in AssignIdents) Exl.expressions.Add(id); FromIndexer.indexes = Exl; ToIndexer.indexes = Exl; AssignIndexerFrom = FromIndexer; AssignIndexerTo = ToIndexer; } SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.from = AssignIndexerFrom; Assign.to = AssignIndexerTo; Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; InnerSTL.subnodes.Add(Assign); return OuterSTL; }
private static SyntaxTree.procedure_call CreateOMPParallelForCall(SyntaxTree.dot_node dn, SyntaxTree.expression FromInclusive, SyntaxTree.expression ToInclusive) { SyntaxTree.procedure_call pc = new PascalABCCompiler.SyntaxTree.procedure_call(); SyntaxTree.method_call mc = new PascalABCCompiler.SyntaxTree.method_call(); pc.func_name = mc; mc.dereferencing_value = CreateTPLFunctionReference("For"); //Здесь прибавляем единицу ко второму параметру, так как в паскале верхняя граница включается, а в parallel.for - нет SyntaxTree.bin_expr ToExclusive = new SyntaxTree.bin_expr(); ToExclusive.left = ToInclusive; ToExclusive.right = new SyntaxTree.int32_const(1); ToExclusive.operation_type = SyntaxTree.Operators.Plus; mc.parameters = new PascalABCCompiler.SyntaxTree.expression_list(); mc.parameters.Add(FromInclusive); mc.parameters.Add(ToExclusive); mc.parameters.Add(dn); return pc; }
private static bool GenerateOMPParallelSectionsCall(statements_list stmts, SyntaxTree.statement_list syntax_stmts, statements_list omp_stmts, syntax_tree_visitor syntax_tree_visitor) { SyntaxTree.expression_list delegates = new PascalABCCompiler.SyntaxTree.expression_list(); SyntaxTree.statement_list stlInit = new PascalABCCompiler.SyntaxTree.statement_list(); SyntaxTree.statement_list stlFinal = new PascalABCCompiler.SyntaxTree.statement_list(); VarInfoContainer Vars = new VarInfoContainer(); string ClassName = syntax_tree_visitor.context.get_free_name("$section_class{0}"); List<SyntaxTree.statement> Sections = new List<PascalABCCompiler.SyntaxTree.statement>(); foreach (SyntaxTree.statement syntax_statement in syntax_stmts.subnodes) { if (syntax_statement is SyntaxTree.empty_statement) continue; //А зачем? ;-) if (syntax_statement is SyntaxTree.var_statement) { //выдать предупреждение. Это не нормально для параллельных секций syntax_tree_visitor.visit(syntax_statement as SyntaxTree.var_statement); } else { //ищем используемые переменные VarFinderSyntaxVisitor VFvis = new VarFinderSyntaxVisitor(syntax_statement, syntax_tree_visitor.context, false); SyntaxTree.compiler_directive dir = syntax_tree_visitor.DirectivesToNodesLinks[syntax_stmts]; //if (DirInfosTable[dir].ErrorName == "WARNING_IN_CLAUSE_PARAMETERS_REPEATED_VARS") // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //else if (DirInfosTable[dir].ErrorName == "ERROR_IN_CLAUSE_PARAMETERS") //{ // syntax_tree_visitor.AddWarning(new Errors.CommonWarning(StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); //} //else if (DirInfosTable[dir].ErrorName != null) { syntax_tree_visitor.AddWarning(new Errors.CommonWarning(PascalABCCompiler.StringResources.Get(DirInfosTable[dir].ErrorName), syntax_stmts.source_context.FileName, DirInfosTable[dir].SC.begin_position.line_num, DirInfosTable[dir].SC.begin_position.column_num)); } Vars.UnionWith(GetVarInfoContainer(VFvis, null, DirInfosTable[dir].Privates, syntax_tree_visitor, dir)); Sections.Add(syntax_statement); } } //сохраняем контекст ContextInfo contextInfo = new ContextInfo(syntax_tree_visitor); try { //создание и конвертирование класса SyntaxTree.class_members member; SyntaxTree.type_declarations Decls = CreateClass(ClassName, out member, Vars); for (int i = 0; i < Sections.Count; ++i) member.members.Add(CreateMethod("method" + i.ToString(), Sections[i], "", member, Vars)); syntax_tree_visitor.visit(Decls); } finally { //восстанавливаем контекст contextInfo.RestoreContext(syntax_tree_visitor); } //создаем инициализацию и финализацию int NameNum = 0; string ObjName = GetFreeName("$section_obj", ref NameNum, syntax_tree_visitor.context); stlInit.subnodes.AddRange(CreateInitPart(ClassName, ObjName, Vars).subnodes); stlFinal.subnodes.AddRange(CreateFinalPart(ObjName, Vars).subnodes); SyntaxTree.procedure_call pc = new PascalABCCompiler.SyntaxTree.procedure_call(); SyntaxTree.method_call mc = new PascalABCCompiler.SyntaxTree.method_call(); mc.dereferencing_value = CreateTPLFunctionReference("Invoke"); pc.func_name = mc; SyntaxTree.expression_list exl = new PascalABCCompiler.SyntaxTree.expression_list(); //foreach (string str in ObjNames) for (int i=0; i<Sections.Count; ++i) exl.Add(new SyntaxTree.dot_node(new SyntaxTree.ident(ObjName), new SyntaxTree.ident("Method"+i.ToString()))); mc.parameters = exl; stlInit.subnodes.Add(CreateNestedRegionBorder(true)); stlInit.subnodes.Add(pc); stlInit.subnodes.AddRange(stlFinal.subnodes); stlInit.subnodes.Add(CreateNestedRegionBorder(false)); statement_node st = syntax_tree_visitor.ret.visit(stlInit); omp_stmts.statements.AddElement(st); return true; }