예제 #1
0
def generate_type_struct(program, function, old_type):
    # Do we take an existing struct with the type we want?
    reuse_struct = probs_helper.random_value(probs.reuse_struct_prob)
    structs = [s for s in program.structs if s.has_type(old_type)]
    existing_structs = len(structs)
    if reuse_struct and existing_structs > 0:
        selected = probs_helper.random_value(
            probs_helper.compute_equal_prob(range(existing_structs)))
        # An existing struct is taken
        return structs[selected]

    # Do we add a new field to an existing struct to create the expected one?
    reuse_struct = probs_helper.random_value(
        probs.enhance_existing_struct_prob)
    existing_structs = len(program.structs)
    if reuse_struct and existing_structs > 0:
        if isinstance(
                old_type,
                ast.Struct) or (isinstance(old_type, ast.Array)
                                and isinstance(old_type.type, ast.Struct)):
            # Take the least referenced struct. They are ordered by the number of references and the min is selected.
            # E.g.:
            #  struct0 -> struct1 -> array(struct2) -> struct3      # La struct3 has a reference depth of 3
            #  strunc4                                              # La struct4 has a reference depth of 0
            #  struct5 -> struct6                                   # La struct6 has a reference depth of 1
            struct_t = min(program.structs,
                           key=lambda s: max(
                               len(path)
                               for path in ast.reference_paths_to_struct(
                                   s, program.structs)))
        else:
            selected = probs_helper.random_value(
                probs_helper.compute_equal_prob(range(existing_structs)))
            struct_t = program.structs[selected]

        if not struct_t.check_circular_reference(old_type):
            # An existing struct is taken
            if not struct_t.has_type(old_type):
                struct_t.add_field(
                    ast.name_struct_field(old_type, len(struct_t.fields)),
                    old_type)
            return struct_t

    # A new struct is created with that particular field
    struct_name = "struct" + str(len(program.structs))
    struct_t = ast.Struct(struct_name,
                          [ast.name_struct_field(old_type, 0), old_type])
    program.structs.append(struct_t)
    return struct_t
예제 #2
0
def generate_lvalue(program, function, exp_type, exp_depth_prob):
    exp_depth = probs_helper.random_value(exp_depth_prob
                                          or probs.exp_depth_prob)

    if exp_depth == 0:
        return generate_basic_lvalue(program, function, exp_type)

    lower_exp_depth_prob = probs_helper.compute_equal_prob(range(0, exp_depth))

    operators = ast.get_operators(exp_type, "lvalue")
    if len(operators) == 0:
        return generate_basic_lvalue(program, function, exp_type)

    operator, _ = probs_helper.random_value(operators)
    if operator == "[]":
        return generate_expression_arity_2(
            program,
            function,
            exp_type,
            operator,
            default_generator_1=generate_lvalue,
            generator_1_depth_prob=lower_exp_depth_prob,
            default_generator_2=generate_expression,
            generator_2_depth_prob=None)
    return generate_expression_arity_1(
        program,
        function,
        exp_type,
        operator,
        default_generator_1=generate_lvalue,
        generator_1_depth_prob=lower_exp_depth_prob)
예제 #3
0
def generate_function(program, function, return_type):
    # Do we take an existing function?
    if isinstance(return_type, ast.Void):
        reuse = probs_helper.random_value(probs.reuse_proc_prob)
    else:
        reuse = probs_helper.random_value(probs.reuse_func_prob)
    functions = program.get_functions_by_return_type(return_type)
    # avoid recursion by default
    if reuse and len(functions):
        selected = probs_helper.random_value(
            probs_helper.compute_equal_prob(range(len(functions))))
        if functions[selected].name != function.name:
            # An existing function is taken
            return functions[selected]

    # A new one is created
    param_types = generate_function_param_types(program, function)
    func_name = "func" + str(len(program.functions))
    new_function = ast.Function(func_name, return_type, param_types)
    program.functions.append(new_function)
    # Generates the statements in the function
    number_statements = probs_helper.random_value(probs.number_stmts_func_prob)
    for i in range(number_statements):
        new_function.stmts.append(generate_stmt_func(program, new_function))
    if not isinstance(return_type, ast.Void):
        new_function.stmts.append(
            generate_stmt_return(program, new_function, None))
    return new_function
