示例#1
0
def test_Lark_DecayModelParamValueReplacement_Visitor_list():
    t = Tree('decay', [
        Tree('particle', [Token('LABEL', 'B0sig')]),
        Tree('decayline', [
            Tree('value', [Token('SIGNED_NUMBER', '1.000')]),
            Tree('particle', [Token('LABEL', 'MyFirstD*-')]),
            Tree('particle', [Token('LABEL', 'MySecondD*+')]),
            Tree('model', [
                Token('MODEL_NAME', 'SVV_HELAMP'),
                Tree('model_options', [
                    Tree('value', [Token('SIGNED_NUMBER', '0.0')]),
                    Tree('value', [Token('SIGNED_NUMBER', '0.0')]),
                    Tree('value', [Token('SIGNED_NUMBER', '0.0')]),
                    Tree('value', [Token('SIGNED_NUMBER', '0.0')]),
                    Tree('value', [Token('SIGNED_NUMBER', '1.0')]),
                    Tree('value', [Token('SIGNED_NUMBER', '0.0')])
                ])
            ])
        ])
    ])

    DecayModelParamValueReplacement().visit(t)

    # The visitor should do nothing in this case
    tree_decayline = list(t.find_data('decayline'))[0]
    assert get_model_name(tree_decayline) == 'SVV_HELAMP'
    assert get_model_parameters(tree_decayline) == [
        0.0, 0.0, 0.0, 0.0, 1.0, 0.0
    ]
示例#2
0
def test_Lark_DecayModelParamValueReplacement_Visitor_single_value():
    t = Tree('decay', [
        Tree('particle', [Token('LABEL', 'Upsilon(4S)')]),
        Tree('decayline', [
            Tree('value', [Token('SIGNED_NUMBER', '1.0')]),
            Tree('particle', [Token('LABEL', 'B0')]),
            Tree('particle', [Token('LABEL', 'anti-B0')]),
            Tree('model', [
                Token('MODEL_NAME', 'VSS_BMIX'),
                Tree('model_options', [Token('LABEL', 'dm')])
            ])
        ])
    ])

    DecayModelParamValueReplacement().visit(t)

    # Nothing done since model parameter name has no corresponding
    # 'Define' statement from which the actual value can be inferred
    tree_decayline = list(t.find_data('decayline'))[0]
    assert get_model_name(tree_decayline) == 'VSS_BMIX'
    assert get_model_parameters(tree_decayline) == ['dm']

    dict_define_defs = {'dm': 0.507e12}

    DecayModelParamValueReplacement(define_defs=dict_define_defs).visit(t)

    # The model parameter 'dm' should now be replaced by its value
    assert get_model_name(tree_decayline) == 'VSS_BMIX'
    assert get_model_parameters(tree_decayline) == [507000000000.0]
示例#3
0
def _unused_argument_check(parse_tree: Tree) -> List[Problem]:
    problems = []
    for func_def in parse_tree.find_data("func_def"):
        if (isinstance(func_def.children[1], Tree)
                and func_def.children[1].data == "func_args"):
            argument_definitions = {}  # type: Dict[str, int]
            argument_tokens = {}
            func_args = func_def.children[1]
            for func_arg in func_args.children:
                arg_name_token = find_name_token_among_children(func_arg)
                arg_name = arg_name_token.value
                argument_definitions[arg_name] = (
                    argument_definitions.get(arg_name, 0) + 1)
                argument_tokens[arg_name] = arg_name_token
            name_occurances = {}  # type: Dict[str, int]
            for xnode in func_def.iter_subtrees():
                for node in xnode.children:
                    if isinstance(node, Token) and node.type == "NAME":
                        name = node.value
                        name_occurances[name] = name_occurances.get(name,
                                                                    0) + 1
            for argument in argument_definitions:
                if argument_definitions[argument] == name_occurances[
                        argument] and not argument.startswith("_"):
                    problems.append(
                        Problem(
                            name="unused-argument",
                            description="unused function argument '{}'".format(
                                argument),
                            line=argument_tokens[argument].line,
                            column=argument_tokens[argument].column,
                        ))
    return problems
def _class_definitions_order_check(order, parse_tree: Tree) -> List[Problem]:
    problems = _class_definitions_order_check_for_class(
        "global scope", parse_tree.children, order)
    for class_def in parse_tree.find_data("class_def"):
        class_name = class_def.children[0].value
        problems += _class_definitions_order_check_for_class(
            "class {}".format(class_name), class_def.children, order)
    return problems
示例#5
0
 def _load_elements(enum_def: Tree) -> List[EnumElement]:
     elements = []
     for enum_element in enum_def.find_data("enum_element"):
         name = enum_element.children[0].value
         value = (standalone_expression_to_str(enum_element.children[1])
                  if len(enum_element.children) > 1 else None)
         elements.append(
             EnumElement(name=name, value=value, lark_node=enum_element))
     return elements
