Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/utap/document.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ class Document
Document& operator=(Document&&) noexcept = default;

/// Returns the global declarations of the document.
const Declarations& get_globals() const { return global; }
Declarations& get_globals() { return global; }

/// Returns the templates of the document.
Expand Down
18 changes: 11 additions & 7 deletions src/ExpressionBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@

#include "utap/TypeChecker.hpp"

#include <cinttypes>
#include <cmath>
#include <sstream>
#include <string>
#include <vector>

#include <cassert>
#include <cinttypes>
#include <cmath>

namespace UTAP {

Expand Down Expand Up @@ -319,15 +319,19 @@ void ExpressionBuilder::expr_call_end(uint32_t n)
switch (id.get_type().get_kind()) {
case Kind::FUNCTION_EXTERNAL:
case Kind::FUNCTION:
if (expr.size() != id.get_type().size())
handle_error(TypeException{"$Wrong_number_of_arguments"});
if (expr.size() < id.get_type().size())
handle_error(TypeException{"$Too_few_arguments_for_function_call"});
if (expr.size() > id.get_type().size())
handle_error(TypeException{"$Too_many_arguments_for_function_call"});
e = Expression::create_nary(id.get_type().get_kind() == Kind::FUNCTION ? Kind::FUN_CALL : Kind::FUN_CALL_EXT, expr, position,
id.get_type()[0]);
break;

case Kind::PROCESS_SET:
if (expr.size() - 1 != id.get_type().size())
handle_error(TypeException{"$Wrong_number_of_arguments"});
if (expr.size() - 1 < id.get_type().size())
handle_error(TypeException{"$Too_few_arguments_for_template_instantiation"});
if (expr.size() - 1 > id.get_type().size())
handle_error(TypeException{"$Too_many_arguments_for_template_instantiation"});
instance = static_cast<const Instance*>(id.get_symbol().get_data());

/* Process set lookups are represented as expressions indexing
Expand Down Expand Up @@ -1073,4 +1077,4 @@ void ExpressionBuilder::pop_dynamic_frame_of(std::string_view name)
dynamicFrames.erase(it);
}

} // namespace UTAP
} // namespace UTAP
24 changes: 15 additions & 9 deletions src/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ Error incompatible_arguments_to_inline_if(const Expression& expr)

Error incompatible_type_for_comma(const Expression& expr) { return {expr, "$Incompatible_type_for_comma_expression"}; }

Error too_few_function_arguments(const Expression& expr) { return {expr, "$Too_few_function_arguments"}; }

Error channel_expected(const Expression& expr) { return {expr, "$Channel_expected"}; }

Error clock_expected(const Expression& expr) { return {expr, "$Clock_expected"}; }
Expand Down Expand Up @@ -1001,7 +1003,7 @@ void TypeChecker::visit_variable(Variable& variable)
else if (variable.init.changes_any_variable())
handleError(must_be_side_effect_free(variable.init));
else
checkInitialiser(variable.uid.get_type(), variable.init);
variable.init = checkInitialiser(variable.uid.get_type(), variable.init);
}
}

Expand Down Expand Up @@ -1645,7 +1647,7 @@ Expression TypeChecker::checkInitialiser(const Type& type, const Expression& ini
for (uint32_t i = 0; i < init.get_type().size(); i++) {
if (!init.get_type().get_label(i).empty())
handleError(field_name_not_allowed_in_array_init(init[i]));
checkInitialiser(subtype, init[i]);
result[i] = checkInitialiser(subtype, init[i]);
}
return Expression::create_nary(Kind::LIST, result, init.get_position(), type);
} else if (type.is_record() && init.get_kind() == Kind::LIST) {
Expand Down Expand Up @@ -2204,12 +2206,16 @@ bool TypeChecker::checkExpression(Expression& expr)
checkExpression(expr[0]);

bool result = true;
const Type& t = expr[0].get_type();
const uint32_t parameters = t.size() - 1;
for (uint32_t i = 0; i < parameters; i++) {
const Type& parameter = t[i + 1];
const Expression& argument = expr[i + 1];
result &= checkParameterCompatible(parameter, argument);
const Type& fn_type = expr[0].get_type(); // [ret_type, arg1_type, ..., argn_type]
const uint32_t param_count = fn_type.size() - 1;
for (uint32_t i = 1; i <= param_count; ++i) {
if (i >= expr.get_size()) {
handleError(too_few_function_arguments(expr));
return false;
}
const Type& param_type = fn_type[i];
const Expression& argument = expr[i];
result &= checkParameterCompatible(param_type, argument);
}
return result;
}
Expand Down Expand Up @@ -2865,4 +2871,4 @@ bool TypeChecker::checkAggregationOp(const Expression& expr)
return true;
}

} // namespace UTAP
} // namespace UTAP
49 changes: 49 additions & 0 deletions test/models/function_calls.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.6//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_6.dtd'>
<nta>
<declaration>int v;

bool enabled(int i) {
return (i&gt;0);
}
</declaration>
<template>
<name x="5" y="5">P</name>
<location id="id0" x="136" y="0">
<name x="126" y="-34">Done</name>
</location>
<location id="id1" x="0" y="0">
<urgent/>
</location>
<init ref="id1"/>
<transition id="id2">
<source ref="id1"/>
<target ref="id0"/>
<label kind="guard" x="25" y="-25">enabled(1)</label>
<label kind="assignment" x="25" y="0">v=1</label>
</transition>
</template>
<system>system P;</system>
<queries>
<query>
<formula>simulate[&lt;=5;3] { v, enabled(1) } : 2 : enabled(1)</formula>
<comment>Good call, should pass</comment>
</query>
<query>
<formula>simulate[&lt;=5;3] { v, enabled(1) } : 2 : enabled()</formula>
<comment>Call is missing argument, should give meaningful error and not crash.</comment>
</query>
<query>
<formula>simulate[&lt;=5;3] { v, enabled() } : 2 : enabled(1)</formula>
<comment>Call is missing argument, should give meaningful error and not crash.</comment>
</query>
<query>
<formula>simulate[&lt;=5;3] { v, enabled() } : 2 : enabled()</formula>
<comment>Both calls are missing arguments, should give error message and not crash</comment>
</query>
<query>
<formula>simulate[&lt;=5;3] { v, non_existent() } : 2 : non_existent()</formula>
<comment>Chould give meaningfull error message and not crash</comment>
</query>
</queries>
</nta>
Loading
Loading