예제 #4
0
def generate_expression_arity_3(program, function, exp_type, operator,
                                default_generator_1, generator_1_depth_prob,
                                default_generator_2, generator_2_depth_prob,
                                default_generator_3, generator_3_depth_prob,
                                **kwargs):
    # Infer types and select one pair
    types_pairs = type_inference.infer_operands_type(program, function, 3,
                                                     operator, exp_type)
    sub_exp_1_type, sub_exp_2_type, sub_exp_2_type = probs_helper.random_value(
        probs_helper.compute_equal_prob(types_pairs))

    sub_exp_1 = default_generator_1(program,
                                    function,
                                    sub_exp_1_type,
                                    exp_depth_prob=generator_1_depth_prob)
    sub_exp_2 = default_generator_2(program,
                                    function,
                                    sub_exp_2_type,
                                    exp_depth_prob=generator_2_depth_prob)
    sub_exp_3 = default_generator_3(program,
                                    function,
                                    sub_exp_2_type,
                                    exp_depth_prob=generator_3_depth_prob)
    return ast.TernaryExpression(sub_exp_1, sub_exp_2, sub_exp_3, operator,
                                 exp_type)
예제 #5
0
def generate_stmt_augmented_assignment(program, function):

    # Get type
    augmented_assignment_type_cls = probs_helper.random_value(
        probs.augmented_assignment_types_prob)
    augmented_assignment_type = generate_type(
        program,
        function,
        new_type_cls=augmented_assignment_type_cls,
        old_type_obj=None)

    # Generate left part
    left_exp = generate_lvalue(program, function, augmented_assignment_type,
                               None)

    # Get operator
    operators = ast.get_operators(augmented_assignment_type, "assignment")
    if not operators:
        operator = "="
    else:
        operator, _ = probs_helper.random_value(operators)

    # Generate right part
    right_types = type_inference.infer_operands_type(
        program, function, 1, operator, augmented_assignment_type)

    right_type = probs_helper.random_value(
        probs_helper.compute_equal_prob(right_types))
    right_exp = generate_expression(program, function, right_type, None)

    # Compose all
    return ast.Assignment(left_exp, operator, right_exp,
                          augmented_assignment_type)
예제 #6
0
def generate_expression_arity_1(program, function, exp_type, operator,
                                default_generator_1, generator_1_depth_prob,
                                **kwargs):
    # Infer types and select one
    sub_exp_1_types = type_inference.infer_operands_type(
        program, function, 1, operator, exp_type)
    sub_exp_1_type = probs_helper.random_value(
        probs_helper.compute_equal_prob(sub_exp_1_types))

    if operator in ["++", "--"]:
        return generate_expression_incdec(program, function, sub_exp_1_type,
                                          operator)

    if operator == "&":
        sub_exp_1 = generate_lvalue(program, function, sub_exp_1_type, None)
        return ast.UnaryExpression(operator,
                                   sub_exp_1,
                                   exp_type,
                                   post_op=False)

    if operator in [".", "->"]:
        sub_exp_1 = default_generator_1(program,
                                        function,
                                        sub_exp_1_type,
                                        exp_depth_prob=generator_1_depth_prob)
        if operator == ".":
            # Type -> Struct
            field = sub_exp_1_type.get_field_by_type(exp_type)
            return ast.StructAccessExpression(operator, sub_exp_1, field,
                                              exp_type)

        if operator == "->":
            # Type -> Pointer(Struct)
            field = sub_exp_1_type.type.get_field_by_type(exp_type)
            return ast.StructAccessExpression(operator, sub_exp_1, field,
                                              exp_type)

        raise AssertionError("Unknown operator")

    if operator == '()':
        sub_exp_1 = default_generator_1(program,
                                        function,
                                        sub_exp_1_type,
                                        exp_depth_prob=generator_1_depth_prob)
        return ast.CastExpression(sub_exp_1, exp_type)

    # Otherwise
    sub_exp_1 = default_generator_1(program, function, sub_exp_1_type,
                                    generator_1_depth_prob)
    return ast.UnaryExpression(operator, sub_exp_1, exp_type, post_op=False)
