Пример #1
0
def detect_unused_vars(model):
    """
    Warns about unused variables -- they may indicate typos.
    """
    # First of all, iterate over all variables and mark their usage of other
    # variables. Notice that it's possible that some code explicitly marked
    # variables as used with mark_variables_as_used() before this step.
    for var in model.all_variables():
        usage_tracker.visit(var.value)

    # Not emit warnings for unused variables.
    import re

    regex_vs_option = re.compile(r"vs[0-9]+\.option\.")

    for var in model.all_variables():
        if (
            not var.is_property
            and not usage_tracker.is_used(var)
            and
            # FIXME: Handle these cases properly. Have a properties group
            #        declaration similar to Property, with type checking and
            #        automated docs and all. Then test for it here as other
            #        properties are tested for.
            not regex_vs_option.match(var.name)
            and
            # FIXME: Handle this case properly.
            var.name != "configurations"
        ):
            warning('variable "%s" is never used', var.name, pos=var.value.pos)
Пример #2
0
def normalize_and_validate_bool_subexpressions(model):
    """
    Normalizes bool expressions, i.e. ensures the conditions are valid bools.
    variables' values with respect to their types.
    """
    logger.debug("checking boolean expressions")
    for var in model.all_variables():
        bkl.vartypes.normalize_and_validate_bool_subexpressions(var.value)
Пример #3
0
def simplify_exprs(model):
    """
    Simplify expressions in the model. This does "cheap" simplifications such
    as merging concatenated literals, recognizing always-false conditions,
    eliminating unnecessary variable references (turn ``foo=$(x);bar=$(foo)``
    into ``bar=$(x)``) etc.
    """
    logger.debug("simplifying expressions")
    simplifier = simplify.BasicSimplifier()
    for var in model.all_variables():
        var.value = simplifier.visit(var.value)
Пример #4
0
def normalize_vars(model):
    """
    Normalizes variables' values with respect to their types. For example,
    changes non-list value expressions for lists into single-item lists.
    """
    logger.debug("normalizing variables")
    for var in model.all_variables():
        # if the type of the variable wasn't determined yet, guess it
        if var.type is bkl.vartypes.TheAnyType:
            var.type = bkl.vartypes.guess_expr_type(var.value)
        # normalize the value for the type
        var.value = var.type.normalize(var.value)
Пример #5
0
def detect_self_references(model):
    """
    Verifies that recursive self-referencing loops (e.g. "foo = $(foo)")
    don't exist.
    """
    logger.debug("checking for self-references")

    class SelfRefChecker(Visitor):
        def __init__(self):
            super(SelfRefChecker, self).__init__()
            self.stack = []
            self.checked = set()

        literal = Visitor.noop
        bool_value = Visitor.noop
        null = Visitor.noop
        concat = Visitor.visit_children
        list = Visitor.visit_children
        path = Visitor.visit_children
        bool = Visitor.visit_children
        if_ = Visitor.visit_children
        placeholder = Visitor.noop

        def reference(self, e):
            var = e.get_variable()
            if var is None:
                # reference to default value of a property
                return
            if var in self.stack:
                # TODO: include complete stack of messages+positions
                raise Error(
                    'variable "%s" is defined recursively, references itself' %
                    var.name,
                    pos=e.pos)
            else:
                self.check(var)

        def check(self, var):
            if var in self.checked:
                return
            self.stack.append(var)
            try:
                self.visit(var.value)
            finally:
                self.stack.pop()
            self.checked.add(var)

    visitor = SelfRefChecker()

    for var in model.all_variables():
        visitor.check(var)
Пример #6
0
def validate_vars(model):
    """
    Validates variables' values with respect to their types, i.e. check
    the correctness of the values. It is assumed that normalize_vars() was
    executed beforehand.
    """
    logger.debug("checking types of variables")
    for var in model.all_variables():
        try:
            var.type.validate(var.value)
        except TypeError as err:
            # TODO: add this as a remark to the error object
            err.msg = "variable \"%s\" (%s): %s" % (var.name, var.type, err.msg)
            raise
Пример #7
0
def detect_self_references(model):
    """
    Verifies that recursive self-referencing loops (e.g. "foo = $(foo)")
    don't exist.
    """
    logger.debug("checking for self-references")

    class SelfRefChecker(Visitor):
        def __init__(self):
            super(SelfRefChecker, self).__init__()
            self.stack = []
            self.checked = set()

        literal = Visitor.noop
        bool_value = Visitor.noop
        null = Visitor.noop
        concat = Visitor.visit_children
        list = Visitor.visit_children
        path = Visitor.visit_children
        bool = Visitor.visit_children
        if_ = Visitor.visit_children
        placeholder = Visitor.noop

        def reference(self, e):
            var = e.get_variable()
            if var is None:
                # reference to default value of a property
                return
            if var in self.stack:
                # TODO: include complete stack of messages+positions
                raise Error('variable "%s" is defined recursively, references itself' % var.name,
                            pos=e.pos)
            else:
                self.check(var)

        def check(self, var):
            if var in self.checked:
                return
            self.stack.append(var)
            try:
                self.visit(var.value)
            finally:
                self.stack.pop()
            self.checked.add(var)

    visitor = SelfRefChecker()

    for var in model.all_variables():
        visitor.check(var)
Пример #8
0
def detect_unused_vars(model):
    """
    Warns about unused variables -- they may indicate typos.
    """
    # First of all, iterate over all variables and mark their usage of other
    # variables. Notice that it's possible that some code explicitly marked
    # variables as used with mark_variables_in_expr_as_used() before this step.
    for var in model.all_variables():
        usage_tracker.visit(var.value)

    # Not emit warnings for unused variables.
    import re
    regex_vs_option = re.compile(r'vs[0-9]+\.option\.')

    for var in model.all_variables():
        if (not var.is_property and not usage_tracker.is_used(var) and
                # FIXME: Handle these cases properly. Have a properties group
                #        declaration similar to Property, with type checking and
                #        automated docs and all. Then test for it here as other
                #        properties are tested for.
                not regex_vs_option.match(var.name) and
                # FIXME: Handle this case properly.
                var.name != "configurations"):
            warning('variable "%s" is never used', var.name, pos=var.value.pos)
Пример #9
0
def eliminate_superfluous_conditionals(model):
    """
    Removes as much of conditional content as possible. This involves doing
    as many optimizations as possible, even if the calculation is relatively
    expensive (compared to simplify_exprs()).
    """
    iteration = 1
    simplifier = simplify.ConditionalsSimplifier()
    while True:
        logger.debug("removing superfluous conditional expressions: pass %i", iteration)
        modified = False
        for var in model.all_variables():
            old = var.value
            var.value = simplifier.visit(var.value)
            if old is not var.value:
                logger.debug("new pass triggered because of this change: {%s} -> {%s}", old, var.value)
                modified = True
        if modified:
            iteration += 1
        else:
            break