Skip to content

Commit 7eb2f2c

Browse files
authored
Merge pull request #4890 from MatWise/feature/stl-return-value-assignment
Statement List: Return value assignment
2 parents 14be863 + 0ad55a4 commit 7eb2f2c

File tree

6 files changed

+130
-48
lines changed

6 files changed

+130
-48
lines changed

src/statement-list/parser.y

+5-6
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ FB_Static_Decl:
431431
;
432432

433433
FB_Body:
434-
TOK_BEGIN Oom_IL_Network
434+
TOK_BEGIN Zom_IL_Network
435435
{
436436
$$ = $2;
437437
}
@@ -617,24 +617,23 @@ Constant_Decl:
617617
;
618618

619619
Func_Body:
620-
TOK_BEGIN Oom_IL_Network
620+
TOK_BEGIN Zom_IL_Network
621621
{
622622
$$ = $2;
623623
}
624624
;
625625

626626
// Network declaration
627-
Oom_IL_Network:
628-
Oom_IL_Network IL_Network
627+
Zom_IL_Network:
628+
Zom_IL_Network IL_Network
629629
{
630630
$$ = $1;
631631
parser_stack($$).add_to_operands(std::move(parser_stack($2)));
632632
}
633-
| IL_Network
633+
| /* nothing */
634634
{
635635
newstack($$);
636636
parser_stack($$).id(ID_statement_list_networks);
637-
parser_stack($$).add_to_operands(std::move(parser_stack($1)));
638637
}
639638
;
640639

src/statement-list/scanner.l

+1-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ void statement_list_scanner_init()
259259
return TOK_REAL_LITERAL;
260260
}
261261

262-
(\"[^\"\r\t\n]+\")|([a-zA-Z][a-zA-Z0-9]*) {
262+
(\"[^\"\r\t\n]+\")|([a-zA-Z][a-zA-Z0-9_]*) {
263263
newstack(yystatement_listlval);
264264
parser_stack(yystatement_listlval) =
265265
convert_identifier(yytext);

src/statement-list/statement_list_parser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static typet find_return_value(const exprt &root)
8181
for(const exprt &op : root.operands())
8282
{
8383
if(op.get(ID_statement_list_type) == ID_statement_list_return)
84-
return typet(op.id());
84+
return op.type();
8585
}
8686

8787
UNREACHABLE; // Root expression of FC should always have a return value

src/statement-list/statement_list_typecheck.cpp

+95-33
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ void statement_list_typecheckt::typecheck()
100100
parse_tree.function_blocks)
101101
{
102102
symbolt &fb_sym{symbol_table.get_writeable_ref(fb.name)};
103-
typecheck_statement_list_networks(fb.networks, fb_sym);
103+
typecheck_statement_list_networks(fb, fb_sym);
104104
}
105105
for(const statement_list_parse_treet::functiont &fc : parse_tree.functions)
106106
{
107107
symbolt &function_sym{symbol_table.get_writeable_ref(fc.name)};
108-
typecheck_statement_list_networks(fc.networks, function_sym);
108+
typecheck_statement_list_networks(fc, function_sym);
109109
}
110110
}
111111

@@ -149,14 +149,12 @@ void statement_list_typecheckt::typecheck_function_block_declaration(
149149
param_sym.mode = STATEMENT_LIST_MODE;
150150
symbol_table.add(param_sym);
151151

152-
// Setup FB symbol type and value and add it to the symbol table.
152+
// Setup FB symbol type and value.
153153
code_typet::parameterst params;
154154
params.push_back(param);
155155
code_typet fb_type{params, empty_typet()};
156156
fb_type.set(ID_statement_list_type, ID_statement_list_function_block);
157157
function_block_sym.type = fb_type;
158-
function_block_sym.value = code_blockt{};
159-
typecheck_temp_var_decls(function_block, function_block_sym);
160158
symbol_table.add(function_block_sym);
161159
}
162160

