|
ESBMC
Efficient SMT-based Context-Bounded Model Checker
|
#include <dynamic_type_handler.h>
Classes | |
| class | scope_guard |
| RAII: adds dynamic_type_names to the transient tagged-name set for the duration of converting one if/else's branches; removes on exit only what it added, keeping nested invocations independent. More... | |
Public Member Functions | |
| dynamic_type_handler (python_converter &converter, type_handler &type_handler) | |
| std::unordered_set< std::string > | detect_dynamic_type_names (const nlohmann::json &if_node) const |
| Names assigned genuinely incompatible literal types across every branch of if_node, following nested if/else (including elif) on either side; a name must be assigned in every branch to qualify. | |
| void | declare_dynamic_type_names (const std::unordered_set< std::string > &dynamic_type_names, const nlohmann::json &ast_node) |
| Declares (or aliases) each name's tagged-object symbol before either branch converts, so goto-symex's struct-merge resolves the join for free. | |
| bool | is_tagged (const std::string &name) const |
| True if name currently resolves to a tagged-object symbol, either because it is one of the current if/else's dynamic-type names, or because an earlier branch join already flagged it. | |
| std::string | tagged_symbol_id (const std::string &name) const |
| The id of the symbol that currently holds name's tagged object, following the alias created for a pre-existing variable. | |
| symbol_id | bound_symbol_id (const std::string &name) const |
| The id of the symbol name binds in the scope being converted: a variable, or class C's own attribute v for a name C.v. | |
| bool | tagged_binop_result_may_be_tagged (const std::string &op) const |
| True if op on two tagged operands can produce either scalar type at runtime (only '+' today); an untagged assignment target then needs to become tagged too. | |
| void | assign (const exprt &rhs, const locationt &location, const std::string &name, codet &target_block) |
| Fills in the tagged-object fields for name from an already-converted value. | |
| void | resolve_read (symbolt *&symbol) const |
| Redirects symbol to its tagged-object alias, if a pre-existing variable was aliased for it; no-op otherwise. | |
| exprt | handle_comparison (const std::string &op, const exprt &lhs, const exprt &rhs) |
| Dispatches Eq/NotEq/Lt/LtE/Gt/GtE between a tagged-scalar operand and the other side. | |
| exprt | handle_arithmetic (const std::string &op, const exprt &lhs, const exprt &rhs, const locationt &location) |
| Dispatches Add/Sub/Div between a tagged-scalar operand and a literal. | |
| void | guard_type_error (const std::string &op, const exprt &lhs, const exprt &rhs, const locationt &location) |
| Inside a try body, raises a catchable TypeError ahead of an Add/Sub/Div or ordered comparison on the path where the operands' runtime types do not support it. | |
| exprt | build_neg_tagged (const exprt &tagged, const locationt &location) |
| Builds unary minus on a tagged-scalar operand, as 0 - tagged, after guard_type_error for that subtraction. | |
| exprt | build_isinstance_check (const exprt &tagged, const std::string &type_name, bool type_is_user_class) const |
| Builds isinstance(tagged, type_name). | |
| exprt | build_truthiness (const exprt &tagged) |
| Python truthiness of a tagged value, decided by its runtime type. | |
| bool | detect_dynamic_return_type (const nlohmann::json &function_node) const |
| True if a function's top-level if/elif/else chain – including an early return with no else, falling through to the next statement – can return genuinely incompatible kinds (num vs str) of literals or scalar-annotated parameters. | |
| bool | parameter_call_returns_tagged (const nlohmann::json &call) const |
| call goes through a parameter of the current function, and every call of that function passes a def returning a dynamic value (#9030). | |
| bool | scope_assigns_divergent_literal_types (const std::string &name, const nlohmann::json &scope_body, const nlohmann::json &module_body=nlohmann::json()) const |
| True if some top-level If in scope_body (a function body or the module body) assigns name genuinely incompatible literal kinds across every branch. | |
| exprt | build_tagged_value (const exprt &value, const locationt &location, codet &target_block) |
| Builds a tagged-object temporary from an already-converted value, for use as either a RETURN value or a function-call ARGUMENT. | |
| exprt | build_numeric_conversion (const exprt &tagged, const typet &result_type, const locationt &location) |
int(tagged) or float(tagged), as result_type says: a str is parsed at runtime and raises ValueError when it does not parse, a number converts by value | |
| void | refuse_float_tag_operation (const exprt &lhs, const exprt &rhs) const |
| Throws when a tag may hold a float and lhs op rhs is not a str operation. | |
| void | refuse_tagged_argument () const |
| Throws the shared "tagged argument, no known parameter type" refusal. | |
| void | assign_tagged_object (const exprt &rhs, const locationt &location, const std::string &name, codet &target_block) |
| Whole-struct copy: fills name's tagged-object symbol from a value that is already tagged-object-typed. | |
| dynamic_type_handler::dynamic_type_handler | ( | python_converter & | converter, |
| type_handler & | type_handler ) |
| void dynamic_type_handler::assign | ( | const exprt & | rhs, |
| const locationt & | location, | ||
| const std::string & | name, | ||
| codet & | target_block ) |
Fills in the tagged-object fields for name from an already-converted value.
| void dynamic_type_handler::assign_tagged_object | ( | const exprt & | rhs, |
| const locationt & | location, | ||
| const std::string & | name, | ||
| codet & | target_block ) |
Whole-struct copy: fills name's tagged-object symbol from a value that is already tagged-object-typed.
| symbol_id dynamic_type_handler::bound_symbol_id | ( | const std::string & | name | ) | const |
The id of the symbol name binds in the scope being converted: a variable, or class C's own attribute v for a name C.v.
| exprt dynamic_type_handler::build_isinstance_check | ( | const exprt & | tagged, |
| const std::string & | type_name, | ||
| bool | type_is_user_class ) const |
Builds isinstance(tagged, type_name).
type_is_user_class says whether type_name names a class defined in the program, which a tag can never hold
Builds unary minus on a tagged-scalar operand, as 0 - tagged, after guard_type_error for that subtraction.
| exprt dynamic_type_handler::build_numeric_conversion | ( | const exprt & | tagged, |
| const typet & | result_type, | ||
| const locationt & | location ) |
int(tagged) or float(tagged), as result_type says: a str is parsed at runtime and raises ValueError when it does not parse, a number converts by value
| exprt dynamic_type_handler::build_tagged_value | ( | const exprt & | value, |
| const locationt & | location, | ||
| codet & | target_block ) |
Builds a tagged-object temporary from an already-converted value, for use as either a RETURN value or a function-call ARGUMENT.
Python truthiness of a tagged value, decided by its runtime type.
| void dynamic_type_handler::declare_dynamic_type_names | ( | const std::unordered_set< std::string > & | dynamic_type_names, |
| const nlohmann::json & | ast_node ) |
Declares (or aliases) each name's tagged-object symbol before either branch converts, so goto-symex's struct-merge resolves the join for free.
| bool dynamic_type_handler::detect_dynamic_return_type | ( | const nlohmann::json & | function_node | ) | const |
True if a function's top-level if/elif/else chain – including an early return with no else, falling through to the next statement – can return genuinely incompatible kinds (num vs str) of literals or scalar-annotated parameters.
| std::unordered_set< std::string > dynamic_type_handler::detect_dynamic_type_names | ( | const nlohmann::json & | if_node | ) | const |
Names assigned genuinely incompatible literal types across every branch of if_node, following nested if/else (including elif) on either side; a name must be assigned in every branch to qualify.
The value a name holds before the if counts as one more branch, and a name C.v stands for class C's own attribute v
| void dynamic_type_handler::guard_type_error | ( | const std::string & | op, |
| const exprt & | lhs, | ||
| const exprt & | rhs, | ||
| const locationt & | location ) |
Inside a try body, raises a catchable TypeError ahead of an Add/Sub/Div or ordered comparison on the path where the operands' runtime types do not support it.
Elsewhere the scalar helper's assert reports it.
| exprt dynamic_type_handler::handle_arithmetic | ( | const std::string & | op, |
| const exprt & | lhs, | ||
| const exprt & | rhs, | ||
| const locationt & | location ) |
Dispatches Add/Sub/Div between a tagged-scalar operand and a literal.
| exprt dynamic_type_handler::handle_comparison | ( | const std::string & | op, |
| const exprt & | lhs, | ||
| const exprt & | rhs ) |
Dispatches Eq/NotEq/Lt/LtE/Gt/GtE between a tagged-scalar operand and the other side.
| bool dynamic_type_handler::is_tagged | ( | const std::string & | name | ) | const |
True if name currently resolves to a tagged-object symbol, either because it is one of the current if/else's dynamic-type names, or because an earlier branch join already flagged it.
| bool dynamic_type_handler::parameter_call_returns_tagged | ( | const nlohmann::json & | call | ) | const |
call goes through a parameter of the current function, and every call of that function passes a def returning a dynamic value (#9030).
| void dynamic_type_handler::refuse_float_tag_operation | ( | const exprt & | lhs, |
| const exprt & | rhs ) const |
Throws when a tag may hold a float and lhs op rhs is not a str operation.
| void dynamic_type_handler::refuse_tagged_argument | ( | ) | const |
Throws the shared "tagged argument, no known parameter type" refusal.
| void dynamic_type_handler::resolve_read | ( | symbolt *& | symbol | ) | const |
Redirects symbol to its tagged-object alias, if a pre-existing variable was aliased for it; no-op otherwise.
| bool dynamic_type_handler::scope_assigns_divergent_literal_types | ( | const std::string & | name, |
| const nlohmann::json & | scope_body, | ||
| const nlohmann::json & | module_body = nlohmann::json() ) const |
True if some top-level If in scope_body (a function body or the module body) assigns name genuinely incompatible literal kinds across every branch.
| bool dynamic_type_handler::tagged_binop_result_may_be_tagged | ( | const std::string & | op | ) | const |
True if op on two tagged operands can produce either scalar type at runtime (only '+' today); an untagged assignment target then needs to become tagged too.
| std::string dynamic_type_handler::tagged_symbol_id | ( | const std::string & | name | ) | const |
The id of the symbol that currently holds name's tagged object, following the alias created for a pre-existing variable.