예제 #7
0
def generate_local_var(program, function, c_type):
    if c_type.name not in function.local_vars.keys():
        # Creates the local vars empty list for that type
        function.local_vars[c_type.name] = []
    create_new_local_var = probs_helper.random_value(probs.new_local_var_prob)
    number_of_vars = len(function.local_vars[c_type.name])
    if not create_new_local_var and number_of_vars > 0:
        selected = probs_helper.random_value(
            probs_helper.compute_equal_prob(range(number_of_vars)))
        # An existing local variable is taken
        return ast.local_variable(c_type, selected + 1)
    # A new local variable must be created
    literal = generate_literal(program,
                               function,
                               c_type,
                               from_declaration=True)
    function.local_vars[c_type.name].append((c_type, literal))
    return ast.local_variable(c_type, len(function.local_vars[c_type.name]))
예제 #8
0
def generate_expression(program, function, exp_type, exp_depth_prob):

    # Check implicit promotion
    if probs_helper.random_value(probs.implicit_promotion_bool):
        try:
            new_type_cls = probs_helper.random_value(
                probs.promotions_prob[exp_type.__class__])
            exp_type = new_type_cls()
        except KeyError:
            pass

    exp_depth = probs_helper.random_value(exp_depth_prob
                                          or probs.exp_depth_prob)

    if exp_depth == 0:
        return generate_basic_exp(program, function, exp_type)

    lower_exp_depth_prob = probs_helper.compute_equal_prob(range(0, exp_depth))

    isCall = probs_helper.random_value(probs.call_prob)

    if not isCall:
        operators = ast.get_operators(exp_type, "normal")
        if len(operators) == 0:
            return generate_basic_exp(program, function, exp_type)

        operator, arity = probs_helper.random_value(operators)
        func_name = "generate_expression_arity_{}".format(arity)
        kwargs = {
            "default_generator_1": generate_expression,
            "generator_1_depth_prob": lower_exp_depth_prob,
            "default_generator_2": generate_expression,
            "generator_2_depth_prob": lower_exp_depth_prob,
            "default_generator_3": generate_expression,
            "generator_3_depth_prob": lower_exp_depth_prob,
        }
        return globals()[func_name](program, function, exp_type, operator,
                                    **kwargs)

    else:
        return generate_expression_invocation(program, function, exp_type,
                                              lower_exp_depth_prob)
예제 #9
0
def generate_stmt_incdec(program, function):
    stmt_type = generate_type(program,
                              function,
                              new_type_cls=None,
                              old_type_obj=None)

    # Check if operators are enabled in expressions
    operators = [k[0] for k in ast.get_operators(stmt_type, "normal").keys()]
    stmt_operators = []
    if '++' in operators:
        stmt_operators.append("++")
    if '--' in operators:
        stmt_operators.append("--")
    if not stmt_operators:
        return generate_stmt_assignment(program, function)

    # Create the statement
    operator = probs_helper.random_value(
        probs_helper.compute_equal_prob(stmt_operators))
    return generate_expression_incdec(program, function, stmt_type, operator)
예제 #10
0
def generate_expression_invocation(program, function, return_type,
                                   exp_depth_prob):
    # generates the function (if necessary)
    invoked_func = generate_function(program, function, return_type)

    # generates the arguments
    params = []
    expression_depth = probs_helper.random_value(exp_depth_prob)
    lower_exp_depth_prob = {0: 1} if exp_depth_prob == 0 \
        else probs_helper.compute_equal_prob(range(0, expression_depth + 1))
    for name, arg_type in invoked_func.param_types:
        params.append(
            generate_expression(program, function, arg_type,
                                lower_exp_depth_prob))

    # Count invocation
    program.invocation_as_expr[invoked_func.name] += 1

    # generates the invocation
    return ast.Invocation(invoked_func.name, params, return_type, False)
예제 #11
0
def generate_expression_arity_2(program, function, exp_type, operator,
                                default_generator_1, generator_1_depth_prob,
                                default_generator_2, generator_2_depth_prob,
                                **kwargs):
    # Infer types and select one pair
    types_pairs = type_inference.infer_operands_type(program, function, 2,
                                                     operator, exp_type)
    sub_exp_1_type, sub_exp_2_type = probs_helper.random_value(
        probs_helper.compute_equal_prob(types_pairs))

    # Generate the expressions
    sub_exp_1 = default_generator_1(program,
                                    function,
                                    sub_exp_1_type,
                                    exp_depth_prob=generator_1_depth_prob)
    sub_exp_2 = default_generator_2(program,
                                    function,
                                    sub_exp_2_type,
                                    exp_depth_prob=generator_2_depth_prob)
    if operator == "[]":
        return ast.ArrayAccessExpression(sub_exp_1, sub_exp_2, exp_type)
    return ast.BinaryExpression(sub_exp_1, operator, sub_exp_2, exp_type)