@@ -170,17 +168,16 @@ void statement_list_typecheckt::typecheck_function_declaration(
170168
function_sym.pretty_name = function_sym.name;
171169
function_sym.mode = STATEMENT_LIST_MODE;
172170
code_typet::parameterst params;
173-
typecheck_function_var_decls(function.var_input, params, function.name);
174-
typecheck_function_var_decls(function.var_inout, params, function.name);
175-
typecheck_function_var_decls(function.var_output, params, function.name);
171+
typecheck_function_var_decls(
172+
function.var_input, params, function.name, ID_statement_list_var_input);
173+
typecheck_function_var_decls(
174+
function.var_inout, params, function.name, ID_statement_list_var_inout);
175+
typecheck_function_var_decls(
176+
function.var_output, params, function.name, ID_statement_list_var_output);
176177

177178
code_typet fc_type{params, function.return_type};
178179
fc_type.set(ID_statement_list_type, ID_statement_list_function);
179180
function_sym.type = fc_type;
180-
function_sym.value = code_blockt{};
181-
182-
typecheck_temp_var_decls(function, function_sym);
183-
184181
symbol_table.add(function_sym);
185182
}
186183

@@ -204,32 +201,39 @@ struct_typet statement_list_typecheckt::create_instance_data_block_type(
204201
const statement_list_parse_treet::function_blockt &function_block)
205202
{
206203
struct_union_typet::componentst components;
207-
typecheck_function_block_var_decls(function_block.var_input, components);
208-
typecheck_function_block_var_decls(function_block.var_inout, components);
209-
typecheck_function_block_var_decls(function_block.var_output, components);
210-
typecheck_function_block_var_decls(function_block.var_static, components);
204+
typecheck_function_block_var_decls(
205+
function_block.var_input, components, ID_statement_list_var_input);
206+
typecheck_function_block_var_decls(
207+
function_block.var_inout, components, ID_statement_list_var_inout);
208+
typecheck_function_block_var_decls(
209+
function_block.var_output, components, ID_statement_list_var_output);
210+
typecheck_function_block_var_decls(
211+
function_block.var_static, components, ID_statement_list_var_static);
211212

212213
return struct_typet{components};
213214
}
214215

215216
void statement_list_typecheckt::typecheck_function_block_var_decls(
216217
const statement_list_parse_treet::var_declarationst &var_decls,
217-
struct_union_typet::componentst &components)
218+
struct_union_typet::componentst &components,
219+
const irep_idt &var_property)
218220
{
219221
for(const statement_list_parse_treet::var_declarationt &declaration :
220222
var_decls)
221223
{
222224
const irep_idt &var_name{declaration.variable.get_identifier()};
223225
const typet &var_type{declaration.variable.type()};
224226
struct_union_typet::componentt component{var_name, var_type};
227+
component.set(ID_statement_list_type, var_property);
225228
components.push_back(component);
226229
}
227230
}
228231

229232
void statement_list_typecheckt::typecheck_function_var_decls(
230233
const statement_list_parse_treet::var_declarationst &var_decls,
231234
code_typet::parameterst &params,
232-
const irep_idt &function_name)
235+
const irep_idt &function_name,
236+
const irep_idt &var_property)
233237
{
234238
for(const statement_list_parse_treet::var_declarationt &declaration :
235239
var_decls)
@@ -247,6 +251,7 @@ void statement_list_typecheckt::typecheck_function_var_decls(
247251
code_typet::parametert param{declaration.variable.type()};
248252
param.set_identifier(param_sym.name);
249253
param.set_base_name(declaration.variable.get_identifier());
254+
param.set(ID_statement_list_type, var_property);
250255
params.push_back(param);
251256
}
252257
}
@@ -274,15 +279,23 @@ void statement_list_typecheckt::typecheck_temp_var_decls(
274279
}
275280

276281
void statement_list_typecheckt::typecheck_statement_list_networks(
277-
const statement_list_parse_treet::networkst &networks,
278-
symbolt &tia_element)
282+
const statement_list_parse_treet::tia_modulet &tia_module,
283+
symbolt &tia_symbol)
279284
{
280-
for(const auto &network : networks)
285+
// Leave value empty if there are no networks to iterate through.
286+
if(tia_module.networks.empty())
287+
return;
288+
if(tia_symbol.value.is_nil())
289+
tia_symbol.value = code_blockt{};
290+
291+
typecheck_temp_var_decls(tia_module, tia_symbol);
292+
293+
for(const auto &network : tia_module.networks)
281294
{
282295
// Set RLO to true each time a new network is entered (TIA behaviour).
283296
rlo_bit = true_exprt();
284297
for(const auto &instruction : network.instructions)
285-
typecheck_statement_list_instruction(instruction, tia_element);
298+
typecheck_statement_list_instruction(instruction, tia_symbol);
286299
}
287300
}
288301

