Support declaring functions as integer

This adds a new syntax for declaring functions integer:

    #external integer(<function name>(<arity)).

If a function is declared integer, it may enable some variables to be
detected as integer as well.
This commit is contained in:
Patrick Lühne 2018-04-19 16:11:05 +02:00
parent 43d2c153c7
commit 09ef64a0e1
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
2 changed files with 43 additions and 1 deletions

View File

@ -148,6 +148,7 @@ struct FunctionDeclaration
std::string name; std::string name;
size_t arity; size_t arity;
Domain domain{Domain::Noninteger};
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -190,7 +190,7 @@ struct StatementVisitor
const auto fail = const auto fail =
[&]() [&]()
{ {
throw LogicException(statement.location, "only #external declarations of the form “#external <predicate name>(<arity>). supported"); throw LogicException(statement.location, "only #external declarations of the form “#external <predicate name>(<arity>). or #external integer(<function name>(<arity>)). supported");
}; };
if (!external.body.empty()) if (!external.body.empty())
@ -204,6 +204,47 @@ struct StatementVisitor
if (predicate.arguments.size() != 1) if (predicate.arguments.size() != 1)
fail(); fail();
const auto handleIntegerDeclaration =
[&]()
{
// Integer function declarations are treated separately if applicable
if (strcmp(predicate.name, "integer") != 0)
return false;
if (predicate.arguments.size() != 1)
return false;
const auto &functionArgument = predicate.arguments.front();
if (!functionArgument.data.is<Clingo::AST::Function>())
return false;
const auto &function = functionArgument.data.get<Clingo::AST::Function>();
if (function.arguments.size() != 1)
return false;
const auto &arityArgument = function.arguments.front();
if (!arityArgument.data.is<Clingo::Symbol>())
return false;
const auto &aritySymbol = arityArgument.data.get<Clingo::Symbol>();
if (aritySymbol.type() != Clingo::SymbolType::Number)
return false;
const size_t arity = aritySymbol.number();
auto functionDeclaration = context.findOrCreateFunctionDeclaration(function.name, arity);
functionDeclaration->domain = Domain::Integer;
return true;
};
if (handleIntegerDeclaration())
return;
const auto &arityArgument = predicate.arguments.front(); const auto &arityArgument = predicate.arguments.front();
if (!arityArgument.data.is<Clingo::Symbol>()) if (!arityArgument.data.is<Clingo::Symbol>())