Example #1
0
    def propagate_units(self, function_dict):
        tw = TreeWalker(self.type_miner)  

        # ASSUME THE TOKENS COME BACK AS A SORTED LIST
        break_point = 1000
        i=0

        for root_token in function_dict['root_tokens']:
            #print root_token.str, root_token.linenr
            tw.is_unit_propagation_based_on_constants = False
            tw.is_unit_propagation_based_on_unknown_variable = False
            tw.found_arg_var = False
            tw.found_non_arg_var = False

            # RESET THE TREE WALKER'S LINE NUMBERS
            tw.reset_min_max_line_numbers()
            # FIND THE MIN AND MAX LINE NUMBERS IN THIS AST : USED TO PROTECT LOOP FROM MULTI-LINE STATEMENTS
            tw.generic_recurse_and_apply_function(root_token, tw.find_min_max_line_numbers)
            # SCAN VARIABLES
            tw.generic_recurse_and_apply_function(root_token, tw.scan_variables)

            # APPLY ROS UNITS TO VARIABLES
            tw.generic_recurse_and_apply_function(root_token, tw.apply_ROS_units)
            # APPLY UNITS TO KNOWN SYMBOLS
            tw.generic_recurse_and_apply_function(root_token, tw.apply_known_symbols_units)
            # APPLY UNITS FROM KNOWN FUNCTION - getX, getY, getZ  
            tw.generic_recurse_and_apply_function(root_token, tw.apply_units_getXYZ)
            # APPLY UNITS TO CONVERSION FACTORS
            tw.generic_recurse_and_apply_function(root_token, tw.apply_conversion_factor_units)
            # APPLY FUNCTION RETURN UNITS
            tw.generic_recurse_and_apply_function(root_token, tw.apply_function_return_units)
            # APPLY UNITS FROM PREVIOUS ROUND
            tw.generic_recurse_and_apply_function(root_token, tw.apply_previous_round_units)
            # APPLY DIMENSIONLESS UNITS
            tw.generic_recurse_and_apply_function(root_token, tw.apply_dimensionless_units)


            if (not tw.was_some_unit_changed):
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_return)

            
            # CONTINUE TO ATTEMPT CHANGES UNTIL CHANGES CEASE
            while tw.was_some_unit_changed:  
                if i>break_point:
                    s = "BREAKING WHILE LOOP AT %d" % break_point
                    raise ValueError(s)
                    return
                i+=1
                tw.was_some_unit_changed = False
                # LOOK FOR EARLY ABANDONMENT OF THIS AST
                if not tw.found_units_in_this_tree and self.should_abandon_early:
                    break
                ### PROPAGATE UNITS
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_dot_connectors)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_double_colon)                
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_square_brackets)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_assignment)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_math_abs_fabs_floor_ceil)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_math_min_max)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_math_fmod_fmodf_fmodl)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_sqrt)
                # tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_getXYZ)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_ternary)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_pow)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_inverse_trig)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_operators)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_return)
                tw.generic_recurse_and_apply_function(root_token, tw.collect_function_param_units_and_decorate_function)
                tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_across_parenthesis)
            # END -- WHILE LOOP

            #RETURN STATEMENT WITH UNITS - STORE UNITS
            if root_token.str == 'return' and root_token.units:
                if function_dict['scopeObject'].function:
                    function_return_units = function_dict['scopeObject'].function.return_units
                    for u in root_token.units:
                        if u not in function_return_units:
                            function_return_units.append(u)

            #ASSIGNMENT STATEMENT WITH UNITS - COLLECT MULTIPLE ASSIGNMENT INCONSISTENCY
            if root_token.isAssignmentOp:
                tw.collect_lhs_unit_constraint(root_token)
