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:
parent
89aec98942
commit
159717f51c
|
@ -149,6 +149,7 @@ struct FunctionDeclaration
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
size_t arity;
|
size_t arity;
|
||||||
|
Domain domain{Domain::General};
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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 = ast::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>())
|
||||||
|
|
|
@ -49,12 +49,9 @@ struct TermDomainVisitor
|
||||||
return ast::Domain::General;
|
return ast::Domain::General;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ast::Domain visit(ast::Function &)
|
static ast::Domain visit(ast::Function &function)
|
||||||
{
|
{
|
||||||
// Functions may return values of any type
|
return function.declaration->domain;
|
||||||
|
|
||||||
// TODO: implement explicit integer specifications
|
|
||||||
return ast::Domain::General;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ast::Domain visit(ast::Integer &)
|
static ast::Domain visit(ast::Integer &)
|
||||||
|
|
Loading…
Reference in New Issue