mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
ast: isconst->hasvalue, const keyword will set the const flag
This commit is contained in:
parent
55aa53beca
commit
6e400ca81f
3 changed files with 30 additions and 33 deletions
28
ast.c
28
ast.c
|
@ -331,7 +331,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
|
|||
self->name = name ? util_strdup(name) : NULL;
|
||||
self->expression.vtype = t;
|
||||
self->expression.next = NULL;
|
||||
self->isconst = false;
|
||||
self->hasvalue = false;
|
||||
self->uses = 0;
|
||||
memset(&self->constval, 0, sizeof(self->constval));
|
||||
|
||||
|
@ -349,7 +349,7 @@ void ast_value_delete(ast_value* self)
|
|||
{
|
||||
if (self->name)
|
||||
mem_d((void*)self->name);
|
||||
if (self->isconst) {
|
||||
if (self->hasvalue) {
|
||||
switch (self->expression.vtype)
|
||||
{
|
||||
case TYPE_STRING:
|
||||
|
@ -950,12 +950,12 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
|||
ast_instantiate(ast_function, ctx, ast_function_delete);
|
||||
|
||||
if (!vtype ||
|
||||
vtype->isconst ||
|
||||
vtype->hasvalue ||
|
||||
vtype->expression.vtype != TYPE_FUNCTION)
|
||||
{
|
||||
asterror(ast_ctx(self), "internal error: ast_function_new condition %i %i type=%i",
|
||||
(int)!vtype,
|
||||
(int)vtype->isconst,
|
||||
(int)vtype->hasvalue,
|
||||
vtype->expression.vtype);
|
||||
mem_d(self);
|
||||
return NULL;
|
||||
|
@ -974,7 +974,7 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
|||
self->breakblock = NULL;
|
||||
self->continueblock = NULL;
|
||||
|
||||
vtype->isconst = true;
|
||||
vtype->hasvalue = true;
|
||||
vtype->constval.vfunc = self;
|
||||
|
||||
return self;
|
||||
|
@ -987,7 +987,7 @@ void ast_function_delete(ast_function *self)
|
|||
mem_d((void*)self->name);
|
||||
if (self->vtype) {
|
||||
/* ast_value_delete(self->vtype); */
|
||||
self->vtype->isconst = false;
|
||||
self->vtype->hasvalue = false;
|
||||
self->vtype->constval.vfunc = NULL;
|
||||
/* We use unref - if it was stored in a global table it is supposed
|
||||
* to be deleted from *there*
|
||||
|
@ -1055,7 +1055,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
{
|
||||
ir_value *v = NULL;
|
||||
|
||||
if (self->isconst && self->expression.vtype == TYPE_FUNCTION)
|
||||
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
|
||||
{
|
||||
ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
|
||||
if (!func)
|
||||
|
@ -1072,7 +1072,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
if (isfield && self->expression.vtype == TYPE_FIELD) {
|
||||
ast_expression *fieldtype = self->expression.next;
|
||||
|
||||
if (self->isconst) {
|
||||
if (self->hasvalue) {
|
||||
asterror(ast_ctx(self), "TODO: constant field pointers with value");
|
||||
goto error;
|
||||
}
|
||||
|
@ -1195,7 +1195,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
v->context = ast_ctx(self);
|
||||
}
|
||||
|
||||
if (self->isconst) {
|
||||
if (self->hasvalue) {
|
||||
switch (self->expression.vtype)
|
||||
{
|
||||
case TYPE_FLOAT:
|
||||
|
@ -1237,7 +1237,7 @@ error: /* clean up */
|
|||
bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
|
||||
{
|
||||
ir_value *v = NULL;
|
||||
if (self->isconst && self->expression.vtype == TYPE_FUNCTION)
|
||||
if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION)
|
||||
{
|
||||
/* Do we allow local functions? I think not...
|
||||
* this is NOT a function pointer atm.
|
||||
|
@ -1308,7 +1308,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
|
|||
/* A constant local... hmmm...
|
||||
* I suppose the IR will have to deal with this
|
||||
*/
|
||||
if (self->isconst) {
|
||||
if (self->hasvalue) {
|
||||
switch (self->expression.vtype)
|
||||
{
|
||||
case TYPE_FLOAT:
|
||||
|
@ -1505,7 +1505,7 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
|
|||
ai = (ast_array_index*)self->dest;
|
||||
idx = (ast_value*)ai->index;
|
||||
|
||||
if (ast_istype(ai->index, ast_value) && idx->isconst)
|
||||
if (ast_istype(ai->index, ast_value) && idx->hasvalue)
|
||||
ai = NULL;
|
||||
}
|
||||
|
||||
|
@ -1729,7 +1729,7 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i
|
|||
ai = (ast_array_index*)self->dest;
|
||||
idx = (ast_value*)ai->index;
|
||||
|
||||
if (ast_istype(ai->index, ast_value) && idx->isconst)
|
||||
if (ast_istype(ai->index, ast_value) && idx->hasvalue)
|
||||
ai = NULL;
|
||||
}
|
||||
|
||||
|
@ -1978,7 +1978,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
|
|||
arr = (ast_value*)self->array;
|
||||
idx = (ast_value*)self->index;
|
||||
|
||||
if (!ast_istype(self->index, ast_value) || !idx->isconst) {
|
||||
if (!ast_istype(self->index, ast_value) || !idx->hasvalue) {
|
||||
/* Time to use accessor functions */
|
||||
ast_expression_codegen *cgen;
|
||||
ir_value *iridx, *funval;
|
||||
|
|
2
ast.h
2
ast.h
|
@ -155,7 +155,7 @@ struct ast_value_s
|
|||
ast_value *next;
|
||||
*/
|
||||
|
||||
bool isconst;
|
||||
bool hasvalue;
|
||||
union {
|
||||
double vfloat;
|
||||
int vint;
|
||||
|
|
33
parser.c
33
parser.c
|
@ -211,7 +211,7 @@ static ast_value* parser_const_float(parser_t *parser, double d)
|
|||
return parser->imm_float[i];
|
||||
}
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_FLOAT);
|
||||
out->isconst = true;
|
||||
out->hasvalue = true;
|
||||
out->constval.vfloat = d;
|
||||
vec_push(parser->imm_float, out);
|
||||
return out;
|
||||
|
@ -256,7 +256,7 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do
|
|||
out = ast_value_new(parser_ctx(parser), name, TYPE_STRING);
|
||||
} else
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
|
||||
out->isconst = true;
|
||||
out->hasvalue = true;
|
||||
out->constval.vstring = parser_strdup(str);
|
||||
vec_push(parser->imm_string, out);
|
||||
return out;
|
||||
|
@ -271,7 +271,7 @@ static ast_value* parser_const_vector(parser_t *parser, vector v)
|
|||
return parser->imm_vector[i];
|
||||
}
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR);
|
||||
out->isconst = true;
|
||||
out->hasvalue = true;
|
||||
out->constval.vvec = v;
|
||||
vec_push(parser->imm_vector, out);
|
||||
return out;
|
||||
|
@ -517,7 +517,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
(exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
|
||||
exprs[0]->expression.vtype != T)
|
||||
#define CanConstFold1(A) \
|
||||
(ast_istype((A), ast_value) && ((ast_value*)(A))->isconst)
|
||||
(ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue)
|
||||
#define CanConstFold(A, B) \
|
||||
(CanConstFold1(A) && CanConstFold1(B))
|
||||
#define ConstV(i) (asvalue[(i)]->constval.vvec)
|
||||
|
@ -2085,7 +2085,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
|
||||
if (!OPTS_FLAG(RELAXED_SWITCH)) {
|
||||
opval = (ast_value*)operand;
|
||||
if (!ast_istype(operand, ast_value) || !opval->isconst) {
|
||||
if (!ast_istype(operand, ast_value) || !opval->hasvalue) {
|
||||
parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
|
||||
ast_unref(operand);
|
||||
return false;
|
||||
|
@ -2478,7 +2478,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
|
|||
parseerror(parser, "expected a framenumber constant in[frame,think] notation");
|
||||
return false;
|
||||
}
|
||||
if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->isconst) {
|
||||
if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->hasvalue) {
|
||||
ast_unref(framenum);
|
||||
parseerror(parser, "framenumber in [frame,think] notation must be a constant");
|
||||
return false;
|
||||
|
@ -3611,9 +3611,6 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
|||
}
|
||||
}
|
||||
|
||||
if (is_const)
|
||||
var->isconst = true;
|
||||
|
||||
/* Part 2:
|
||||
* Create the global/local, and deal with vector types.
|
||||
*/
|
||||
|
@ -3774,7 +3771,7 @@ skipvar:
|
|||
break;
|
||||
}
|
||||
|
||||
if (var->isconst) {
|
||||
if (var->hasvalue) {
|
||||
(void)!parsewarning(parser, WARN_DOUBLE_DECLARATION,
|
||||
"builtin `%s` has already been defined\n"
|
||||
" -> previous declaration here: %s:%i",
|
||||
|
@ -3821,11 +3818,11 @@ skipvar:
|
|||
|
||||
if (!localblock) {
|
||||
cval = (ast_value*)cexp;
|
||||
if (!ast_istype(cval, ast_value) || !cval->isconst)
|
||||
if (!ast_istype(cval, ast_value) || !cval->hasvalue)
|
||||
parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
|
||||
else
|
||||
{
|
||||
var->isconst = true;
|
||||
var->hasvalue = true;
|
||||
if (cval->expression.vtype == TYPE_STRING)
|
||||
var->constval.vstring = parser_strdup(cval->constval.vstring);
|
||||
else
|
||||
|
@ -4196,21 +4193,21 @@ bool parser_finish(const char *output)
|
|||
|
||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||
ast_value *field;
|
||||
bool isconst;
|
||||
bool hasvalue;
|
||||
if (!ast_istype(parser->fields[i], ast_value))
|
||||
continue;
|
||||
field = (ast_value*)parser->fields[i];
|
||||
isconst = field->isconst;
|
||||
field->isconst = false;
|
||||
hasvalue = field->hasvalue;
|
||||
field->hasvalue = false;
|
||||
if (!ast_global_codegen((ast_value*)field, ir, true)) {
|
||||
con_out("failed to generate field %s\n", field->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
if (isconst) {
|
||||
if (hasvalue) {
|
||||
ir_value *ifld;
|
||||
ast_expression *subtype;
|
||||
field->isconst = true;
|
||||
field->hasvalue = true;
|
||||
subtype = field->expression.next;
|
||||
ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
|
||||
if (subtype->expression.vtype == TYPE_FIELD)
|
||||
|
@ -4225,7 +4222,7 @@ bool parser_finish(const char *output)
|
|||
if (!ast_istype(parser->globals[i], ast_value))
|
||||
continue;
|
||||
asvalue = (ast_value*)(parser->globals[i]);
|
||||
if (!asvalue->uses && !asvalue->isconst && asvalue->expression.vtype != TYPE_FUNCTION) {
|
||||
if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
|
||||
if (strcmp(asvalue->name, "end_sys_globals") &&
|
||||
strcmp(asvalue->name, "end_sys_fields"))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue