private static SyntaxTree.if_node CreateNestedRegionBorder(bool ifEnter) { SyntaxTree.if_node result = new PascalABCCompiler.SyntaxTree.if_node(); SyntaxTree.un_expr ue = new PascalABCCompiler.SyntaxTree.un_expr(); ue.operation_type = PascalABCCompiler.SyntaxTree.Operators.LogicalNOT; ue.subnode = new SyntaxTree.ident(TreeConverter.compiler_string_consts.OMP_NESTED); result.condition = ue; SyntaxTree.assign AssignInParVar = new PascalABCCompiler.SyntaxTree.assign(); AssignInParVar.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; AssignInParVar.from = new SyntaxTree.ident(ifEnter ? "true" : "false"); AssignInParVar.to = new SyntaxTree.ident(InParallelSection); result.then_body = AssignInParVar; return result; }
private static SyntaxTree.statement_list CreateFinalPart(string ObjName, VarInfoContainer Vars) { SyntaxTree.statement_list stl = new PascalABCCompiler.SyntaxTree.statement_list(); //создаем присваивания разделяемым переменным for (int i = 0; i < Vars.SharedVariables.Count; ++i) { string VarName = Vars.SharedVariables[i].name; if (LoopVariables.Contains(VarName.ToLower())) continue; SyntaxTree.dot_node DotNode = new PascalABCCompiler.SyntaxTree.dot_node(); DotNode.left = new SyntaxTree.ident(ObjName); DotNode.right = new SyntaxTree.ident(VarName); SyntaxTree.array_type arrType = ConvertToSyntaxType(Vars.SharedVariables[i].type as type_node) as SyntaxTree.array_type; if (arrType != null && !is_dyn_arr(arrType)) { stl.subnodes.Add(AssignArrs(arrType, DotNode, new SyntaxTree.ident(VarName))); } else { SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.to = new SyntaxTree.ident(VarName); Assign.from = DotNode; stl.subnodes.Add(Assign); } } //создаем присваивания переменным редукции for (int i = 0; i < Vars.ReductionVariables.Count; ++i) { string VarName = Vars.ReductionVariables[i].name; SyntaxTree.dot_node DotNode = new PascalABCCompiler.SyntaxTree.dot_node(); DotNode.left = new SyntaxTree.ident(ObjName); DotNode.right = new SyntaxTree.ident("$" + VarName); SyntaxTree.array_type arrType = ConvertToSyntaxType(Vars.ReductionVariables[i].type as type_node) as SyntaxTree.array_type; if (arrType != null && !is_dyn_arr(arrType)) { stl.subnodes.Add(AssignArrs(arrType, DotNode, new SyntaxTree.ident(VarName))); } else { SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.to = new SyntaxTree.ident(VarName); Assign.from = DotNode; stl.subnodes.Add(Assign); } } return stl; }
private static SyntaxTree.procedure_definition CreateMethod(string MethodName, SyntaxTree.statement Body, string LoopVariableName, SyntaxTree.class_members ClassMember, VarInfoContainer Vars) { // генерация метода SyntaxTree.procedure_definition ProcDef = new PascalABCCompiler.SyntaxTree.procedure_definition(); //ClassMember.members.Add(ProcDef); SyntaxTree.procedure_header ProcHead = new PascalABCCompiler.SyntaxTree.procedure_header(); ProcDef.proc_header = ProcHead; ProcHead.name = new PascalABCCompiler.SyntaxTree.method_name(null, null, new PascalABCCompiler.SyntaxTree.ident(MethodName), null); if (LoopVariableName != "") { // параметр, счетчик цикла string ParamType = "integer"; SyntaxTree.formal_parameters FormalParams = new PascalABCCompiler.SyntaxTree.formal_parameters(); ProcHead.parameters = FormalParams; SyntaxTree.typed_parameters TypedParams = new PascalABCCompiler.SyntaxTree.typed_parameters(); FormalParams.params_list.Add(TypedParams); SyntaxTree.ident_list idl = new PascalABCCompiler.SyntaxTree.ident_list(); TypedParams.idents = idl; idl.Add(new SyntaxTree.ident(LoopVariableName)); SyntaxTree.named_type_reference ntr = new PascalABCCompiler.SyntaxTree.named_type_reference(); TypedParams.vars_type = ntr; ntr.Add(new SyntaxTree.ident(ParamType)); } SyntaxTree.block ProcBlock = new PascalABCCompiler.SyntaxTree.block(); ProcDef.proc_body = ProcBlock; ProcBlock.defs = new PascalABCCompiler.SyntaxTree.declarations(); if (Vars.Constants.Count > 0) { SyntaxTree.consts_definitions_list cdl = new PascalABCCompiler.SyntaxTree.consts_definitions_list(); ProcBlock.defs.defs.Add(cdl); // константы - в методе for (int i = 0; i < Vars.Constants.Count; ++i) cdl.Add(CreateClassMember(Vars.Constants[i], "") as SyntaxTree.typed_const_definition); } if ((Vars.ReductionVariables.Count > 0) || (Vars.PrivateVariables.Count > 0)) { // переменные редукции - в методе тоже, но без префикса SyntaxTree.variable_definitions vds = new PascalABCCompiler.SyntaxTree.variable_definitions(); ProcBlock.defs.defs.Add(vds); for (int i = 0; i < Vars.ReductionVariables.Count; ++i) vds.Add(CreateClassMember(Vars.ReductionVariables[i], "") as SyntaxTree.var_def_statement); // и приватные переменные for (int i = 0; i < Vars.PrivateVariables.Count; ++i) vds.Add(CreateClassMember(Vars.PrivateVariables[i], "") as SyntaxTree.var_def_statement); } if (Body is SyntaxTree.statement_list) ProcBlock.program_code = Body as SyntaxTree.statement_list; else { SyntaxTree.statement_list stl = new PascalABCCompiler.SyntaxTree.statement_list(); stl.subnodes.Add(Body); ProcBlock.program_code = stl; } //присваивания для переменных редукции if (Vars.ReductionVariables.Count > 0) { SyntaxTree.statement_list LoopBodyInit = new PascalABCCompiler.SyntaxTree.statement_list(); SyntaxTree.statement_list LoopBodyFinal = new PascalABCCompiler.SyntaxTree.statement_list(); for (int i = 0; i < Vars.ReductionVariables.Count; ++i) { //присваивание начального значения SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.to = new SyntaxTree.ident(Vars.ReductionVariables[i].name); bool isBool = Vars.ReductionVariables[i].type.name.ToLower() == "boolean"; switch (Vars.ReductionActions[i]) { case ReductionOperations.and: { if (isBool) Assign.from = new SyntaxTree.bool_const(true); else { //отрицание нуля Assign.from = new SyntaxTree.int32_const(0); LoopBodyInit.subnodes.Add(Assign); Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.to = new SyntaxTree.ident(Vars.ReductionVariables[i].name); SyntaxTree.un_expr ue = new PascalABCCompiler.SyntaxTree.un_expr(); ue.operation_type = PascalABCCompiler.SyntaxTree.Operators.LogicalNOT; ue.subnode = new SyntaxTree.ident(Vars.ReductionVariables[i].name); Assign.from = ue; } break; } case ReductionOperations.or: if (isBool) Assign.from = new SyntaxTree.bool_const(false); else { Assign.from = new SyntaxTree.int32_const(0); } break; case ReductionOperations.xor: // case ReductionOperations.plus: //см следующую ветку case ReductionOperations.minus: Assign.from = new SyntaxTree.int32_const(0); break; case ReductionOperations.mult: Assign.from = new SyntaxTree.int32_const(1); break; } LoopBodyInit.Add(Assign); //присваивание после итерации Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.to = new SyntaxTree.ident("$" + Vars.ReductionVariables[i].name); SyntaxTree.bin_expr From = new PascalABCCompiler.SyntaxTree.bin_expr(); From.left = new SyntaxTree.ident("$" + Vars.ReductionVariables[i].name); From.right = new SyntaxTree.ident(Vars.ReductionVariables[i].name); Assign.from = From; switch (Vars.ReductionActions[i]) { case ReductionOperations.and: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.LogicalAND; break; case ReductionOperations.or: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.LogicalOR; break; case ReductionOperations.xor: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.BitwiseXOR; break; case ReductionOperations.plus: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.Plus; break; case ReductionOperations.minus: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.Minus; break; case ReductionOperations.mult: From.operation_type = PascalABCCompiler.SyntaxTree.Operators.Multiplication; break; } LoopBodyFinal.Add(Assign); } //создаем обьект для блокировки в классе SyntaxTree.var_def_statement Lvds = new PascalABCCompiler.SyntaxTree.var_def_statement(); SyntaxTree.ident_list Lidl = new PascalABCCompiler.SyntaxTree.ident_list(); Lvds.vars = Lidl; Lidl.Add(new SyntaxTree.ident("$ReductionLock")); SyntaxTree.named_type_reference Lntr = new PascalABCCompiler.SyntaxTree.named_type_reference(); Lvds.vars_type = Lntr; Lntr.Add(new SyntaxTree.ident("object")); SyntaxTree.new_expr Lne = new PascalABCCompiler.SyntaxTree.new_expr(); Lvds.inital_value = Lne; Lne.type = Lntr; ClassMember.members.Add(Lvds); //создаем lock Statement на обьекте с присваиваниями в конце итерации SyntaxTree.lock_stmt reductionLock = new PascalABCCompiler.SyntaxTree.lock_stmt(); reductionLock.lock_object = new SyntaxTree.ident("$ReductionLock"); reductionLock.stmt = LoopBodyFinal; //собираем все вместе и присваиваем это телу процедуры LoopBodyInit.subnodes.AddRange(ProcBlock.program_code.subnodes); LoopBodyInit.subnodes.Add(reductionLock); ProcBlock.program_code = LoopBodyInit; } return ProcDef; }
private static SyntaxTree.statement_list CreateInitPart(string ClassName, string ObjName, VarInfoContainer Vars) { SyntaxTree.statement_list stl = new PascalABCCompiler.SyntaxTree.statement_list(); //Var Statement - объявление экземпляра обьекта-функции SyntaxTree.var_statement ClassVar = new PascalABCCompiler.SyntaxTree.var_statement(); stl.subnodes.Add(ClassVar); SyntaxTree.var_def_statement ClassVarDef = new PascalABCCompiler.SyntaxTree.var_def_statement(); ClassVar.var_def = ClassVarDef; SyntaxTree.ident_list ClassIdl = new PascalABCCompiler.SyntaxTree.ident_list(); ClassVarDef.vars = ClassIdl; ClassIdl.idents.Add(new PascalABCCompiler.SyntaxTree.ident(ObjName)); SyntaxTree.named_type_reference ClassTypeNTR = new PascalABCCompiler.SyntaxTree.named_type_reference(); ClassVarDef.vars_type = ClassTypeNTR; ClassTypeNTR.names.Add(new PascalABCCompiler.SyntaxTree.ident(ClassName)); SyntaxTree.new_expr ClassInitNE = new PascalABCCompiler.SyntaxTree.new_expr(); ClassVarDef.inital_value = ClassInitNE; SyntaxTree.named_type_reference ClassInitNTR = new PascalABCCompiler.SyntaxTree.named_type_reference(); ClassInitNE.type = ClassInitNTR; ClassInitNTR.names.Add(new PascalABCCompiler.SyntaxTree.ident(ClassName)); //создаем присваивания разделяемым переменным for (int i = 0; i < Vars.SharedVariables.Count; ++i) { string VarName = Vars.SharedVariables[i].name; SyntaxTree.dot_node DotNode = new PascalABCCompiler.SyntaxTree.dot_node(); DotNode.left = new SyntaxTree.ident(ObjName); DotNode.right = new SyntaxTree.ident(VarName); SyntaxTree.array_type arrType = ConvertToSyntaxType(Vars.SharedVariables[i].type as type_node) as SyntaxTree.array_type; if (arrType != null && !is_dyn_arr(arrType)) { stl.subnodes.Add(AssignArrs(arrType, new SyntaxTree.ident(VarName), DotNode)); } else { SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.from = new SyntaxTree.ident(VarName); Assign.to = DotNode; stl.subnodes.Add(Assign); } } //создаем присваивания переменным редукции for (int i = 0; i < Vars.ReductionVariables.Count; ++i) { string VarName = Vars.ReductionVariables[i].name; SyntaxTree.dot_node DotNode = new PascalABCCompiler.SyntaxTree.dot_node(); DotNode.left = new SyntaxTree.ident(ObjName); DotNode.right = new SyntaxTree.ident("$" + VarName); SyntaxTree.array_type arrType = ConvertToSyntaxType(Vars.ReductionVariables[i].type as type_node) as SyntaxTree.array_type; if (arrType != null && !is_dyn_arr(arrType)) { stl.subnodes.Add(AssignArrs(arrType, new SyntaxTree.ident(VarName), DotNode)); } else { SyntaxTree.assign Assign = new PascalABCCompiler.SyntaxTree.assign(); Assign.operator_type = PascalABCCompiler.SyntaxTree.Operators.Assignment; Assign.from = new SyntaxTree.ident(VarName); Assign.to = DotNode; stl.subnodes.Add(Assign); } } return stl; }
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; }