msg_disable ();
if ((*node)->type == OP_format
&& fmt_check_input (&(*node)->format.f)
- && fmt_check_type_compat (&(*node)->format.f, NUMERIC))
+ && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC))
{
msg_enable ();
if (do_coercion)
msg_disable ();
if ((*node)->type == OP_format
&& fmt_check_output (&(*node)->format.f)
- && fmt_check_type_compat (&(*node)->format.f, NUMERIC))
+ && fmt_check_type_compat (&(*node)->format.f, VAR_NUMERIC))
{
msg_enable ();
if (do_coercion)
}
break;
+ case OP_var:
+ if ((*node)->type == OP_NUM_VAR || (*node)->type == OP_STR_VAR)
+ {
+ if (do_coercion)
+ *node = (*node)->composite.args[0];
+ return true;
+ }
+ break;
+
case OP_pos_int:
if ((*node)->type == OP_number
&& floor ((*node)->number.n) == (*node)->number.n
(union any_node **) node, NULL, false);
}
+/* Returns true if ACTUAL_TYPE is a kind of REQUIRED_TYPE, false
+ otherwise. */
+static bool
+is_compatible (atom_type required_type, atom_type actual_type)
+{
+ return (required_type == actual_type
+ || (required_type == OP_var
+ && (actual_type == OP_num_var || actual_type == OP_str_var)));
+}
+
/* How to parse an operator. */
struct operator
{
assert (o->arg_cnt == arg_cnt);
assert ((o->flags & OPF_ARRAY_OPERAND) == 0);
for (i = 0; i < arg_cnt; i++)
- assert (o->args[i] == arg_type);
+ assert (is_compatible (arg_type, o->args[i]));
return true;
}
|| !lex_match (lexer, ')'))
return NULL;
- return expr_allocate_binary (e, (vector->var[0]->type == NUMERIC
+ return expr_allocate_binary (e, (vector_get_type (vector) == VAR_NUMERIC
? OP_VEC_ELEM_NUM : OP_VEC_ELEM_STR),
element, expr_allocate_vector (e, vector));
}
}
static int
-compare_names (const char *test, const char *name)
+compare_names (const char *test, const char *name, bool abbrev_ok)
{
+ if (!abbrev_ok)
+ return true;
+
for (;;)
{
if (!word_matches (&test, &name))
}
static int
-compare_strings (const char *test, const char *name)
+compare_strings (const char *test, const char *name, bool abbrev_ok UNUSED)
{
return strcasecmp (test, name);
}
static bool
lookup_function_helper (const char *name,
- int (*compare) (const char *test, const char *name),
+ int (*compare) (const char *test, const char *name,
+ bool abbrev_ok),
const struct operation **first,
const struct operation **last)
{
for (f = operations + OP_function_first;
f <= operations + OP_function_last; f++)
- if (!compare (name, f->name))
+ if (!compare (name, f->name, !(f->flags & OPF_NO_ABBREV)))
{
*first = f;
- while (f <= operations + OP_function_last && !compare (name, f->name))
+ while (f <= operations + OP_function_last
+ && !compare (name, f->name, !(f->flags & OPF_NO_ABBREV)))
f++;
*last = f;
assert (is_composite (n->type));
assert (c->arg_cnt >= op->arg_cnt);
for (i = 0; i < op->arg_cnt; i++)
- assert (expr_node_returns (c->args[i]) == op->args[i]);
+ assert (is_compatible (op->args[i], expr_node_returns (c->args[i])));
if (c->arg_cnt > op->arg_cnt && !is_operator (n->type))
{
assert (op->flags & OPF_ARRAY_OPERAND);
for (i = 0; i < c->arg_cnt; i++)
- assert (operations[c->args[i]->type].returns
- == op->args[op->arg_cnt - 1]);
+ assert (is_compatible (op->args[op->arg_cnt - 1],
+ expr_node_returns (c->args[i])));
}
}
expr_allocate_variable (struct expression *e, struct variable *v)
{
union any_node *n = pool_alloc (e->expr_pool, sizeof n->variable);
- n->type = v->type == NUMERIC ? OP_num_var : OP_str_var;
+ n->type = var_is_numeric (v) ? OP_num_var : OP_str_var;
n->variable.v = v;
return n;
}
allocate_unary_variable (struct expression *e, struct variable *v)
{
assert (v != NULL);
- return expr_allocate_unary (e, v->type == NUMERIC ? OP_NUM_VAR : OP_STR_VAR,
+ return expr_allocate_unary (e, var_is_numeric (v) ? OP_NUM_VAR : OP_STR_VAR,
expr_allocate_variable (e, v));
}