#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This file defines the probability for creating each part of the program.
Probability may be defined manually, or using the helper functions in probs_helper.
They are expressed as dictionaries: {value: probability of that value}.
The sum of the probabilities must be 1.0.
For a fixed value, just set its probability to 1.0.
The doc:Dict[str,str] documents all the probabilities meanings to be shown to the user.
"""
from core import probs_helper, ast, probs
from typing import Dict
# Name of the global dictionary used to document the probabilities
DOC_NAME = "doc"
# the doc:Dict[str,str] documents all the probabilities meanings to be shown to the user.
doc = dict()
# ------------ Types --------------
primitive_types = {
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
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)"
array_size = probs_helper.compute_equal_prob(set(range(1, 10)))
doc['reuse_struct_prob'] = "when a struct is needed, probability of using and existing one " \
"rather than creating a new one (default: 90%)"
reuse_struct_prob = {True: 0.99, False: 0.01}
doc['enhance_existing_struct_prob'] = "when a struct is needed, probability of extending an existing one with " \
"the demanded field rather than creating a new one (default: 70%)"
enhance_existing_struct_prob = {True: 0.7, False: 0.3}
doc['array_literal_initialization_prob'] = "array initialization upon definition (default: 10%)"
array_literal_initialization_prob = {True: 0.1, False: 0.9}
doc['struct_literal_initialization_prob'] = "struct initialization upon definition (default: 10%)"
struct_literal_initialization_prob = {True: 0.1, False: 0.9}
# ------------ Expressions --------------
doc['exp_depth_prob'] = "expression depth (default: equal probabilities for [0-2])"
exp_depth_prob = probs_helper.compute_equal_prob(set(range(0, 3)))
doc['return_exp_depth_prob'] = "expression depth for the particular expressions to be returned by functions " \
"(default: equal probabilities for [0-2])"
return_exp_depth_prob = probs_helper.compute_equal_prob(set(range(0, 3)))
# ------------ Functions --------------
doc['call_prob'] = "probability that a new expression is a function invocation (default: 20%)"
call_prob = {True: 0.2, False: 0.8}
doc['basic_expression_prob'] = "basic expressions (default: same probability among literal, local_var, " \
"global_var, and param_var)"
basic_expression_prob = probs_helper.compute_equal_prob({'literal', 'local_var', 'global_var', 'param_var'})
doc['param_number_prob'] = "number of parameters (default: 10% for 1, 20% for [1,4] and 5% for [5,6])"
param_number_prob = {0: 0.10, 1: 0.20, 2: 0.20, 3: 0.20, 4: 0.20, 5: 0.05, 6: 0.05}
doc['param_types_prob'] = "types of the parameters (default: all types are equally likely)"
param_types_prob = all_types_prob
# stmt_invocation_prob = {ast.FuncProc.Func: 0.2, ast.FuncProc.Proc: 0.8}
doc['stmt_invocation_prob'] = "invocation statements to functions or procedures (default: function=88%, procedure=12%)"
stmt_invocation_prob = {ast.FuncProc.Func: 0.88, ast.FuncProc.Proc: 0.12}
doc['return_types_prob'] = "function return types (default: all types are equally likely)"
return_types_prob = all_types_prob
doc['int_emulate_bool'] = "probability of generating a bool return (0 or 1) when an int type is expected " \
"(default: 20%)"
int_emulate_bool = {True: 0.2, False: 0.8}
# ------------ Variables --------------
doc['new_global_var_prob'] = "probability of creating a new global variable when one of the expected type" \
"already exists (default: 1%)"
new_global_var_prob = {True: 0.01, False: 0.99}
doc['new_local_var_prob'] = "probability of creating a new local variable when one of the expected type" \
"already exists (default: 1%)"
new_local_var_prob = {True: 0.01, False: 0.99}
doc['reuse_func_prob'] = "probability of reusing an existing function of the expected type (default: 99%)"
reuse_func_prob = {True: 0.99, False: 0.01}
doc['reuse_proc_prob'] = "probability of reusing an existing procedure of the expected type (default: 99%)"
reuse_proc_prob = {True: 0.99, False: 0.01}
doc['global_or_local_as_basic_lvalue_prob'] = "When a basic lvalue needs to be generated, this is the " \
"probability of using a global variable; otherwise, " \
"a local variable is used (default: 50%)"
global_or_local_as_basic_lvalue_prob = {True: 0.5, False: 0.5}
# ------------ Statements --------------
doc['basic_or_compound_stmt_prob'] = "probability of generating a basic (no block) or compound statement " \
"(default: basic=70%, compound=30%)"
basic_or_compound_stmt_prob = {True: 0.7, False: 0.3}
doc['function_basic_stmt_prob'] = "each kind of basic (no block) statement in functions (default: assignment=60%, " \
"invocation=20%, increment/decrement=20%, augmented assignment=10%)"
function_basic_stmt_prob = probs_helper.compute_proportional_prob({'assignment': 4, 'invocation': 4, 'incdec': 2,
'augmented_assignment': 2, 'expression_stmt': 1})
doc['function_compound_stmt_prob'] = "each kind of compound statement (with blocks) in functions " \
"(equal probability for Block, If, Switch, Do, While, For)"
function_compound_stmt_prob = probs_helper.compute_proportional_prob({'block': 1, 'while': 4, 'do': 4,
'if': 4, 'for': 4, 'switch': 4})
doc['stmt_depth_prob'] = "statement depth (default: equal probabilities for [0-2])"
stmt_depth_prob = probs_helper.compute_equal_prob(set(range(0, 3)))
doc['procedure_basic_stmt_prob'] = "each kind of basic (no block) statement in functions (default: assignment=60%, " \
"invocation=20%, increment/decrement=20%, augmented assignment=10%)"
procedure_basic_stmt_prob = function_basic_stmt_prob
doc['procedure_compound_stmt_prob'] = "each kind of compound statement (with blocks) in functions " \
"(equal probability for Block, If, Switch, Do, While, For)"
procedure_compound_stmt_prob = function_compound_stmt_prob
doc['number_stmts_main_prob'] = "number of statements in the main function " \
"(default: equal probabilities between 5 and 10)"
number_stmts_main_prob = probs_helper.compute_equal_prob(set(range(5, 11)))
doc['number_stmts_func_prob'] = "number of statements in functions " \
"(default: 20% for [1,4] and 10% for [5, 6])"
number_stmts_func_prob = {1: 0.2, 2: 0.2, 3: 0.2, 4: 0.2, 5: 0.1, 6: 0.1}
doc['number_stmts_block_prob'] = "number of statements in blocks (default: 1/3 for 1, 2 and 3)"
number_stmts_block_prob = probs_helper.compute_equal_prob({1, 2, 3})
doc['else_body_prob'] = "probability of generating an else body for an if statement " \
"(default: 50%)"
else_body_prob = {True: 0.5, False: 0.5}
doc['number_cases_prob'] = "number of cases in switch statements " \
"(default: equal probabilities between 1 and 4)"
number_cases_prob = probs_helper.compute_equal_prob(set(range(1, 5)))
doc['cases_type_prob'] = "type of the cases clauses in switch statements " \
"(default: equal probabilities between types promotable to int, excluding bool)"
cases_type_prob = probs_helper.compute_equal_prob({ast.SignedChar, ast.UnsignedChar,
ast.SignedShortInt, ast.UnsignedShortInt, ast.SignedInt, ast.UnsignedInt})
doc['default_switch_prob'] = "probability of generating a default case in a switch statement " \
"(default: 80%)"
default_switch_prob = {True: 0.8, False: 0.2}
doc['break_case_prob'] = "probability of having a break statement at the end of a case block " \
"(default: 70%)"
break_case_prob = {True: 0.7, False: 0.3}
doc['return_at_end_if_else_bodies_prob'] = "probability of having a return at the end of a if / else blocks " \
"(default: 15%)"
return_at_end_if_else_bodies_prob = {True: 0.15, False: 0.85}
doc['return_at_end_case_prob'] = "probability of having a return at the end of the cases clauses in a switch " \
"statement (default: 15%)"
return_at_end_case_prob = {True: 0.15, False: 0.85}
# ------------ Promotions --------------
doc['implicit_promotion_bool'] = "if an expression is expected, the probability to generate it with another type " \
"promotable to the expected one (default: 30%)"
implicit_promotion_bool = {True: 0.3, False: 0.7}
doc['promotions_prob'] = "promotions between types (default: all the conversions are equally likely)"
# the key of the dictionary represents the higher type (to) and the content the low type (from)
promotions_prob = {
ast.Bool: probs_helper.compute_equal_prob({
ast.Bool
}),
ast.UnsignedChar: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
}),
ast.SignedChar: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
}),
ast.UnsignedShortInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
}),
ast.SignedShortInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
}),
ast.UnsignedInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
}),
ast.SignedInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
}),
ast.UnsignedLongInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
}),
ast.SignedLongInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
}),
ast.UnsignedLongLongInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
ast.SignedLongLongInt,
ast.UnsignedLongLongInt,
}),
ast.SignedLongLongInt: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
ast.SignedLongLongInt,
ast.UnsignedLongLongInt,
}),
ast.Float: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.Float,
}),
ast.Double: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
ast.Float,
ast.Double,
}),
ast.LongDouble: probs_helper.compute_equal_prob({
ast.Bool,
ast.SignedChar,
ast.UnsignedChar,
ast.SignedShortInt,
ast.UnsignedShortInt,
ast.SignedInt,
ast.UnsignedInt,
ast.SignedLongInt,
ast.UnsignedLongInt,
ast.Float,
ast.Double,
ast.LongDouble,
}),
}
# ------------ Functions --------------
[docs]def set_probabilities(probabilities: Dict[str, dict]) -> None:
"""Modifies the global variables of this module, that is the default probabilities of Cnerator"""
if probabilities:
for (prob_name, prob_dict) in probabilities.items():
assert does_this_probability_exist(prob_name), f"The probability '{prob_name}' is not defined in probs module"
probs.__dict__[prob_name] = prob_dict
[docs]def does_this_probability_exist(probability_name: str) -> bool:
return probability_name in probs.__dict__.keys()