mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
allow array size to be inferred from the initializer
This commit is contained in:
parent
dc91918c1f
commit
8ce331b563
3 changed files with 63 additions and 24 deletions
5
ast.c
5
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);
|
||||
|
|
3
ast.h
3
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
|
||||
|
|
79
parser.c
79
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[]>", 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 &&
|
||||
|
|
Loading…
Reference in a new issue