@@ -1249,9 +1262,10 @@ void statement_list_typecheckt::typecheck_called_function(
12491262
symbolt &tia_element)
12501263
{
12511264
const symbol_exprt call_operand{to_symbol_expr(op_code.op0())};
1252-
const symbolt &called_function{
1265+
const symbolt &called_function_sym{
12531266
symbol_table.lookup_ref(call_operand.get_identifier())};
1254-
const code_typet &called_type{to_code_type(called_function.type)};
1267+
const symbol_exprt called_function_expr{called_function_sym.symbol_expr()};
1268+
const code_typet &called_type{to_code_type(called_function_sym.type)};
12551269

12561270
// Check if function name is followed by data block.
12571271
if(!can_cast_expr<equal_exprt>(op_code.op1()))
@@ -1275,11 +1289,22 @@ void statement_list_typecheckt::typecheck_called_function(
12751289

12761290
for(const code_typet::parametert &param : params)
12771291
{
1278-
const exprt &arg{typecheck_function_call_arguments(assignments, param)};
1292+
const exprt &arg{
1293+
typecheck_function_call_arguments(assignments, param, tia_element)};
12791294
args.push_back(arg);
12801295
}
1281-
const code_function_callt call{call_operand, args};
1282-
tia_element.value.add_to_operands(call);
1296+
1297+
// Check the return value if present.
1298+
if(called_type.return_type().is_nil())
1299+
tia_element.value.add_to_operands(
1300+
code_function_callt{called_function_expr, args});
1301+
else
1302+
{
1303+
const exprt lhs{typecheck_return_value_assignment(
1304+
assignments, called_type.return_type(), tia_element)};
1305+
tia_element.value.add_to_operands(
1306+
code_function_callt{lhs, called_function_expr, args});
1307+
}
12831308
}
12841309

12851310
void statement_list_typecheckt::typecheck_called_function_block(
@@ -1296,23 +1321,60 @@ void statement_list_typecheckt::typecheck_called_function_block(
12961321

12971322
exprt statement_list_typecheckt::typecheck_function_call_arguments(
12981323
const std::vector<equal_exprt> &assignments,
1299-
const code_typet::parametert &param)
1324+
const code_typet::parametert &param,
1325+
const symbolt &tia_element)
1326+
{
1327+
const irep_idt &param_name = param.get_base_name();
1328+
const typet &param_type = param.type();
1329+
for(const equal_exprt &assignment : assignments)
1330+
{
1331+
const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1332+
if(param_name == lhs.get_identifier())
1333+
{
1334+
const symbol_exprt &rhs{to_symbol_expr(assignment.rhs())};
1335+
const exprt assigned_variable{
1336+
typecheck_identifier(tia_element, rhs.get_identifier())};
1337+
if(param_type == assigned_variable.type())
1338+
return assigned_variable;
1339+
else
1340+
{
1341+
error() << "Types of parameter assignment do not match: "
1342+
<< param.type().id() << " != " << assigned_variable.type().id()
1343+
<< eom;
1344+
throw TYPECHECK_ERROR;
1345+
}
1346+
}
1347+
}
1348+
error() << "No assignment found for function parameter "
1349+
<< param.get_identifier() << eom;
1350+
throw TYPECHECK_ERROR;
1351+
}
1352+
1353+
exprt statement_list_typecheckt::typecheck_return_value_assignment(
1354+
const std::vector<equal_exprt> &assignments,
1355+
const typet &return_type,
1356+
const symbolt &tia_element)
13001357
{
13011358
for(const equal_exprt &assignment : assignments)
13021359
{
13031360
const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1304-
if(param.get_identifier() == lhs.get_identifier())
1361+
if(ID_statement_list_return_value_id == lhs.get_identifier())
13051362
{
1306-
if(param.type() == assignment.rhs().type())
1307-
return assignment.rhs();
1363+
const symbol_exprt &rhs{to_symbol_expr(assignment.rhs())};
1364+
const exprt assigned_variable{
1365+
typecheck_identifier(tia_element, rhs.get_identifier())};
1366+
if(return_type == assigned_variable.type())
1367+
return assigned_variable;
13081368
else
13091369
{
1310-
error() << "Types of parameter assignment do not match" << eom;
1370+
error() << "Types of return value assignment do not match: "
1371+
<< return_type.id() << " != " << assigned_variable.type().id()
1372+
<< eom;
13111373
throw TYPECHECK_ERROR;
13121374
}
13131375
}
13141376
}
1315-
error() << "No assignment found for function parameter" << eom;
1377+
error() << "No assignment found for function return value" << eom;
13161378
throw TYPECHECK_ERROR;
13171379
}
13181380

src/statement-list/statement_list_typecheck.h

+27-7
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,26 @@ class statement_list_typecheckt : public typecheckt
143143
/// to the given component element.
144144
/// \param var_decls: List of declarations which should be typechecked.
145145
/// \param [out] components: List of typechecked and converted declarations.
146+
/// \param var_property: Type of variable declaration list (for example
147+
/// input, output, ...).
146148
void typecheck_function_block_var_decls(
147149
const statement_list_parse_treet::var_declarationst &var_decls,
148-
struct_union_typet::componentst &components);
150+
struct_union_typet::componentst &components,
151+
const irep_idt &var_property);
149152

150153
/// Performs a typecheck on a variable declaration list and saves the result
151154
/// to the given component element.
152155
/// \param var_decls: List of declarations which should be typechecked.
153156
/// \param [out] params: List of typechecked and converted declarations.
154157
/// \param function_name: Function to which the variable list belongs (used
155158
/// for naming).
159+
/// \param var_property: Type of variable declaration list (for example
160+
/// input, output, ...).
156161
void typecheck_function_var_decls(
157162
const statement_list_parse_treet::var_declarationst &var_decls,
158163
code_typet::parameterst &params,
159-
const irep_idt &function_name);
164+
const irep_idt &function_name,
165+
const irep_idt &var_property);
160166

161167
/// Performs a typecheck on the temp variables of a TIA module and saves the
162168
/// result to the given symbol value.
@@ -168,11 +174,11 @@ class statement_list_typecheckt : public typecheckt
168174

169175
/// Performs a typecheck on the networks of a TIA module and saves the
170176
/// result to the given symbol.
171-
/// \param networks: Network list that should be checked.
172-
/// \param [out] tia_element: Symbol representation of the TIA module.
177+
/// \param tia_module: Module containing the networks that shall be checked.
178+
/// \param [out] tia_symbol: Symbol representation of the given TIA module.
173179
void typecheck_statement_list_networks(
174-
const statement_list_parse_treet::networkst &networks,
175-
symbolt &tia_element);
180+
const statement_list_parse_treet::tia_modulet &tia_module,
181+
symbolt &tia_symbol);
176182

