//TODO: Добавить приведение типов. public override void visit(SyntaxTree.case_node _case_node) { convertion_data_and_alghoritms.check_node_parser_error(_case_node); switch_node sn = new switch_node(get_location(_case_node)); expression_node en = convert_strong(_case_node.param); if (en is typed_expression) en = convert_typed_expression_to_function_call(en as typed_expression); type_node case_expr_type = en.type; internal_interface ii = en.type.get_internal_interface(internal_interface_kind.ordinal_interface); if (ii == null && en.type != SystemLibrary.SystemLibrary.string_type) { AddError(new OrdinalOrStringTypeExpected(en.location)); } if (ii != null) { ordinal_type_interface oti = (ordinal_type_interface)ii; en = convertion_data_and_alghoritms.create_simple_function_call(oti.value_to_int, en.location, en); sn.condition = en; foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); case_variant_node sem_cv = new case_variant_node(get_location(cv)); sn.case_variants.AddElement(sem_cv); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { convertion_data_and_alghoritms.check_node_parser_error(expr); SyntaxTree.diapason_expr diap = expr as SyntaxTree.diapason_expr; if (diap == null) { expression_node cn = convert_strong(expr); int_const_node icn = convert_const_to_switch(cn, oti, case_expr_type, get_location(expr)); is_case_variant_intersection_with_another(sn, icn, get_location(expr)); sem_cv.case_constants.AddElement(icn); } else { convertion_data_and_alghoritms.check_node_parser_error(diap.left); expression_node left = convert_strong(diap.left); /* constant_node cons_left = left as constant_node; if (cons_left==null) { throw new ConstantExpressionExpected(get_location(diap.left)); } */ int_const_node icn_left = convert_const_to_switch(left, oti, case_expr_type, get_location(diap.left)); convertion_data_and_alghoritms.check_node_parser_error(diap.right); expression_node right = convert_strong(diap.right); /* constant_node cons_right = right as constant_node; if (cons_right == null) { throw new ConstantExpressionExpected(get_location(diap.right)); } */ int_const_node icn_right = convert_const_to_switch(right, oti, case_expr_type, get_location(diap.right)); //ssyy if (icn_left.constant_value > icn_right.constant_value) { AddError(get_location(diap.right), "LEFT_RANGE_GREATER_THEN_RIGHT"); } //\ssyy case_range_node crn = new case_range_node(icn_left, icn_right, get_location(diap)); is_case_range_intersection_with_another(sn, crn, get_location(expr)); sem_cv.case_ranges.AddElement(crn); } } context.enter_code_block_with_bind(); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); sem_cv.case_statement = stmn; //sn.case_variants.AddElement(sem_cv); } context.enter_code_block_with_bind(); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); sn.default_statement = else_statement; return_value(sn); } else { if_node main_ifn = null; if_node ifn = null; compiled_function_node str_eq_meth = SystemLibrary.SystemLibrary.string_type.find_in_type("=").sym_info as compiled_function_node; Dictionary<string, string> case_constants = new Dictionary<string, string>(); foreach (SyntaxTree.case_variant cv in _case_node.conditions.variants) { convertion_data_and_alghoritms.check_node_parser_error(cv); location loc = get_location(cv); expression_node eq_node = null; List<compiled_static_method_call> eq_calls = new List<compiled_static_method_call>(); foreach (SyntaxTree.expression expr in cv.conditions.expressions) { expression_node cn = convert_strong(expr); if (cn.type != SystemLibrary.SystemLibrary.string_type) AddError(new CanNotConvertTypes(cn, cn.type, SystemLibrary.SystemLibrary.string_type, cn.location)); string_const_node scn = convert_string_const_to_switch(cn, cn.location); if (!case_constants.ContainsKey(scn.constant_value)) case_constants.Add(scn.constant_value, scn.constant_value); else AddError(cn.location, "CASE_CONSTANT_VARIANT_COINCIDE_WITH_ANOTHER"); compiled_static_method_call eq_call = new compiled_static_method_call(str_eq_meth, cn.location); eq_call.parameters.AddElement(en); eq_call.parameters.AddElement(cn); eq_calls.Add(eq_call); } foreach (compiled_static_method_call eq_call in eq_calls) { if (eq_node == null) eq_node = eq_call; else eq_node = new basic_function_call(SystemLibrary.SystemLibrary.bool_or as basic_function_node, null, eq_node, eq_call); } context.enter_code_block_with_bind(); statement_node stmn = convert_strong(cv.exec_if_true); context.leave_code_block(); if (ifn != null) { ifn.else_body = new if_node(eq_node, stmn, null, loc); ifn = ifn.else_body as if_node; } else ifn = new if_node(eq_node, stmn, null, loc); if (main_ifn == null) main_ifn = ifn; } context.enter_code_block_with_bind(); statement_node else_statement = convert_weak(_case_node.else_statement); context.leave_code_block(); if (ifn == null) { ifn = new if_node(en, new statements_list(null), null, get_location(_case_node)); main_ifn = ifn; } ifn.else_body = else_statement; return_value(main_ifn); } }
private void VisitCaseVariantNode(case_variant_node cvn) { bw.Write(cvn.case_constants.Count); foreach (constant_node cnst in cvn.case_constants) VisitExpression(cnst); bw.Write(cvn.case_ranges.Count); foreach (case_range_node crn in cvn.case_ranges) { VisitExpression(crn.lower_bound); VisitExpression(crn.high_bound); } VisitStatement(cvn.case_statement); }
private case_variant_node CreateCaseVariant() { case_variant_node cvn = new case_variant_node(null); int const_num = br.ReadInt32(); for (int i = 0; i < const_num; i++) cvn.case_constants.AddElement((int_const_node)CreateExpression()); int range_num = br.ReadInt32(); for (int i = 0; i < range_num; i++) cvn.case_ranges.AddElement(new case_range_node((int_const_node)CreateExpression(), (int_const_node)CreateExpression(), null)); cvn.case_statement = CreateStatement(); return cvn; }