示例#6
0
def _comparison_with_itself_check(parse_tree: Tree) -> List[Problem]:
    problems = []
    for comparison in parse_tree.find_data("comparison"):
        assert len(comparison.children) == 3
        if comparison.children[0] == comparison.children[2]:
            problems.append(
                Problem(
                    name="comparison-with-itself",
                    description="Redundant comparison",
                    line=comparison.line,
                    column=comparison.column,
                ))
    return problems
示例#7
0
def gen_enum(tree: Tree) -> type:
    assert tree.data == "enum"
    name_node = tree.children[2]
    class_name = name_node.value

    assert tree.children[0].type == "ENUM_NAME"
    assert name_node.type == "CUSTOM_TYPE_NAME"

    attrs = {}
    for rule in tree.find_data('enum_line'):
        attrs[rule.children[0].value] = rule.children[2].value

    cls = Enum(class_name, attrs, module=__name__)
    return cls
示例#8
0
def test_Lark_DecayModelParamValueReplacement_Visitor_list():
    t = Tree(
        "decay",
        [
            Tree("particle", [Token("LABEL", "B0sig")]),
            Tree(
                "decayline",
                [
                    Tree("value", [Token("SIGNED_NUMBER", "1.000")]),
                    Tree("particle", [Token("LABEL", "MyFirstD*-")]),
                    Tree("particle", [Token("LABEL", "MySecondD*+")]),
                    Tree(
                        "model",
                        [
                            Token("MODEL_NAME", "SVV_HELAMP"),
                            Tree(
                                "model_options",
                                [
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "0.0")]),
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "0.0")]),
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "0.0")]),
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "0.0")]),
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "1.0")]),
                                    Tree("value",
                                         [Token("SIGNED_NUMBER", "0.0")]),
                                ],
                            ),
                        ],
                    ),
                ],
            ),
        ],
    )

    DecayModelParamValueReplacement().visit(t)

    # The visitor should do nothing in this case
    tree_decayline = list(t.find_data("decayline"))[0]
    assert get_model_name(tree_decayline) == "SVV_HELAMP"
    assert get_model_parameters(tree_decayline) == [
        0.0, 0.0, 0.0, 0.0, 1.0, 0.0
    ]
示例#9
0
def test_Lark_DecayModelParamValueReplacement_Visitor_no_params():
    t = Tree('decay', [
        Tree('particle', [Token('LABEL', 'D0')]),
        Tree('decayline', [
            Tree('value', [Token('SIGNED_NUMBER', '1.0')]),
            Tree('particle', [Token('LABEL', 'K-')]),
            Tree('particle', [Token('LABEL', 'pi+')]),
            Tree('model', [Token('MODEL_NAME', 'PHSP')])
        ])
    ])

    DecayModelParamValueReplacement().visit(t)

    # The visitor should do nothing in this case
    tree_decayline = list(t.find_data('decayline'))[0]
    assert get_model_name(tree_decayline) == 'PHSP'
    assert get_model_parameters(tree_decayline) == ''
def _function_args_num_check(threshold, parse_tree: Tree) -> List[Problem]:
    problems = []
    for func_def in parse_tree.find_data("func_def"):
        func_name_token = func_def.children[0]
        assert func_name_token.type == "NAME"
        func_name = func_name_token.value
        if (isinstance(func_def.children[1], Tree)
                and func_def.children[1].data == "func_args"):
            args_num = len(func_def.children[1].children)
            if args_num > threshold:
                problems.append(
                    Problem(
                        name="function-arguments-number",
                        description='Function "{}" has more than {} arguments'.
                        format(func_name, threshold),
                        line=func_name_token.line,
                        column=func_name_token.column,
                    ))
    return problems
def _expression_not_assigned_check(parse_tree: Tree) -> List[Problem]:
    problems = []
    for expr_stmt in parse_tree.find_data("expr_stmt"):
        expr = expr_stmt.children[0]
        child = expr.children[0]
        if not isinstance(child, Tree) or child.data not in [
                "assnmnt_expr",
                "standalone_call",
                "getattr_call",
                "string",
        ]:
            problems.append(
                Problem(
                    name="expression-not-assigned",
                    description=
                    "expression is not asigned, and hence it can be removed",
                    line=child.line,
                    column=child.column,
                ))
    return problems