177183
/// Performs a typecheck on a single instruction and saves the result to the
178184
/// given symbol body if necessary.
@@ -534,10 +540,24 @@ class statement_list_typecheckt : public typecheckt
534540
/// function call and returns the expression of the assigned variable.
535541
/// \param assignments: Assignment list of the function call.
536542
/// \param param: Parameter that should be checked.
543+
/// \param tia_element: Symbol representation of the TIA element.
537544
/// \return: Expression including the assigned symbol's name and type.
538545
exprt typecheck_function_call_arguments(
539546
const std::vector<equal_exprt> &assignments,
540-
const code_typet::parametert &param);
547+
const code_typet::parametert &param,
548+
const symbolt &tia_element);
549+
550+
/// Checks if there is a return value assignment inside of the assignment
551+
/// list of a function call and returns the expression of the assigned
552+
/// variable.
553+
/// \param assignments: Assignment list of the function call.
554+
/// \param return_type: Type of the return value.
555+
/// \param tia_element: Symbol representation of the TIA element.
556+
/// \return: Expression including the assigned symbol's name and type.
557+
exprt typecheck_return_value_assignment(
558+
const std::vector<equal_exprt> &assignments,
559+
const typet &return_type,
560+
const symbolt &tia_element);
541561

542562
// Helper functions
543563

src/util/irep_ids.def

+1
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ IREP_ID_ONE(statement_list_var_constant)
774774
IREP_ID_ONE(statement_list_var_temp)
775775
IREP_ID_ONE(statement_list_var_static)
776776
IREP_ID_ONE(statement_list_return)
777+
IREP_ID_TWO(statement_list_return_value_id, Ret_Val)
777778
IREP_ID_ONE(statement_list_var_entry)
778779
IREP_ID_ONE(statement_list_var_decls)
779780
IREP_ID_ONE(statement_list_network)

0 commit comments

Comments
 (0)