diff options
Diffstat (limited to 'src/evaluate.c')
-rw-r--r-- | src/evaluate.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index 506c2414..19faf621 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1805,10 +1805,45 @@ static void map_set_concat_info(struct expr *map) } } +static void __mapping_expr_expand(struct expr *i) +{ + struct expr *j, *range, *next; + + assert(i->etype == EXPR_MAPPING); + switch (i->right->etype) { + case EXPR_VALUE: + range = range_expr_alloc(&i->location, expr_get(i->right), expr_get(i->right)); + expr_free(i->right); + i->right = range; + break; + case EXPR_CONCAT: + list_for_each_entry_safe(j, next, &i->right->expressions, list) { + if (j->etype != EXPR_VALUE) + continue; + + range = range_expr_alloc(&j->location, expr_get(j), expr_get(j)); + list_replace(&j->list, &range->list); + expr_free(j); + } + i->right->flags &= ~EXPR_F_SINGLETON; + break; + default: + break; + } +} + +static void mapping_expr_expand(struct expr *init) +{ + struct expr *i; + + list_for_each_entry(i, &init->expressions, list) + __mapping_expr_expand(i); +} + static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) { - struct expr_ctx ectx = ctx->ectx; struct expr *map = *expr, *mappings; + struct expr_ctx ectx = ctx->ectx; const struct datatype *dtype; struct expr *key, *data; @@ -1879,9 +1914,13 @@ static int expr_evaluate_map(struct eval_ctx *ctx, struct expr **expr) if (binop_transfer(ctx, expr) < 0) return -1; - if (ctx->set->data->flags & EXPR_F_INTERVAL) + if (ctx->set->data->flags & EXPR_F_INTERVAL) { ctx->set->data->len *= 2; + if (set_is_anonymous(ctx->set->flags)) + mapping_expr_expand(ctx->set->init); + } + ctx->set->key->len = ctx->ectx.len; ctx->set = NULL; map = *expr; @@ -1984,6 +2023,10 @@ static int expr_evaluate_mapping(struct eval_ctx *ctx, struct expr **expr) data_mapping_has_interval(mapping->right)) set->data->flags |= EXPR_F_INTERVAL; + if (!set_is_anonymous(set->flags) && + set->data->flags & EXPR_F_INTERVAL) + __mapping_expr_expand(mapping); + if (!(set->data->flags & EXPR_F_INTERVAL) && !expr_is_singleton(mapping->right)) return expr_error(ctx->msgs, mapping->right, |