Example #2
0
    def check_error_when_top3_units(self, root_token):
        tw = TreeWalker(None)

        # ASSUME THE TOKENS COME BACK AS A SORTED LIST
        break_point = 1000
        i = 0

        tw.is_unit_propagation_based_on_constants = False
        tw.is_unit_propagation_based_on_unknown_variable = False

        # RESET THE TREE WALKER'S LINE NUMBERS
        tw.reset_min_max_line_numbers()
        # FIND THE MIN AND MAX LINE NUMBERS IN THIS AST : USED TO PROTECT LOOP FROM MULTI-LINE STATEMENTS
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.find_min_max_line_numbers)

        # APPLY ROS UNITS TO VARIABLES
        tw.generic_recurse_and_apply_function(root_token, tw.apply_ROS_units)
        # APPLY UNITS TO KNOWN SYMBOLS
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.apply_known_symbols_units)
        # APPLY UNITS FROM KNOWN FUNCTION - getX, getY, getZ
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.apply_units_getXYZ)
        # APPLY UNITS TO CONVERSION FACTORS
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.apply_conversion_factor_units)
        # APPLY FUNCTION RETURN UNITS
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.apply_function_return_units)
        # APPLY UNITS FROM PREVIOUS ROUND
        tw.generic_recurse_and_apply_function(
            root_token, tw.apply_previous_round_top3_units)
        # APPLY DIMENSIONLESS UNITS
        tw.generic_recurse_and_apply_function(root_token,
                                              tw.apply_dimensionless_units)

        if (not tw.was_some_unit_changed):
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_return)

        # CONTINUE TO ATTEMPT CHANGES UNTIL CHANGES CEASE
        while tw.was_some_unit_changed:
            if i > break_point:
                s = "BREAKING WHILE LOOP AT %d" % break_point
                raise ValueError(s)
                return
            i += 1
            tw.was_some_unit_changed = False
            # LOOK FOR EARLY ABANDONMENT OF THIS AST
            if not tw.found_units_in_this_tree:
                break
            ### PROPAGATE UNITS
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_dot_connectors)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_double_colon)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_square_brackets)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_assignment)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_math_abs_fabs_floor_ceil)
            tw.perform_intersection = True
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_math_min_max)
            tw.perform_intersection = False
            tw.perform_intersection = True
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_math_fmod_fmodf_fmodl)
            tw.perform_intersection = False
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.propagate_units_sqrt)
            # tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_getXYZ)
            tw.perform_intersection = True
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.propagate_units_ternary)
            tw.perform_intersection = False
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.propagate_units_pow)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_inverse_trig)
            tw.perform_intersection = True
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_operators)
            tw.perform_intersection = False
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_return)
            tw.generic_recurse_and_apply_function(
                root_token,
                tw.collect_function_param_units_and_decorate_function)
            tw.generic_recurse_and_apply_function(
                root_token, tw.propagate_units_across_parenthesis)
