CBMC
Loading...
Searching...
No Matches
json_goto_function.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: JSON goto_function deserialization
4
5Author: Michael Tautschnig
6
7\*******************************************************************/
8
11
12#include "json_goto_function.h"
13
15#include <util/expr.h>
16#include <util/json_irep.h>
17#include <util/string2int.h>
18
19#include "json_symbol.h"
20
25{
26 auto code_it = json.find("code");
27 if(code_it == json.end())
29 "instruction_from_json: key 'code' not found"};
30
32 irept code_irep = json2irep.convert_from_json(code_it->second);
33 return static_cast<goto_instruction_codet &>(code_irep);
34}
35
42{
44 if(code.get_statement() != code_id)
45 {
47 "instruction_from_json: expected '" + id2string(code_id) + "', got '" +
48 id2string(code.get_statement()) + "'"};
49 }
50 return code;
51}
52
57{
58 auto guard_it = json.find("guard");
59 if(guard_it == json.end())
61 "instruction_from_json: key 'guard' not found"};
62
64 irept guard_irep = json2irep.convert_from_json(guard_it->second);
65 return static_cast<exprt &>(guard_irep);
66}
67
73{
74 auto id_it = json.find("instructionId");
75 if(id_it == json.end())
76 {
78 "instruction_from_json: key 'instructionId' not found"};
79 }
80 auto instruction_type = try_get_string(id_it->second, "instructionId");
81
82 source_locationt source_location = source_locationt::nil();
83 auto location_it = json.find("sourceLocation");
84 if(location_it != json.end())
85 source_location = try_get_source_location(location_it->second);
86
87 if(instruction_type == "GOTO")
88 {
90 try_get_guard(json), source_location);
91 }
92 else if(instruction_type == "ASSUME")
93 {
94 return goto_programt::make_assumption(try_get_guard(json), source_location);
95 }
96 else if(instruction_type == "ASSERT")
97 {
98 return goto_programt::make_assertion(try_get_guard(json), source_location);
99 }
100 else if(instruction_type == "OTHER")
101 {
102 return goto_programt::make_other(try_get_code(json), source_location);
103 }
104 else if(instruction_type == "SKIP")
105 {
106 return goto_programt::make_skip(source_location);
107 }
108 else if(instruction_type == "START_THREAD")
109 {
111 static_cast<const goto_instruction_codet &>(get_nil_irep()),
112 source_location,
114 nil_exprt{},
115 {}};
116 }
117 else if(instruction_type == "END_THREAD")
118 {
120 static_cast<const goto_instruction_codet &>(get_nil_irep()),
121 source_location,
123 nil_exprt{},
124 {}};
125 }
126 else if(instruction_type == "LOCATION")
127 {
128 return goto_programt::make_location(source_location);
129 }
130 else if(instruction_type == "END_FUNCTION")
131 {
132 return goto_programt::make_end_function(source_location);
133 }
134 else if(instruction_type == "ATOMIC_BEGIN")
135 {
136 return goto_programt::make_atomic_begin(source_location);
137 }
138 else if(instruction_type == "ATOMIC_END")
139 {
140 return goto_programt::make_atomic_end(source_location);
141 }
142 else if(instruction_type == "SET_RETURN_VALUE")
143 {
145 to_code_return(try_get_code(json, ID_return)).return_value(),
146 source_location);
147 }
148 else if(instruction_type == "ASSIGN")
149 {
151 to_code_assign(try_get_code(json, ID_assign)), source_location);
152 }
153 else if(instruction_type == "DECL")
154 {
156 to_code_decl(try_get_code(json, ID_decl)), source_location);
157 }
158 else if(instruction_type == "DEAD")
159 {
162 source_location,
163 DEAD,
164 nil_exprt{},
165 {}};
166 }
167 else if(instruction_type == "FUNCTION_CALL")
168 {
171 source_location);
172 }
173 else if(instruction_type == "THROW")
174 {
175 return goto_programt::make_throw(source_location);
176 }
177 else if(instruction_type == "CATCH")
178 {
179 return goto_programt::make_catch(source_location);
180 }
181 else
182 {
184 "instruction_from_json: got unexpected instructionId '" +
185 instruction_type + "'"};
186 }
187}
188
193{
194 if(!json.is_array())
195 throw deserialization_exceptiont{"goto_program_from_json takes an array"};
196
197 goto_programt program;
198
199 // First pass: create all instructions
200 std::map<unsigned, goto_programt::targett> target_map;
201 for(const auto &instruction_json : to_json_array(json))
202 {
203 if(!instruction_json.is_object())
204 throw deserialization_exceptiont{"instruction_from_json takes an object"};
205
207 auto location_number_it = json_object.find("locationNumber");
208 std::optional<unsigned> loc_unsigned;
209 if(
211 location_number_it->second.is_number())
212 {
214 }
215 if(!loc_unsigned.has_value())
216 {
218 "goto_program_from_json: key 'locationNumber' not found or does not "
219 "map to an unsigned number"};
220 }
221
223 auto new_key =
224 target_map.insert({*loc_unsigned, std::prev(program.instructions.end())})
225 .second;
226 if(!new_key)
227 {
229 "goto_program_from_json: duplicate locationNumber " +
230 location_number_it->second.value};
231 }
232 }
233
234 // Second pass: resolve targets
236 for(const auto &instruction_json : to_json_array(json))
237 {
238 for(const auto &kv : to_json_object(instruction_json))
239 {
240 if(
241 kv.first == "code" || kv.first == "guard" ||
242 kv.first == "instruction" || kv.first == "instructionId" ||
243 kv.first == "locationNumber" || kv.first == "sourceLocation")
244 {
245 continue;
246 }
247 else if(kv.first == "labels")
248 {
249 if(!kv.second.is_array())
250 throw deserialization_exceptiont{"labels must be an array"};
251
252 for(const auto &label : to_json_array(kv.second))
253 {
254 if(!label.is_string())
255 throw deserialization_exceptiont{"label must be a string"};
256 instruction_it->labels.push_back(label.value);
257 }
258 }
259 else if(kv.first == "targets")
260 {
261 if(!kv.second.is_array())
262 throw deserialization_exceptiont{"targets must be an array"};
263
264 for(const auto &target : to_json_array(kv.second))
265 {
266 std::optional<unsigned> target_unsigned =
267 string2optional_unsigned(target.value);
268 if(!target.is_number() || !target_unsigned.has_value())
270 "target must be an unsigned number"};
271 auto target_it = target_map.find(*target_unsigned);
272 if(target_it == target_map.end())
273 throw deserialization_exceptiont{"target not in function"};
274 instruction_it->targets.push_back(target_it->second);
275 }
276
277 if(
278 !instruction_it->is_incomplete_goto() ||
279 instruction_it->targets.empty())
280 {
282 "goto_program_from_json: invalid targets entry"};
283 }
284 goto_programt::targett target = instruction_it->targets.back();
285 instruction_it->targets.pop_back();
286 instruction_it->complete_goto(target);
287 }
288 else
289 {
291 "goto_program_from_json: unexpected key '" + kv.first + "'"};
292 }
293 }
294
296 }
297
298 return program;
299}
300
302{
303 goto_functiont result;
304
305 for(const auto &kv : json)
306 {
307 if(kv.first == "instructions")
308 {
309 result.body = goto_program_from_json(kv.second);
310 }
311 else if(kv.first == "parameterIdentifiers")
312 {
313 if(!kv.second.is_array())
314 {
316 "parameterIdentifiers must be an array"};
317 }
318
319 for(const auto &param : to_json_array(kv.second))
320 {
321 if(!param.is_string())
322 {
324 "parameter identifier must be a string"};
325 }
326 result.parameter_identifiers.push_back(param.value);
327 }
328 }
329 else if(kv.first == "isHidden")
330 {
331 if(try_get_bool(kv.second, "isHidden"))
332 result.make_hidden();
333 }
334 else if(kv.first == "name")
335 {
336 // ignored, already processed by goto_functions_from_json
337 }
338 else if(kv.first == "isBodyAvailable" || kv.first == "isInternal")
339 {
340 // ignored, computed at runtime
341 }
342 else
343 {
345 "goto_function_from_json: unexpected key '" + kv.first + "'"};
346 }
347 }
348
349 return result;
350}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Data structure for representing an arbitrary statement in a program.
const irep_idt & get_statement() const
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
goto_programt body
parameter_identifierst parameter_identifiers
The identifiers of the parameters of this function.
This class represents an instruction in the GOTO intermediate representation.
A generic container class for the GOTO intermediate representation of one function.
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
instructionst instructions
The list of instructions in the goto program.
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
instructionst::iterator targett
static instructiont make_atomic_end(const source_locationt &l=source_locationt::nil())
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
static instructiont make_throw(const source_locationt &l=source_locationt::nil())
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
static instructiont make_catch(const source_locationt &l=source_locationt::nil())
static instructiont make_atomic_begin(const source_locationt &l=source_locationt::nil())
static instructiont make_location(const source_locationt &l)
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
Definition json.h:27
The NIL expression.
Definition std_expr.h:3209
static const source_locationt & nil()
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
const code_deadt & to_code_dead(const goto_instruction_codet &code)
const code_assignt & to_code_assign(const goto_instruction_codet &code)
const code_declt & to_code_decl(const goto_instruction_codet &code)
const code_returnt & to_code_return(const goto_instruction_codet &code)
@ DEAD
@ END_THREAD
@ START_THREAD
const irept & get_nil_irep()
Definition irep.cpp:19
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
json_objectt & to_json_object(jsont &json)
Definition json.h:442
json_arrayt & to_json_array(jsont &json)
Definition json.h:424
static goto_instruction_codet try_get_code(const json_objectt &json)
Return code at "code" key in a JSON object, if any.
goto_functiont goto_function_from_json(const json_objectt &json)
Deserialize a goto_functiont from JSON.
static exprt try_get_guard(const json_objectt &json)
Return expression at "guard" key in a JSON object, if any.
static goto_programt goto_program_from_json(const jsont &json)
Deserialize a goto_programt from JSON.
static goto_programt::instructiont instruction_from_json(const json_objectt &json)
Deserialize a goto_programt::instructiont from JSON.
JSON goto_function deserialization.
bool try_get_bool(const jsont &in, const std::string &key)
Return boolean value for a given key if present in the json object.
source_locationt try_get_source_location(const jsont &json)
Return a source_locationt from the given JSON object.
const std::string & try_get_string(const jsont &in, const std::string &key)
Return string value for a given key if present in the json object.
static void json(json_objectT &result, const irep_idt &property_id, const property_infot &property_info)
std::optional< unsigned > string2optional_unsigned(const std::string &str, int base)
Convert string to unsigned similar to the stoul or stoull functions, return nullopt when the conversi...