24bool python_annotation<Json>::are_all_user_classes(
25 const std::vector<std::string> &types)
const
30 for (
const auto &type_name : types)
44bool python_annotation<Json>::are_specializable_types(
45 const std::vector<std::string> &types)
const
47 if (are_all_user_classes(types))
49 bool has_int =
false, has_float =
false;
50 for (
const auto &t : types)
52 if (t !=
"int" && t !=
"float" && t !=
"str" && t !=
"bool")
54 has_int |= t ==
"int";
55 has_float |= t ==
"float";
57 return has_int && has_float;
65bool python_annotation<Json>::is_specialization_pending(
66 const std::string &func_name,
68 const std::vector<std::string> &types)
const
70 for (
const auto &spec : pending_specializations_)
72 spec.function_name == func_name &&
73 (spec.param_index == param_index || !are_all_user_classes(types)))
79std::string python_annotation<Json>::build_specialized_function_name(
80 const std::string &base_name,
81 const std::string &class_name)
const
83 return base_name +
"__esbmc_poly_" + class_name;
87std::string python_annotation<Json>::resolve_name_assigned_class(
88 const std::string &name,
97 node.contains(
"_type") && node[
"_type"] ==
"Assign" &&
98 node.contains(
"targets") && node[
"targets"].is_array() &&
99 !node[
"targets"].empty() && node[
"targets"][0].is_object() &&
100 node[
"targets"][0].contains(
"_type") &&
101 node[
"targets"][0][
"_type"] ==
"Name" &&
102 node[
"targets"][0].contains(
"id") && node[
"targets"][0][
"id"] == name &&
103 node.contains(
"value") && node[
"value"].is_object() &&
104 node[
"value"].contains(
"_type") && node[
"value"][
"_type"] ==
"Call" &&
105 node[
"value"].contains(
"func") && node[
"value"][
"func"].is_object() &&
106 node[
"value"][
"func"].contains(
"_type") &&
107 node[
"value"][
"func"][
"_type"] ==
"Name" &&
108 node[
"value"][
"func"].contains(
"id"))
110 std::string class_name =
111 node[
"value"][
"func"][
"id"].template get<std::string>();
116 for (
auto it = node.begin(); it != node.end(); ++it)
118 std::string found = resolve_name_assigned_class(name, it.value());
123 else if (node.is_array())
125 for (
const auto &element : node)
127 std::string found = resolve_name_assigned_class(name, element);
137void python_annotation<Json>::rewrite_specialized_calls(
138 const std::string &original_name,
140 const std::unordered_map<std::string, std::string> &specialized_names,
143 if (node.is_object())
146 node.contains(
"_type") && node[
"_type"] ==
"Call" &&
147 node.contains(
"func") && node[
"func"].is_object() &&
148 node[
"func"].contains(
"_type") && node[
"func"][
"_type"] ==
"Name" &&
149 node[
"func"].contains(
"id") && node[
"func"][
"id"] == original_name &&
150 node.contains(
"args") && node[
"args"].is_array() &&
151 param_index < node[
"args"].size())
153 std::string arg_type = get_argument_type(node[
"args"][param_index]);
155 arg_type.empty() && node[
"args"][param_index].contains(
"_type") &&
156 node[
"args"][param_index][
"_type"] ==
"Name" &&
157 node[
"args"][param_index].contains(
"id"))
159 const std::string arg_name =
160 node[
"args"][param_index][
"id"].template get<std::string>();
161 arg_type = resolve_name_assigned_class(arg_name, ast_[
"body"]);
164 auto it = specialized_names.find(arg_type);
165 if (it != specialized_names.end())
166 node[
"func"][
"id"] = it->second;
169 for (
auto it = node.begin(); it != node.end(); ++it)
170 rewrite_specialized_calls(
171 original_name, param_index, specialized_names, it.value());
173 else if (node.is_array())
175 for (
auto &element : node)
176 rewrite_specialized_calls(
177 original_name, param_index, specialized_names, element);
187void python_annotation<Json>::retype_builtin_copy(
189 const pending_specializationt &spec,
190 const std::string &type,
191 const std::vector<Json> &calls)
193 if (are_all_user_classes(spec.class_types))
195 const size_t param_index = spec.param_index;
196 std::vector<Json> reaching;
197 for (
const Json &call : calls)
199 param_index < call[
"args"].size() &&
200 get_argument_type(call[
"args"][param_index]) == type)
201 reaching.push_back(call);
203 Json ¶ms = fn[
"args"][
"args"];
204 for (
size_t j = 0; j < params.size(); ++j)
208 (params[j].contains(
"annotation") && !params[j][
"annotation"].is_null()))
210 const std::vector<std::string> types =
211 collect_parameter_types_from_calls(j, reaching);
212 if (types.size() > 1)
213 throw std::runtime_error(
214 "unsupported: function '" + fn[
"name"].
template get<std::string>() +
215 "' is called with differing types in more than one parameter");
216 if (types.size() == 1)
217 add_parameter_annotation(params[j], types.front());
220 fn[
"returns"].is_object() &&
221 fn[
"returns"].
value(
"_inferred_annotation",
false))
222 fn[
"returns"] =
nullptr;
226void python_annotation<Json>::apply_pending_specializations()
228 for (
const auto &spec : pending_specializations_)
230 const std::string &func_name = spec.function_name;
231 size_t param_index = spec.param_index;
233 Json original_function;
235 size_t original_index = 0;
237 for (
const auto &node : ast_[
"body"])
240 node.contains(
"_type") && node[
"_type"] ==
"FunctionDef" &&
241 node.contains(
"name") && node[
"name"] == func_name)
243 original_function = node;
245 original_index = idx;
254 const std::vector<Json> calls =
255 find_function_calls(func_name, ast_[
"body"]);
256 if (!spec.class_types.empty())
258 for (
auto &node : ast_[
"body"])
261 node.contains(
"_type") && node[
"_type"] ==
"FunctionDef" &&
262 node.contains(
"name") && node[
"name"] == func_name &&
263 node.contains(
"args") && node[
"args"].is_object() &&
264 node[
"args"].contains(
"args") && node[
"args"][
"args"].is_array() &&
265 param_index < node[
"args"][
"args"].size())
267 Json ¶m = node[
"args"][
"args"][param_index];
268 add_parameter_annotation(param, spec.class_types.front());
269 retype_builtin_copy(node, spec, spec.class_types.front(), calls);
275 std::unordered_map<std::string, std::string> specialized_names;
276 Json specialized_nodes = Json::array();
277 for (
const auto &class_name : spec.class_types)
279 Json specialized = original_function;
280 const std::string specialized_name =
281 build_specialized_function_name(func_name, class_name);
282 specialized[
"name"] = specialized_name;
285 specialized.contains(
"args") && specialized[
"args"].is_object() &&
286 specialized[
"args"].contains(
"args") &&
287 specialized[
"args"][
"args"].is_array() &&
288 param_index < specialized[
"args"][
"args"].size())
290 Json ¶m = specialized[
"args"][
"args"][param_index];
291 add_parameter_annotation(param, class_name);
292 retype_builtin_copy(specialized, spec, class_name, calls);
295 specialized_names[class_name] = specialized_name;
296 specialized_nodes.push_back(std::move(specialized));
300 ast_[
"body"].begin() +
static_cast<ptrdiff_t>(original_index + 1);
302 insert_it, specialized_nodes.begin(), specialized_nodes.end());
304 rewrite_specialized_calls(
305 func_name, param_index, specialized_names, ast_);
308 pending_specializations_.clear();
315std::vector<std::string>
316python_annotation<Json>::get_class_ancestors(
const std::string &class_name)
318 std::vector<std::string> ancestors;
319 std::unordered_set<std::string> visited;
320 std::vector<std::string> worklist = {class_name};
322 while (idx < worklist.size())
324 std::string cur = worklist[idx++];
325 if (cur.empty() || cur ==
"object" || visited.count(cur))
328 ancestors.push_back(cur);
330 if (cls.empty() || !cls.contains(
"bases"))
332 for (
const auto &
base : cls[
"bases"])
333 if (
base.contains(
"id"))
334 worklist.push_back(
base[
"id"].
template get<std::string>());
341std::string python_annotation<Json>::find_common_ancestor(
342 const std::string &type_a,
343 const std::string &type_b)
345 std::vector<std::string> ancestors_a = get_class_ancestors(type_a);
346 std::unordered_set<std::string> ancestors_b_set;
347 for (
const auto &anc : get_class_ancestors(type_b))
348 ancestors_b_set.insert(anc);
349 for (
const auto &anc : ancestors_a)
350 if (ancestors_b_set.count(anc))
static const twodig_t base
Definition bigint.cpp:28
JsonType find_class(const JsonType &ast_json, const std::string &class_name)
Definition json_utils.h:159
bool is_class(const std::string &name, const JsonType &ast_json)
Definition json_utils.h:441
void * value
Definition solidity_mapping.c:2
long int ptrdiff_t
Definition stddef.h:30