/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "Function.hpp"
namespace ousia {
namespace script {
/* Class ArgumentValidator */
std::pair> ArgumentValidator::setError(
int idx, const std::string &msg, std::vector &res)
{
errorIndex = idx;
errorMessage = msg;
return std::make_pair(false, res);
}
void ArgumentValidator::resetError()
{
errorIndex = -1;
errorMessage = "";
}
std::pair> ArgumentValidator::validate(
const std::vector &args)
{
std::vector res;
// Reset any old error
resetError();
// Sanity check: Do not allow too many arguments
if (args.size() > signature.size()) {
return setError(signature.size(),
"Expected " + std::to_string(signature.size()) +
" arguments but got " + std::to_string(args.size()),
res);
}
// Iterate over the given arguments and check their type
res.reserve(signature.size());
for (unsigned int i = 0; i < args.size(); i++) {
// TODO: Implicit type conversion
const VariantType tGiven = args[i].getType();
const VariantType tExpected = signature[i].type;
if (tGiven != tExpected) {
return setError(i, std::string("Expected type ") +
Variant::getTypeName(tExpected) +
" but got " + Variant::getTypeName(tGiven),
res);
}
res.push_back(args[i]);
}
// Make sure the remaining arguments have a default value, and if they have
// one, add it to the result
for (unsigned int i = args.size(); i < signature.size(); i++) {
if (!signature[i].hasDefault) {
return setError(i, "Expected argument " + std::to_string(i), res);
}
res.push_back(signature[i].defaultValue);
}
return std::make_pair(true, res);
}
/* Class ValidatingFunction */
Variant ValidatingFunction::call(const std::vector &args) const
{
if (validate) {
ArgumentValidator validator{signature};
std::pair> res = validator.validate(args);
if (!res.first) {
throw validator.error();
}
return validatedCall(res.second);
}
return validatedCall(args);
}
}
}