public virtual void visit(ISwitchNode value) { }
//перевод конструкции case public override void visit(ISwitchNode value) { //if (save_debug_info) // MarkSequencePoint(value.Location); Label default_case = il.DefineLabel(); Label jump_def_label = il.DefineLabel(); Label end_label; bool in_if = false; if (if_stack.Count == 0) end_label = il.DefineLabel(); else { end_label = if_stack.Pop(); in_if = true; } System.Collections.Generic.Dictionary<IConstantNode, Label> dict; TmpForLabel[] case_labels = GetCaseSelectors(value, jump_def_label, out dict); value.case_expression.visit(this); LocalBuilder lb = null; //if (case_labels.Length > 1) { lb = il.DeclareLocal(TypeFactory.Int32Type); il.Emit(OpCodes.Stloc, lb); } for (int i = 0; i < case_labels.Length; i++) { if (lb != null) { il.Emit(OpCodes.Ldloc, lb); //il.Emit(OpCodes.Ldc_I4, case_labels[i].low_bound); NETGeneratorTools.LdcIntConst(il, case_labels[i].low_bound); il.Emit(OpCodes.Sub); } else { //il.Emit(OpCodes.Ldc_I4, case_labels[i].low_bound); NETGeneratorTools.LdcIntConst(il, case_labels[i].low_bound); il.Emit(OpCodes.Sub); } il.Emit(OpCodes.Switch, case_labels[i].labels); } il.MarkLabel(jump_def_label); ConvertRangedSelectors(value, end_label, lb); il.Emit(OpCodes.Br, default_case); foreach (ICaseVariantNode cvn in value.case_variants) ConvertCaseVariantNode(cvn, end_label, dict); CompleteRangedSelectors(value, end_label); il.MarkLabel(default_case); if (value.default_statement != null) { if (value.default_statement.Location != null) MarkSequencePoint(il, value.default_statement.Location.begin_line_num, value.default_statement.Location.begin_column_num, value.default_statement.Location.begin_line_num, value.default_statement.Location.begin_column_num); value.default_statement.visit(this); } //MarkSequencePoint(il,0xFeeFee,0xFeeFee,0xFeeFee,0xFeeFee); if (!in_if) il.MarkLabel(end_label); }
//перевод селекторов-диапазонов case private void ConvertRangedSelectors(ISwitchNode value, Label end_label, LocalBuilder lb) { foreach (ICaseVariantNode cvn in value.case_variants) { var ranges = cvn.ranges; if (ranges.Length > 0) { Label range_stmts_label = il.DefineLabel(); for (int i = 0; i < ranges.Length; i++) { Label false_label = il.DefineLabel(); il.Emit(OpCodes.Ldloc, lb); ranges[i].lower_bound.visit(this); il.Emit(OpCodes.Blt, false_label); il.Emit(OpCodes.Ldloc, lb); ranges[i].high_bound.visit(this); il.Emit(OpCodes.Bgt, false_label); /*if (save_debug_info) MarkSequencePoint(cvn.statement_to_execute.Location); cvn.statement_to_execute.visit(this);*/ il.Emit(OpCodes.Br, range_stmts_label); range_stmts_labels[cvn.statement_to_execute] = range_stmts_label; il.MarkLabel(false_label); } } } }
//сбор информации о селекторах (сортировка, группировка и т. д.) private TmpForLabel[] GetCaseSelectors(ISwitchNode value, Label default_label, out System.Collections.Generic.Dictionary<IConstantNode, Label> dict) { System.Collections.Generic.SortedDictionary<int, TmpForCase> sel_list = new System.Collections.Generic.SortedDictionary<int, TmpForCase>(); System.Collections.Generic.Dictionary<ICaseRangeNode, IStatementNode> sel_range = new System.Collections.Generic.Dictionary<ICaseRangeNode, IStatementNode>(); dict = new System.Collections.Generic.Dictionary<IConstantNode, Label>(); //sobiraem informaciju o konstantah v case for (int i = 0; i < value.case_variants.Length; i++) { ICaseVariantNode cvn = value.case_variants[i]; for (int j = 0; j < cvn.elements.Length; j++) { IConstantNode cnst = cvn.elements[j]; if (cnst is IIntConstantNode) { TmpForCase tfc = new TmpForCase(); tfc.cnst = cnst; tfc.stmt = cvn.statement_to_execute; sel_list[((IIntConstantNode)cnst).constant_value] = tfc; } else if (cnst is ICharConstantNode) { TmpForCase tfc = new TmpForCase(); tfc.cnst = cnst; tfc.stmt = cvn.statement_to_execute; sel_list[(int)((ICharConstantNode)cnst).constant_value] = tfc; } else if (cnst is IBoolConstantNode) { TmpForCase tfc = new TmpForCase(); tfc.cnst = cnst; tfc.stmt = cvn.statement_to_execute; sel_list[Convert.ToInt32(((IBoolConstantNode)cnst).constant_value)] = tfc; } //ICaseRangeNode crn = cvn.ranges[j]; // sel_range[crn] = cvn.statement_to_execute; } } System.Collections.Generic.List<int> lst = new System.Collections.Generic.List<int>(); foreach (int val in sel_list.Keys) { lst.Add(val); } //sortiruem spisok perehodov v case lst.Sort(); //int size = lst[lst.Count - 1] - lst[0] + 1; System.Collections.Generic.List<Label> label_list = new System.Collections.Generic.List<Label>(); int last = 0; int size = 0; TmpForLabel tfl = new TmpForLabel(); List<TmpForLabel> ltfl = new List<TmpForLabel>(); //sozdaem metki dlja perehodov if (lst.Count > 0) { last = lst[0]; size = 1; tfl.low_bound = last;//niznjaa granica Label l = il.DefineLabel(); dict[sel_list[last].cnst] = l;//konstante sopostavim metku label_list.Add(l); } for (int i = 1; i < lst.Count; i++) { int dist = lst[i] - last; if (dist < 10)//esli rasstojanie mezhdu sosednimi konstantami nebolshoe { last = lst[i]; size += dist;//pribavljaem rasstojanie if (dist > 1) { for (int j = 1; j < dist; j++) //inache nado perehodit k proverke diapazonov label_list.Add(default_label); } Label l = il.DefineLabel(); dict[sel_list[last].cnst] = l; label_list.Add(l); } else { tfl.labels = label_list.ToArray();//inache sozdaem otdelnuju tablicu perehodov ltfl.Add(tfl); tfl = new TmpForLabel(); label_list = new List<Label>(); tfl.low_bound = lst[i]; last = lst[i]; Label l = il.DefineLabel(); dict[sel_list[last].cnst] = l; label_list.Add(l); } } tfl.labels = label_list.ToArray(); ltfl.Add(tfl); return ltfl.ToArray(); }
private void CompleteRangedSelectors(ISwitchNode value, Label end_label) { foreach (ICaseVariantNode cvn in value.case_variants) { if (cvn.ranges.Length > 0) { il.MarkLabel((Label)range_stmts_labels[cvn.statement_to_execute]); if (save_debug_info) MarkSequencePoint(cvn.statement_to_execute.Location); ConvertStatement(cvn.statement_to_execute); il.Emit(OpCodes.Br, end_label); } } }
public void visit(ISwitchNode value) { string s = value.GetType().Name + "."; prepare_node(value.case_expression, s + "case_expression"); prepare_base_node_collection(value.case_variants, s + "case_variants", "case_variants", value.case_variants.Length); prepare_node(value.default_statement, s + "default_statement"); }
public void visit(ISwitchNode value) { throw new System.NotSupportedException(value.GetType().ToString()); }