From 8ce331b563e413f7d1c17bbe6bccc48657cfab90 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 12 Jun 2013 15:47:11 +0200 Subject: [PATCH] allow array size to be inferred from the initializer --- ast.c | 5 ++++ ast.h | 3 +++ parser.c | 79 +++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/ast.c b/ast.c index c1d8cb9..94b254c 100644 --- a/ast.c +++ b/ast.c @@ -1373,6 +1373,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) ast_expression *elemtype = self->expression.next; int vtype = elemtype->vtype; + if (self->expression.flags & AST_FLAG_ARRAY_INIT && !self->expression.count) { + compile_error(ast_ctx(self), "array `%s' has no size", self->name); + return false; + } + /* same as with field arrays */ if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count); diff --git a/ast.h b/ast.h index 7f56bee..1c4574a 100644 --- a/ast.h +++ b/ast.h @@ -153,6 +153,9 @@ struct ast_expression_common #define AST_FLAG_INCLUDE_DEF (1<<5) #define AST_FLAG_IS_VARARG (1<<6) #define AST_FLAG_ALIAS (1<<7) +/* An array declared as [] + * so that the size is taken from the initializer */ +#define AST_FLAG_ARRAY_INIT (1<<8) #define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN) /* Value diff --git a/parser.c b/parser.c index 6a4ae20..e6326a9 100644 --- a/parser.c +++ b/parser.c @@ -4917,32 +4917,44 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) return NULL; } - cexp = parse_expression_leave(parser, true, false, false); + if (parser->tok != ']') { + cexp = parse_expression_leave(parser, true, false, false); - if (!cexp || !ast_istype(cexp, ast_value)) { - if (cexp) - ast_unref(cexp); - ast_delete(var); - parseerror(parser, "expected array-size as constant positive integer"); - return NULL; + if (!cexp || !ast_istype(cexp, ast_value)) { + if (cexp) + ast_unref(cexp); + ast_delete(var); + parseerror(parser, "expected array-size as constant positive integer"); + return NULL; + } + cval = (ast_value*)cexp; + } + else { + cexp = NULL; + cval = NULL; } - cval = (ast_value*)cexp; tmp = ast_value_new(ctx, "", TYPE_ARRAY); tmp->expression.next = (ast_expression*)var; var = tmp; - if (cval->expression.vtype == TYPE_INTEGER) - tmp->expression.count = cval->constval.vint; - else if (cval->expression.vtype == TYPE_FLOAT) - tmp->expression.count = cval->constval.vfloat; - else { + if (cval) { + if (cval->expression.vtype == TYPE_INTEGER) + tmp->expression.count = cval->constval.vint; + else if (cval->expression.vtype == TYPE_FLOAT) + tmp->expression.count = cval->constval.vfloat; + else { + ast_unref(cexp); + ast_delete(var); + parseerror(parser, "array-size must be a positive integer constant"); + return NULL; + } + ast_unref(cexp); - ast_delete(var); - parseerror(parser, "array-size must be a positive integer constant"); - return NULL; + } else { + var->expression.count = -1; + var->expression.flags |= AST_FLAG_ARRAY_INIT; } - ast_unref(cexp); if (parser->tok != ']') { ast_delete(var); @@ -5192,6 +5204,18 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons return true; } +static bool create_array_accessors(parser_t *parser, ast_value *var) +{ + char name[1024]; + util_snprintf(name, sizeof(name), "%s##SET", var->name); + if (!parser_create_array_setter(parser, var, name)) + return false; + util_snprintf(name, sizeof(name), "%s##GET", var->name); + if (!parser_create_array_getter(parser, var, var->expression.next, name)) + return false; + return true; +} + static bool parse_array(parser_t *parser, ast_value *array) { if (!parser_next(parser)) { @@ -5226,6 +5250,16 @@ static bool parse_array(parser_t *parser, ast_value *array) return false; } */ + + if (array->expression.flags & AST_FLAG_ARRAY_INIT) { + if (array->expression.count != (size_t)-1) { + parseerror(parser, "array `%s' has already been initialized with %u elements", + array->name, (unsigned)array->expression.count); + } + array->expression.count = vec_size(array->initlist); + if (!create_array_accessors(parser, array)) + return false; + } return true; } @@ -5662,13 +5696,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield * deal with arrays */ if (var->expression.vtype == TYPE_ARRAY) { - char name[1024]; - util_snprintf(name, sizeof(name), "%s##SET", var->name); - if (!parser_create_array_setter(parser, var, name)) - goto cleanup; - util_snprintf(name, sizeof(name), "%s##GET", var->name); - if (!parser_create_array_getter(parser, var, var->expression.next, name)) - goto cleanup; + if (var->expression.count != (size_t)-1) { + if (!create_array_accessors(parser, var)) + goto cleanup; + } } else if (!localblock && !nofields && var->expression.vtype == TYPE_FIELD && -- 2.39.2