예제 #12
0
def _process_json_probs_entry(prob_name: str, prob_dictionary: dict, result: dict) -> None:
    """Takes one entry of the json probability specification file, process it
    and adds the correct representation to result"""
    from core import probs
    if not probs.does_this_probability_exist(prob_name):
        print(f"Unknown probability '{prob_name}'.", file=sys.stderr)  # probability name is not in probs module
    elif "__prob_distribution__" not in prob_dictionary.keys():
        # 1) fixed probability set by the user
        result[prob_name] = {_eval_str(key): content for (key, content) in prob_dictionary.items()}
    elif prob_dictionary["__prob_distribution__"] == "equal_prob":
        # 2) equal probability for a set of values
        if "__values__" not in prob_dictionary.keys():
            print(f"Equal probability distribution requires a __values__ entry.", file=sys.stderr)
        else:
            values = set()
            for value_str in prob_dictionary["__values__"]:
                values.add(_eval_str(value_str))
            result[prob_name] = probs_helper.compute_equal_prob(values)
    elif prob_dictionary["__prob_distribution__"] in ["proportional_prob", "inverse_proportional_prob"]:
        # 3) (inverse and direct) proportional probability for a set of values that do not sum 0
        if "__values__" not in prob_dictionary.keys():
            print(f"Proportional probability distribution requires a __values__ entry.", file=sys.stderr)
        else:
            # keys of the dict must be evaluated (e.g., "3" -> 3, "ast.Int" -> ast.Int)
            values_dict = {_eval_str(key): content for (key, content) in prob_dictionary["__values__"].items()}
            if prob_name == "proportional_prob":  # direct proportional
                result[prob_name] = probs_helper.compute_proportional_prob(values_dict)
            else:  # inverse proportional
                result[prob_name] = probs_helper.compute_inverse_proportional_prob(values_dict)
    elif prob_dictionary["__prob_distribution__"] == "normal_prob":
        # 5) normal probability, given a mean and standard deviation
        if not {"__mean__", "__stdev__"}.issubset(prob_dictionary.keys()):
            print(f"Normal probability distribution requires __mean__  and __stdev__ entries.", file=sys.stderr)
        else:
            result[prob_name] = probs_helper.compute_normal_prob(prob_dictionary["__mean__"],
                                                                 prob_dictionary["__stdev__"])
    else:
        print(f"Unknown probability distribution '{prob_dictionary['__prob_distribution__']}'.", file=sys.stderr)
예제 #13
0
def generate_expression_incdec(program, function, exp_type, operator):
    assert operator in ["++", "--"]
    sub_exp_1 = generate_lvalue(program, function, exp_type, None)
    post_op = probs_helper.random_value(
        probs_helper.compute_equal_prob([True, False]))
    return ast.UnaryExpression(operator, sub_exp_1, exp_type, post_op)
예제 #14
0
    ast.UnsignedShortInt,
    ast.SignedInt,
    ast.UnsignedInt,
    ast.SignedLongInt,
    ast.UnsignedLongInt,
    ast.SignedLongLongInt,
    ast.UnsignedLongLongInt,
    ast.Float,
    ast.Double,
    ast.LongDouble,
}

all_types = set(primitive_types).union({ast.Pointer, ast.Struct, ast.Array})

doc['primitive_types_prob'] = "probabilities among primitive types (default: equal probability for all the types)"
primitive_types_prob = probs_helper.compute_equal_prob(primitive_types)

doc['assignment_types_prob'] = "assignment type (default: equal probability for all the types)"
assignment_types_prob = probs_helper.compute_equal_prob(
    set(primitive_types).union({ast.Pointer, ast.Struct}))

doc['augmented_assignment_types_prob'] = "augmented assignment type (+=, -=, *=...) " \
                                         "(default: equal probability for primitive types)"
augmented_assignment_types_prob = probs_helper.compute_equal_prob(
    primitive_types)

doc['all_types_prob'] = "type probability when any type may occur in a syntax construction " \
                        "(default: equal probability for any type)"
all_types_prob = probs_helper.compute_equal_prob(all_types)

doc['array_size'] = "size of the arrays to be created (default: 1-10)"