static void
no_match (struct expression *e, const char *func_name, struct expr_node *node,
- const struct operation *first, const struct operation *last)
+ const struct operation *ops, size_t n)
{
struct string s;
- const struct operation *f;
ds_init_empty (&s);
- if (last - first == 1)
+ if (n == 1)
{
- ds_put_format (&s, _("Type mismatch invoking %s as "), first->prototype);
+ ds_put_format (&s, _("Type mismatch invoking %s as "), ops->prototype);
put_invocation (&s, func_name, node);
}
else
put_invocation (&s, func_name, node);
ds_put_cstr (&s, _(" does not match any known function. Candidates are:"));
- for (f = first; f < last; f++)
- ds_put_format (&s, "\n%s", f->prototype);
+ for (size_t i = 0; i < n; i++)
+ ds_put_format (&s, "\n%s", ops[i].prototype);
}
ds_put_byte (&s, '.');
msg_at (SE, expr_location (e, node), "%s", ds_cstr (&s));
+ if (n == 1 && ops->n_args == node->n_args)
+ {
+ for (size_t i = 0; i < ops->n_args; i++)
+ if ((ops->args[i] == OP_ni_format
+ || ops->args[i] == OP_no_format)
+ && expr_node_returns (node->args[i]) == OP_format)
+ {
+ const struct fmt_spec *f = &node->args[i]->format;
+ char *error = fmt_check__ (f, (ops->args[i] == OP_ni_format
+ ? FMT_FOR_INPUT : FMT_FOR_OUTPUT));
+ if (!error)
+ error = fmt_check_type_compat__ (f, VAL_NUMERIC);
+ if (error)
+ {
+ msg_at (SN, expr_location (e, node->args[i]), "%s", error);
+ free (error);
+ }
+ }
+ }
+
ds_destroy (&s);
}
const struct operation *f = match_function (n, first, last);
if (!f)
{
- no_match (e, ds_cstr (&func_name), n, first, last);
+ no_match (e, ds_cstr (&func_name), n, first, last - first);
goto fail;
}
n->type = f - operations;