Example #3
0
    def collect_constraints(self, function_dict):
        tw = TreeWalker(self.type_miner, self.vnh)
        tw.current_file = self.current_file_under_analysis
        tw.source_file_lines = self.source_file_lines
        tw.source_file = self.source_file

        # ASSUME THE TOKENS COME BACK AS A SORTED LIST
        break_point = 1000
        i = 0
        found_units = False

        for root_token in function_dict['root_tokens']:
            #print root_token.str, root_token.linenr
            tw.is_unit_propagation_based_on_constants = False
            tw.is_unit_propagation_based_on_unknown_variable = False
            tw.current_child_vars = []
            tw.found_arg_var = False
            tw.found_non_arg_var = False

            # RESET THE TREE WALKER'S LINE NUMBERS
            tw.reset_min_max_line_numbers()
            # FIND THE MIN AND MAX LINE NUMBERS IN THIS AST : USED TO PROTECT LOOP FROM MULTI-LINE STATEMENTS
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.find_min_max_line_numbers)
            # SCAN VARIABLES
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.scan_variables)

            # APPLY ROS UNITS TO VARIABLES
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_ROS_units)
            # APPLY UNITS TO KNOWN SYMBOLS
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_known_symbols_units)
            # APPLY UNITS FROM KNOWN FUNCTION - getX, getY, getZ
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_getXYZ)
            # APPLY UNITS TO CONVERSION FACTORS
            tw.generic_recurse_and_apply_function(
                root_token, tw.apply_conversion_factor_units)
            # APPLY FUNCTION RETURN UNITS
            tw.generic_recurse_and_apply_function(
                root_token, tw.apply_function_return_units)
            # APPLY DIMENSIONLESS UNITS
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_dimensionless_units)

            if (tw.found_units_in_this_tree):
                found_units = True

            if (not tw.was_some_unit_changed):
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_return)

            # CONTINUE TO ATTEMPT CHANGES UNTIL CHANGES CEASE
            while tw.was_some_unit_changed:
                if i > break_point:
                    s = "BREAKING WHILE LOOP AT %d" % break_point
                    raise ValueError(s)
                    return
                i += 1
                tw.was_some_unit_changed = False
                # LOOK FOR EARLY ABANDONMENT OF THIS AST
                if not tw.found_units_in_this_tree and self.should_abandon_early:
                    break
                ### PROPAGATE UNITS
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_dot_connectors)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_double_colon)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_square_brackets)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_assignment)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_math_abs_fabs_floor_ceil)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_math_min_max)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_math_fmod_fmodf_fmodl)
                tw.generic_recurse_and_apply_function(root_token,
                                                      tw.propagate_units_sqrt)
                # tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_getXYZ)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_ternary)
                tw.generic_recurse_and_apply_function(root_token,
                                                      tw.propagate_units_pow)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_inverse_trig)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_operators)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_return)
                tw.generic_recurse_and_apply_function(
                    root_token,
                    tw.collect_function_param_units_and_decorate_function)
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_parenthesis)
            # END -- WHILE LOOP

            #RETURN STATEMENT WITH UNITS - STORE UNITS
            if root_token.str == 'return' and root_token.units:
                if function_dict['scopeObject'].function:
                    function_return_units = function_dict[
                        'scopeObject'].function.return_units
                    for u in root_token.units:
                        if u not in function_return_units:
                            function_return_units.append(u)

            #ASSIGNMENT STATEMENT WITH UNITS - RIGHT TO LEFT PROPAGATION CONSTRAINT
            if root_token.isAssignmentOp:
                tw.collect_lhs_unit_constraint(root_token)

            #tw.generic_recurse_and_apply_function(root_token, tw.collect_implied_non_unit_variables)
            #SAME UNIT CONSTRAINTS
            tw.generic_recurse_and_apply_function(
                root_token, tw.collect_same_unit_constraints)
            tw.generic_recurse_and_apply_function(
                root_token, tw.collect_same_unit_constraints_II)
            tw.generic_recurse_and_apply_function(
                root_token, tw.collect_same_unit_constraints_III)
            #CONVERSION FACTOR CONSTRAINTS
            #tw.generic_recurse_and_apply_function(root_token, tw.collect_conversion_factor_constraints)
            tw.generic_recurse_and_apply_function(
                root_token, tw.collect_angle_unit_constraints)
            #KNOWN SYMBOL CONSTRAINTS
            tw.generic_recurse_and_apply_function(
                root_token, tw.collect_known_symbol_constraints)
            if not self.SHOULD_USE_DEEP_LEARNING_VAR_NAME_HEURISTIC:
                #NAMING CONSTRAINTS
                tw.generic_recurse_and_apply_function(
                    root_token, tw.collect_naming_constraints)
            else:
                #DEEP LEARNING NAMING CONSTRAINTS
                tw.generic_recurse_and_apply_function(
                    root_token, tw.collect_deep_network_naming_constraints)
        # END -- FOR LOOP

        if (not found_units) and function_dict['scopeObject'].function \
                and ((not tw.found_var) or (tw.found_arg_or_local_var)):
            #and function_dict['scopeObject'].function.argument:
            function_dict['scopeObject'].function.maybe_generic_function = True
    def analyze_function(self, function_dict):

        if self.debug_verbose:
            print inspect.stack()[0][3]
        tw = TreeWalker(
            function_dict
        )  # ARGUMENT 'FUNCTION DICTIONARY' IS USED BY SYMBOL TABLE
        tw.cps_unit_checker = self
        tw.my_symbol_helper.cps_unit_checker = self
        self.tw = tw  # LINK CURRENT Tree Walker to self
        tw.debug = self.debug
        tw.debug_verbose = self.debug_verbose
        tw.current_file = self.current_file_under_analysis
        tw.source_file_lines = self.source_file_lines
        tw.source_file = self.source_file
        tw.should_check_unitless_during_multiplication = False  # UNITLESS
        tw.my_symbol_helper.should_match_on_heuristic_variable_names = False
        tw.current_function_dict = function_dict

        found_units_in_this_function = False

        # ASSUME THE TOKENS COME BACK AS A SORTED LIST
        break_point = 1000
        i = 0

        for root_token in function_dict['root_tokens']:
            # INITIALIZAE TREE WALKER FOR THIS ROOT TOKEN
            tw.was_some_unit_changed = True
            tw.is_unit_propagation_based_on_constants = False
            tw.is_unit_propagation_based_on_unknown_variable = False
            if self.SHOULD_ONLY_FIND_FILES_WITH_UNITS and self.found_ros_units_in_this_file and not self.SHOULD_FIND_ALL_UNITS:
                return
            # RESET THE TREE WALKER'S LINE NUMBERS
            tw.reset_min_max_line_numbers()
            # FIND THE MIN AND MAX LINE NUMBERS IN THIS AST : USED TO PROTECT LOOP FROM MULTI-LINE STATEMENTS
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.find_min_max_line_numbers)

            # APPLY ROS UNITS TO VARIABLES
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_ROS_units)
            # APPLY UNITS FROM PREVIOUS ASSIGNMENTS IN SCOPE
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_from_scope)
            # APPLY UNITS FROM KNOWN FUNCTIONS - atan2
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_inverse_trig)
            # APPLY UNITS FROM KNOWN SYMBOLS - M_PI
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_known_symbols)
            # APPLY UNITS FROM KNOWN FUNCTION - toSec
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_toSec)
            # APPLY UNITS FROM KNOWN FUNCTION - getX, getY, getZ
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_getXYZ)
            # APPLY UNITS FROM KNOWN FUNCTION - quatToRPY
            tw.generic_recurse_and_apply_function(root_token,
                                                  tw.apply_units_quatToRPY)

            # CONTINUE TO ATTEMPT CHANGES UNTIL CHANGES CEASE
            while tw.was_some_unit_changed:
                if i > break_point:
                    if self.debug_verbose:
                        s = "BREAKING QUIESSENCE (WHILE) LOOP AT %d" % break_point
                        raise ValueError(s)
                        return
                    break
                i += 1
                tw.was_some_unit_changed = False
                # LOOK FOR EARLY ABANDONMENT OF THIS AST
                if not tw.found_units_in_this_tree and self.should_abandon_early:
                    break
                # SPECIAL MODE - JUST FIND ROS FILES
                if self.SHOULD_ONLY_FIND_FILES_WITH_UNITS:
                    break
                ### PROPAGATE ACROSS '.'
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_dot_connectors)
                ### PROPAGATE ACROSS + - * /  += -= *= /=
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_operators)
                ### PROPAGATE ACROSS (
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_parenthesis)
                ### PROPAGATE ACROSS [
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_square_brackets)
                ### PROPAGATE INTO f(meters, arg2)  into function  - FUTURE: CONSTRAINT MODE
                #tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_into_function_args)
                ### PROPAGATE ACROSS '='
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_assignment)
                ### PROPAGATE ACROSS 'std::abs' 'std::fabs' 'abs' 'fabs'
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_math_abs_fabs_floor_ceil)
                ### PROPAGATE ACROSS 'std::min' 'std::max' 'min' 'max'
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_math_min_max)
                ### PROPAGATE ACROSS 'sqrt'
                tw.generic_recurse_and_apply_function(root_token,
                                                      tw.propagate_units_sqrt)
                ### PROPAGATE ACROSS 'getXYZ
                # tw.generic_recurse_and_apply_function(root_token, tw.propagate_units_getXYZ)
                ### PROPAGATE ACROSS TERNARY
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_ternary)
                ### PROPAGATE ACROSS 'pow'
                tw.generic_recurse_and_apply_function(root_token,
                                                      tw.propagate_units_pow)
                ### PROPAGATE ACROSS 'atan2', 'acos', 'asin'
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_inverse_trig)
                ### PROPAGATE ACROSS 'return'
                tw.generic_recurse_and_apply_function(
                    root_token, tw.propagate_units_across_return)
                ### COLLECT UNITS FROM FUNCTION CALL POINTS
                tw.generic_recurse_and_apply_function(
                    root_token, tw.
                    collect_function_parameters_units_and_decorate_function_objects
                )
                #FUNCTIONS todo:
            # END -- WHILE LOOP
            #ASSIGNMENT STATEMENTS WITH UNITS - RIGHT TO LEFT PROPAGATION
            if root_token.isAssignmentOp and root_token.units:
                # COLLECT LEFT SIDE OF ASSIGNMENT
                lhs_compound_name = tw.recurse_and_collect_string(
                    root_token.astOperand1)
                # ADD UNITS TO VARIABLE IN SCOPE
                tw.return_value_list = []
                tw.generic_recurse_and_apply_function(root_token.astOperand1,
                                                      tw.find_first_variable)
                if len(tw.return_value_list) != 1:
                    if len(tw.return_value_list) == 0:
                        if self.debug and self.debug_LHS:
                            print "%s %s LHS no variable found not found" % (
                                root_token.file, root_token.linenr)
                    else:
                        if self.debug and self.debug_LHS:
                            for value in tw.return_value_list:
                                print "%s %s LHS Variable found: %s" % (
                                    root_token.file, root_token.linenr, value)
                    continue  # todo track count of this error
                lhs_var = tw.return_value_list[0]
                lhs_scope = lhs_var.nameToken.scope
                if lhs_var.isArgument:
                    lhs_scope = function_dict['scopeObject']

                line_num = int(root_token.linenr)
                if lhs_compound_name in lhs_scope.var_ordered_dict:
                    # ALREADY HAS ASSIGNMENT, ADD TO IT
                    lhs_scope.var_ordered_dict[lhs_compound_name][line_num] = {
                        'units':
                        root_token.units,  # THIS IS A LIST 
                        'token':
                        root_token,
                        'is_unit_propagation_based_on_constants':
                        tw.is_unit_propagation_based_on_constants,
                        'is_unit_propagation_based_on_unknown_variable':
                        tw.is_unit_propagation_based_on_unknown_variable
                    }
                else:
                    lhs_scope.var_ordered_dict[lhs_compound_name] = {
                        line_num: {
                            'units':
                            root_token.units,
                            'token':
                            root_token,
                            'is_unit_propagation_based_on_constants':
                            tw.is_unit_propagation_based_on_constants,
                            'is_unit_propagation_based_on_unknown_variable':
                            tw.is_unit_propagation_based_on_unknown_variable
                        }
                    }

                if self.debug and self.debug_scope:
                    print "ADDED to SCOPE %s : %s has units %s at %s" % (
                        lhs_scope.Id, lhs_compound_name, root_token.units,
                        line_num)
                    print 'constants-based? %s  unknown-based? %s' % (
                        tw.is_unit_propagation_based_on_constants,
                        tw.is_unit_propagation_based_on_unknown_variable)
            # EXTRACT UNITS FROM RETURN STATEMENT AND APPLY TO FUNCTION
            if root_token.str == 'return' and root_token.units:
                if function_dict['scopeObject'].function:
                    function_return_units = function_dict[
                        'scopeObject'].function.return_units
                    for u in root_token.units:
                        if u not in function_return_units:
                            function_return_units.append(u)
                            function_dict[
                                'scopeObject'].function.is_unit_propagation_based_on_constants = tw.is_unit_propagation_based_on_constants
                            function_dict[
                                'scopeObject'].function.is_unit_propagation_based_on_unknown_variable = tw.is_unit_propagation_based_on_unknown_variable
            found_units_in_this_function = found_units_in_this_function or tw.found_units_in_this_tree

        # LOOK FOR EARLY ABANDONMENT
        if not found_units_in_this_function and not self.debug_print_AST and self.should_abandon_early:
            return

        # DEBUG PRINTING
        for root_token in function_dict['root_tokens']:
            if self.debug_print_AST:
                tw.debug_walk(root_token)

        self.found_ros_units_in_this_file = self.found_ros_units_in_this_file or found_units_in_this_function