def _private_method_call_check(parse_tree: Tree) -> List[Problem]:
    problems = []
    for getattr_call in parse_tree.find_data("getattr_call"):
        _getattr = getattr_call.children[0]
        callee_name_token = _getattr.children[-1]
        callee_name = callee_name_token.value
        called = _getattr.children[-2]
        if (isinstance(called, Token) and called.type == "NAME"
                and called.value == "self"):
            continue
        if not _is_method_private(callee_name):
            continue
        problems.append(
            Problem(
                name="private-method-call",
                description='Private method "{}" has been called'.format(
                    callee_name),
                line=callee_name_token.line,
                column=callee_name_token.column,
            ))
    return problems
示例#13
0
def gen_struct(tree: Tree) -> type:
    assert tree.data == "struct"
    name_node = tree.children[2]
    class_name = name_node.value

    assert tree.children[0].type == "STRUCT_NAME"
    assert name_node.type == "CUSTOM_TYPE_NAME"

    fields = []
    for rule in tree.find_data('struct_line'):
        typ = get_type(rule.children[0])
        field_name = rule.children[2].value
        fields.append((
            field_name,
            typ,
        ))

    if len(fields) != len(set(f[0] for f in fields)):
        raise DuplicateFieldError("Duplicate field in struct")

    cls = make_dataclass(class_name, fields)
    return cls
示例#14
0
def gen_message(tree: Tree) -> type:
    # TODO: Handle the integer mapping
    assert tree.data == "message"
    name_node = tree.children[2]
    class_name = name_node.value

    assert tree.children[0].type == "MESSAGE_NAME"
    assert name_node.type == "CUSTOM_TYPE_NAME"

    fields = []
    for rule in tree.find_data('message_line'):
        typ = get_type(rule.children[2])
        field_name = rule.children[4].value
        fields.append((
            field_name,
            typ,
        ))
    if len(fields) != len(set(f[0] for f in fields)):
        raise DuplicateFieldError("Duplicate field in message")

    cls = make_dataclass(class_name, fields)
    return cls
示例#15
0
def test_Lark_DecayModelParamValueReplacement_Visitor_single_value():
    t = Tree(
        "decay",
        [
            Tree("particle", [Token("LABEL", "Upsilon(4S)")]),
            Tree(
                "decayline",
                [
                    Tree("value", [Token("SIGNED_NUMBER", "1.0")]),
                    Tree("particle", [Token("LABEL", "B0")]),
                    Tree("particle", [Token("LABEL", "anti-B0")]),
                    Tree(
                        "model",
                        [
                            Token("MODEL_NAME", "VSS_BMIX"),
                            Tree("model_options", [Token("LABEL", "dm")]),
                        ],
                    ),
                ],
            ),
        ],
    )

    DecayModelParamValueReplacement().visit(t)

    # Nothing done since model parameter name has no corresponding
    # 'Define' statement from which the actual value can be inferred
    tree_decayline = list(t.find_data("decayline"))[0]
    assert get_model_name(tree_decayline) == "VSS_BMIX"
    assert get_model_parameters(tree_decayline) == ["dm"]

    dict_define_defs = {"dm": 0.507e12}

    DecayModelParamValueReplacement(define_defs=dict_define_defs).visit(t)

    # The model parameter 'dm' should now be replaced by its value
    assert get_model_name(tree_decayline) == "VSS_BMIX"
    assert get_model_parameters(tree_decayline) == [507000000000.0]
示例#16
0
def _duplicated_load_check(parse_tree: Tree) -> List[Problem]:
    problems = []
    loaded_strings = set()  # type: Set[str]
    for call in parse_tree.find_data("standalone_call"):
        name_token = call.children[0]
        callee_name = name_token.value
        if (callee_name in ["load", "preload"] and len(call.children) > 1
                and isinstance(call.children[2], Tree)
                and call.children[2].data == "string"):
            string_rule = call.children[2]
            loaded_string = string_rule.children[0].value
            if loaded_string in loaded_strings:
                problems.append(
                    Problem(
                        name="duplicated-load",
                        description="duplicated loading of {}".format(
                            loaded_string),
                        line=string_rule.line,
                        column=string_rule.column,
                    ))
            else:
                loaded_strings.add(loaded_string)
    return problems
示例#17
0
def test_Lark_DecayModelParamValueReplacement_Visitor_no_params():
    t = Tree(
        "decay",
        [
            Tree("particle", [Token("LABEL", "D0")]),
            Tree(
                "decayline",
                [
                    Tree("value", [Token("SIGNED_NUMBER", "1.0")]),
                    Tree("particle", [Token("LABEL", "K-")]),
                    Tree("particle", [Token("LABEL", "pi+")]),
                    Tree("model", [Token("MODEL_NAME", "PHSP")]),
                ],
            ),
        ],
    )

    DecayModelParamValueReplacement().visit(t)

    # The visitor should do nothing in this case
    tree_decayline = list(t.find_data("decayline"))[0]
    assert get_model_name(tree_decayline) == "PHSP"
    assert get_model_parameters(tree_decayline) == ""