//инициализация критических секций с созданием класса private static void InitCriticals(syntax_tree_visitor visitor) { //генерируем класс SyntaxTree.type_declarations TypeDecls = new PascalABCCompiler.SyntaxTree.type_declarations(); SyntaxTree.type_declaration TypeDecl = new PascalABCCompiler.SyntaxTree.type_declaration(); TypeDecls.types_decl.Add(TypeDecl); LocksName = visitor.context.get_free_name("$locks_container{0}"); TypeDecl.type_name = new PascalABCCompiler.SyntaxTree.ident(LocksName); SyntaxTree.class_definition ClassDef = new PascalABCCompiler.SyntaxTree.class_definition(); TypeDecl.type_def = ClassDef; SyntaxTree.class_body ClassBody = new PascalABCCompiler.SyntaxTree.class_body(); ClassDef.body = ClassBody; SyntaxTree.class_members ClassMember = new PascalABCCompiler.SyntaxTree.class_members(); ClassBody.class_def_blocks.Add(ClassMember); ClassMember.access_mod = new PascalABCCompiler.SyntaxTree.access_modifer_node(PascalABCCompiler.SyntaxTree.access_modifer.public_modifer); List<string> ProcessedNames = new List<string>(); foreach (KeyValuePair<SyntaxTree.compiler_directive, DirectiveInfo> pair in DirInfosTable) { if (pair.Value.Kind == DirectiveKind.Critical) { string LockName = "$default"; if (pair.Value.Name.Length != 0) LockName = pair.Value.Name; if (ProcessedNames.Contains(LockName)) continue; ProcessedNames.Add(LockName); SyntaxTree.var_def_statement vds = new PascalABCCompiler.SyntaxTree.var_def_statement(); SyntaxTree.ident_list idl = new PascalABCCompiler.SyntaxTree.ident_list(); vds.vars = idl; idl.Add(new SyntaxTree.ident(LockName)); SyntaxTree.named_type_reference ntr = new PascalABCCompiler.SyntaxTree.named_type_reference(); vds.vars_type = ntr; ntr.Add(new SyntaxTree.ident("object")); SyntaxTree.new_expr ne = new PascalABCCompiler.SyntaxTree.new_expr(); vds.inital_value = ne; ne.type = ntr; vds.var_attr = PascalABCCompiler.SyntaxTree.definition_attribute.Static; ClassMember.members.Add(vds); } } //сохраняем контекст ContextInfo contextInfo = new ContextInfo(visitor); try { visitor.visit(TypeDecls); LocksInitialized = true; } finally { //восстанавливаем контекст contextInfo.RestoreContext(visitor); } }
private static void CreateInParallelVariable(syntax_tree_visitor syntax_tree_visitor, out string VarName) { //сохраняем контекст ContextInfo contextInfo = new ContextInfo(syntax_tree_visitor); VarName = "$InParallelSection"; try { //создание и конвертирование переменной SyntaxTree.var_def_statement vds = new PascalABCCompiler.SyntaxTree.var_def_statement(); SyntaxTree.variable_definitions var_def = new PascalABCCompiler.SyntaxTree.variable_definitions(vds, null); SyntaxTree.ident_list idl = new PascalABCCompiler.SyntaxTree.ident_list(); vds.vars = idl; idl.Add(new SyntaxTree.ident(VarName)); SyntaxTree.named_type_reference ntr = new PascalABCCompiler.SyntaxTree.named_type_reference(); vds.vars_type = ntr; ntr.names.Add(new PascalABCCompiler.SyntaxTree.ident("boolean")); vds.inital_value = new PascalABCCompiler.SyntaxTree.ident("false"); syntax_tree_visitor.visit(var_def); } finally { //восстанавливаем контекст contextInfo.RestoreContext(syntax_tree_visitor); } InParallelSectionCreated = true; }
private static SyntaxTree.declaration CreateClassMember(SemanticTree.IDefinitionNode Def, string Prefix) { if (Def is SemanticTree.IConstantDefinitionNode) { SemanticTree.IConstantDefinitionNode ConstDef = Def as SemanticTree.IConstantDefinitionNode; SyntaxTree.typed_const_definition tcd = new PascalABCCompiler.SyntaxTree.typed_const_definition(); tcd.const_name = new PascalABCCompiler.SyntaxTree.ident(Prefix + ConstDef.name); tcd.const_type = ConvertToSyntaxType(ConstDef.type as type_node); tcd.const_value = ConvertConstant(ConstDef.constant_value); return tcd; } else { SemanticTree.IVAriableDefinitionNode VarDef = Def as SemanticTree.IVAriableDefinitionNode; SyntaxTree.var_def_statement vds = new PascalABCCompiler.SyntaxTree.var_def_statement(); SyntaxTree.ident_list idl = new PascalABCCompiler.SyntaxTree.ident_list(); vds.vars = idl; idl.Add(new SyntaxTree.ident(Prefix + VarDef.name)); vds.vars_type = ConvertToSyntaxType(VarDef.type as type_node); return vds; } }
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.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; }