]> git.xonotic.org Git - xonotic/gmqcc.git/blob - parser.c
Change the parser to use the hashtable functions
[xonotic/gmqcc.git] / parser.c
1 /*
2  * Copyright (C) 2012
3  *     Wolfgang Bumiller
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #include <stdio.h>
24 #include <stdarg.h>
25
26 #include "gmqcc.h"
27 #include "lexer.h"
28
29 #define PARSER_HT_FIELDS  0
30 #define PARSER_HT_GLOBALS 1
31 /* beginning of locals */
32 #define PARSER_HT_LOCALS  2
33
34 #define PARSER_HT_SIZE    1024
35
36 typedef struct {
37     lex_file *lex;
38     int      tok;
39
40     ast_expression **globals;
41     ast_expression **fields;
42     ast_function **functions;
43     ast_value    **imm_float;
44     ast_value    **imm_string;
45     ast_value    **imm_vector;
46
47     /* must be deleted first, they reference immediates and values */
48     ast_value    **accessors;
49
50     ast_value *imm_float_zero;
51     ast_value *imm_float_one;
52     ast_value *imm_vector_zero;
53
54     size_t crc_globals;
55     size_t crc_fields;
56
57     ast_function *function;
58
59     /* A list of hashtables for each scope */
60     ht *variables;
61     ht htfields;
62     ht htglobals;
63
64     /* not to be used directly, we use the hash table */
65     ast_expression **_locals;
66     size_t          *_blocklocals;
67
68     size_t errors;
69
70     /* we store the '=' operator info */
71     const oper_info *assign_op;
72
73     /* TYPE_FIELD -> parser_find_fields is used instead of find_var
74      * TODO: TYPE_VECTOR -> x, y and z are accepted in the gmqcc standard
75      * anything else: type error
76      */
77     qcint  memberof;
78 } parser_t;
79
80 static void parser_enterblock(parser_t *parser);
81 static bool parser_leaveblock(parser_t *parser);
82 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
83 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, bool is_const);
84 static ast_block* parse_block(parser_t *parser, bool warnreturn);
85 static bool parse_block_into(parser_t *parser, ast_block *block, bool warnreturn);
86 static ast_expression* parse_statement_or_block(parser_t *parser);
87 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
88 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma);
89 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma);
90
91 static void parseerror(parser_t *parser, const char *fmt, ...)
92 {
93         va_list ap;
94
95         parser->errors++;
96
97         va_start(ap, fmt);
98     con_vprintmsg(LVL_ERROR, parser->lex->tok.ctx.file, parser->lex->tok.ctx.line, "parse error", fmt, ap);
99         va_end(ap);
100 }
101
102 /* returns true if it counts as an error */
103 static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
104 {
105         va_list ap;
106         int lvl = LVL_WARNING;
107
108     if (!OPTS_WARN(warntype))
109         return false;
110
111     if (opts_werror) {
112             parser->errors++;
113             lvl = LVL_ERROR;
114         }
115
116         va_start(ap, fmt);
117     con_vprintmsg(lvl, parser->lex->tok.ctx.file, parser->lex->tok.ctx.line, "warning", fmt, ap);
118         va_end(ap);
119
120         return opts_werror;
121 }
122
123 static bool GMQCC_WARN genwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
124 {
125         va_list ap;
126         int lvl = LVL_WARNING;
127
128     if (!OPTS_WARN(warntype))
129         return false;
130
131     if (opts_werror)
132             lvl = LVL_ERROR;
133
134         va_start(ap, fmt);
135     con_vprintmsg(lvl, ctx.file, ctx.line, "warning", fmt, ap);
136         va_end(ap);
137
138         return opts_werror;
139 }
140
141 /**********************************************************************
142  * some maths used for constant folding
143  */
144
145 vector vec3_add(vector a, vector b)
146 {
147     vector out;
148     out.x = a.x + b.x;
149     out.y = a.y + b.y;
150     out.z = a.z + b.z;
151     return out;
152 }
153
154 vector vec3_sub(vector a, vector b)
155 {
156     vector out;
157     out.x = a.x - b.x;
158     out.y = a.y - b.y;
159     out.z = a.z - b.z;
160     return out;
161 }
162
163 qcfloat vec3_mulvv(vector a, vector b)
164 {
165     return (a.x * b.x + a.y * b.y + a.z * b.z);
166 }
167
168 vector vec3_mulvf(vector a, float b)
169 {
170     vector out;
171     out.x = a.x * b;
172     out.y = a.y * b;
173     out.z = a.z * b;
174     return out;
175 }
176
177 /**********************************************************************
178  * parsing
179  */
180
181 bool parser_next(parser_t *parser)
182 {
183     /* lex_do kills the previous token */
184     parser->tok = lex_do(parser->lex);
185     if (parser->tok == TOKEN_EOF)
186         return true;
187     if (parser->tok >= TOKEN_ERROR) {
188         parseerror(parser, "lex error");
189         return false;
190     }
191     return true;
192 }
193
194 #define parser_tokval(p) ((p)->lex->tok.value)
195 #define parser_token(p)  (&((p)->lex->tok))
196 #define parser_ctx(p)    ((p)->lex->tok.ctx)
197
198 static ast_value* parser_const_float(parser_t *parser, double d)
199 {
200     size_t i;
201     ast_value *out;
202     for (i = 0; i < vec_size(parser->imm_float); ++i) {
203         const double compare = parser->imm_float[i]->constval.vfloat;
204         if (memcmp((const void*)&compare, (const void *)&d, sizeof(double)) == 0)
205             return parser->imm_float[i];
206     }
207     out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_FLOAT);
208     out->isconst = true;
209     out->constval.vfloat = d;
210     vec_push(parser->imm_float, out);
211     return out;
212 }
213
214 static ast_value* parser_const_float_0(parser_t *parser)
215 {
216     if (!parser->imm_float_zero)
217         parser->imm_float_zero = parser_const_float(parser, 0);
218     return parser->imm_float_zero;
219 }
220
221 static ast_value* parser_const_float_1(parser_t *parser)
222 {
223     if (!parser->imm_float_one)
224         parser->imm_float_one = parser_const_float(parser, 1);
225     return parser->imm_float_one;
226 }
227
228 static char *parser_strdup(const char *str)
229 {
230     if (str && !*str) {
231         /* actually dup empty strings */
232         char *out = mem_a(1);
233         *out = 0;
234         return out;
235     }
236     return util_strdup(str);
237 }
238
239 static ast_value* parser_const_string(parser_t *parser, const char *str)
240 {
241     size_t i;
242     ast_value *out;
243     for (i = 0; i < vec_size(parser->imm_string); ++i) {
244         if (!strcmp(parser->imm_string[i]->constval.vstring, str))
245             return parser->imm_string[i];
246     }
247     out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
248     out->isconst = true;
249     out->constval.vstring = parser_strdup(str);
250     vec_push(parser->imm_string, out);
251     return out;
252 }
253
254 static ast_value* parser_const_vector(parser_t *parser, vector v)
255 {
256     size_t i;
257     ast_value *out;
258     for (i = 0; i < vec_size(parser->imm_vector); ++i) {
259         if (!memcmp(&parser->imm_vector[i]->constval.vvec, &v, sizeof(v)))
260             return parser->imm_vector[i];
261     }
262     out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR);
263     out->isconst = true;
264     out->constval.vvec = v;
265     vec_push(parser->imm_vector, out);
266     return out;
267 }
268
269 static ast_value* parser_const_vector_f(parser_t *parser, float x, float y, float z)
270 {
271     vector v;
272     v.x = x;
273     v.y = y;
274     v.z = z;
275     return parser_const_vector(parser, v);
276 }
277
278 static ast_value* parser_const_vector_0(parser_t *parser)
279 {
280     if (!parser->imm_vector_zero)
281         parser->imm_vector_zero = parser_const_vector_f(parser, 0, 0, 0);
282     return parser->imm_vector_zero;
283 }
284
285 static ast_expression* parser_find_field(parser_t *parser, const char *name)
286 {
287     return util_htget(parser->htfields, name);
288 }
289
290 static ast_expression* parser_find_global(parser_t *parser, const char *name)
291 {
292     return util_htget(parser->htglobals, name);
293 }
294
295 static ast_expression* parser_find_param(parser_t *parser, const char *name)
296 {
297     size_t i;
298     ast_value *fun;
299     if (!parser->function)
300         return NULL;
301     fun = parser->function->vtype;
302     for (i = 0; i < vec_size(fun->expression.params); ++i) {
303         if (!strcmp(fun->expression.params[i]->name, name))
304             return (ast_expression*)(fun->expression.params[i]);
305     }
306     return NULL;
307 }
308
309 static ast_expression* parser_find_local(parser_t *parser, const char *name, size_t upto, bool *isparam)
310 {
311     size_t          i, hash;
312     ast_expression *e;
313
314     hash = util_hthash(parser->htglobals, name);
315
316     *isparam = false;
317     for (i = vec_size(parser->variables); i > upto;) {
318         --i;
319         if ( (e = util_htgeth(parser->variables[i], name, hash)) )
320             return e;
321     }
322     *isparam = true;
323     return parser_find_param(parser, name);
324 }
325
326 static ast_expression* parser_find_var(parser_t *parser, const char *name)
327 {
328     bool dummy;
329     ast_expression *v;
330     v         = parser_find_local(parser, name, 0, &dummy);
331     if (!v) v = parser_find_global(parser, name);
332     return v;
333 }
334
335 typedef struct
336 {
337     size_t etype; /* 0 = expression, others are operators */
338     int             paren;
339     size_t          off;
340     ast_expression *out;
341     ast_block      *block; /* for commas and function calls */
342     lex_ctx ctx;
343 } sy_elem;
344 typedef struct
345 {
346     sy_elem *out;
347     sy_elem *ops;
348 } shunt;
349
350 #define SY_PAREN_EXPR '('
351 #define SY_PAREN_FUNC 'f'
352 #define SY_PAREN_INDEX '['
353
354 static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
355     sy_elem e;
356     e.etype = 0;
357     e.off   = 0;
358     e.out   = v;
359     e.block = NULL;
360     e.ctx   = ctx;
361     e.paren = 0;
362     return e;
363 }
364
365 static sy_elem syblock(lex_ctx ctx, ast_block *v) {
366     sy_elem e;
367     e.etype = 0;
368     e.off   = 0;
369     e.out   = (ast_expression*)v;
370     e.block = v;
371     e.ctx   = ctx;
372     e.paren = 0;
373     return e;
374 }
375
376 static sy_elem syop(lex_ctx ctx, const oper_info *op) {
377     sy_elem e;
378     e.etype = 1 + (op - operators);
379     e.off   = 0;
380     e.out   = NULL;
381     e.block = NULL;
382     e.ctx   = ctx;
383     e.paren = 0;
384     return e;
385 }
386
387 static sy_elem syparen(lex_ctx ctx, int p, size_t off) {
388     sy_elem e;
389     e.etype = 0;
390     e.off   = off;
391     e.out   = NULL;
392     e.block = NULL;
393     e.ctx   = ctx;
394     e.paren = p;
395     return e;
396 }
397
398 #ifdef DEBUGSHUNT
399 # define DEBUGSHUNTDO(x) x
400 #else
401 # define DEBUGSHUNTDO(x)
402 #endif
403
404 /* With regular precedence rules, ent.foo[n] is the same as (ent.foo)[n],
405  * so we need to rotate it to become ent.(foo[n]).
406  */
407 static bool rotate_entfield_array_index_nodes(ast_expression **out)
408 {
409     ast_array_index *index;
410     ast_entfield    *entfield;
411
412     ast_value       *field;
413     ast_expression  *sub;
414     ast_expression  *entity;
415
416     lex_ctx ctx = ast_ctx(*out);
417
418     if (!ast_istype(*out, ast_array_index))
419         return false;
420     index = (ast_array_index*)*out;
421
422     if (!ast_istype(index->array, ast_entfield))
423         return false;
424     entfield = (ast_entfield*)index->array;
425
426     if (!ast_istype(entfield->field, ast_value))
427         return false;
428     field = (ast_value*)entfield->field;
429
430     sub    = index->index;
431     entity = entfield->entity;
432
433     ast_delete(index);
434
435     index = ast_array_index_new(ctx, (ast_expression*)field, sub);
436     entfield = ast_entfield_new(ctx, entity, (ast_expression*)index);
437     *out = (ast_expression*)entfield;
438
439     return true;
440 }
441
442 static bool parser_sy_pop(parser_t *parser, shunt *sy)
443 {
444     const oper_info *op;
445     lex_ctx ctx;
446     ast_expression *out = NULL;
447     ast_expression *exprs[3];
448     ast_block      *blocks[3];
449     ast_value      *asvalue[3];
450     size_t i, assignop, addop, subop;
451     qcint  generated_op = 0;
452
453     char ty1[1024];
454     char ty2[1024];
455
456     if (!vec_size(sy->ops)) {
457         parseerror(parser, "internal error: missing operator");
458         return false;
459     }
460
461     if (vec_last(sy->ops).paren) {
462         parseerror(parser, "unmatched parenthesis");
463         return false;
464     }
465
466     op = &operators[vec_last(sy->ops).etype - 1];
467     ctx = vec_last(sy->ops).ctx;
468
469     DEBUGSHUNTDO(con_out("apply %s\n", op->op));
470
471     if (vec_size(sy->out) < op->operands) {
472         parseerror(parser, "internal error: not enough operands: %i (operator %s (%i))", vec_size(sy->out),
473                    op->op, (int)op->id);
474         return false;
475     }
476
477     vec_shrinkby(sy->ops, 1);
478
479     vec_shrinkby(sy->out, op->operands);
480     for (i = 0; i < op->operands; ++i) {
481         exprs[i]  = sy->out[vec_size(sy->out)+i].out;
482         blocks[i] = sy->out[vec_size(sy->out)+i].block;
483         asvalue[i] = (ast_value*)exprs[i];
484     }
485
486     if (blocks[0] && !vec_size(blocks[0]->exprs) && op->id != opid1(',')) {
487         parseerror(parser, "internal error: operator cannot be applied on empty blocks");
488         return false;
489     }
490
491 #define NotSameType(T) \
492              (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
493               exprs[0]->expression.vtype != T)
494 #define CanConstFold1(A) \
495              (ast_istype((A), ast_value) && ((ast_value*)(A))->isconst)
496 #define CanConstFold(A, B) \
497              (CanConstFold1(A) && CanConstFold1(B))
498 #define ConstV(i) (asvalue[(i)]->constval.vvec)
499 #define ConstF(i) (asvalue[(i)]->constval.vfloat)
500 #define ConstS(i) (asvalue[(i)]->constval.vstring)
501     switch (op->id)
502     {
503         default:
504             parseerror(parser, "internal error: unhandled operator: %s (%i)", op->op, (int)op->id);
505             return false;
506
507         case opid1('.'):
508             if (exprs[0]->expression.vtype == TYPE_ENTITY) {
509                 if (exprs[1]->expression.vtype != TYPE_FIELD) {
510                     parseerror(parser, "type error: right hand of member-operand should be an entity-field");
511                     return false;
512                 }
513                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
514             }
515             else if (exprs[0]->expression.vtype == TYPE_VECTOR) {
516                 parseerror(parser, "internal error: vector access is not supposed to be handled at this point");
517                 return false;
518             }
519             else {
520                 parseerror(parser, "type error: member-of operator on something that is not an entity or vector");
521                 return false;
522             }
523             break;
524
525         case opid1('['):
526             if (exprs[0]->expression.vtype != TYPE_ARRAY &&
527                 !(exprs[0]->expression.vtype == TYPE_FIELD &&
528                   exprs[0]->expression.next->expression.vtype == TYPE_ARRAY))
529             {
530                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
531                 parseerror(parser, "cannot index value of type %s", ty1);
532                 return false;
533             }
534             if (exprs[1]->expression.vtype != TYPE_FLOAT) {
535                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
536                 parseerror(parser, "index must be of type float, not %s", ty1);
537                 return false;
538             }
539             out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
540             if (rotate_entfield_array_index_nodes(&out))
541             {
542                 if (opts_standard != COMPILER_GMQCC) {
543                     /* this error doesn't need to make us bail out */
544                     (void)!parsewarning(parser, WARN_EXTENSIONS,
545                                         "accessing array-field members of an entity without parenthesis\n"
546                                         " -> this is an extension from -std=gmqcc");
547                 }
548             }
549             break;
550
551         case opid1(','):
552             if (blocks[0]) {
553                 vec_push(blocks[0]->exprs, exprs[1]);
554             } else {
555                 blocks[0] = ast_block_new(ctx);
556                 vec_push(blocks[0]->exprs, exprs[0]);
557                 vec_push(blocks[0]->exprs, exprs[1]);
558             }
559             if (!ast_block_set_type(blocks[0], exprs[1]))
560                 return false;
561
562             vec_push(sy->out, syblock(ctx, blocks[0]));
563             return true;
564
565         case opid2('-','P'):
566             switch (exprs[0]->expression.vtype) {
567                 case TYPE_FLOAT:
568                     if (CanConstFold1(exprs[0]))
569                         out = (ast_expression*)parser_const_float(parser, -ConstF(0));
570                     else
571                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
572                                                               (ast_expression*)parser_const_float_0(parser),
573                                                               exprs[0]);
574                     break;
575                 case TYPE_VECTOR:
576                     if (CanConstFold1(exprs[0]))
577                         out = (ast_expression*)parser_const_vector_f(parser,
578                             -ConstV(0).x, -ConstV(0).y, -ConstV(0).z);
579                     else
580                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
581                                                               (ast_expression*)parser_const_vector_0(parser),
582                                                               exprs[0]);
583                     break;
584                 default:
585                 parseerror(parser, "invalid types used in expression: cannot negate type %s",
586                            type_name[exprs[0]->expression.vtype]);
587                 return false;
588             }
589             break;
590
591         case opid2('!','P'):
592             switch (exprs[0]->expression.vtype) {
593                 case TYPE_FLOAT:
594                     if (CanConstFold1(exprs[0]))
595                         out = (ast_expression*)parser_const_float(parser, !ConstF(0));
596                     else
597                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
598                     break;
599                 case TYPE_VECTOR:
600                     if (CanConstFold1(exprs[0]))
601                         out = (ast_expression*)parser_const_float(parser,
602                             (!ConstV(0).x && !ConstV(0).y && !ConstV(0).z));
603                     else
604                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]);
605                     break;
606                 case TYPE_STRING:
607                     if (CanConstFold1(exprs[0]))
608                         out = (ast_expression*)parser_const_float(parser, !ConstS(0) || !*ConstS(0));
609                     else
610                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]);
611                     break;
612                 /* we don't constant-fold NOT for these types */
613                 case TYPE_ENTITY:
614                     out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]);
615                     break;
616                 case TYPE_FUNCTION:
617                     out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]);
618                     break;
619                 default:
620                 parseerror(parser, "invalid types used in expression: cannot logically negate type %s",
621                            type_name[exprs[0]->expression.vtype]);
622                 return false;
623             }
624             break;
625
626         case opid1('+'):
627             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
628                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
629             {
630                 parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
631                            type_name[exprs[0]->expression.vtype],
632                            type_name[exprs[1]->expression.vtype]);
633                 return false;
634             }
635             switch (exprs[0]->expression.vtype) {
636                 case TYPE_FLOAT:
637                     if (CanConstFold(exprs[0], exprs[1]))
638                     {
639                         out = (ast_expression*)parser_const_float(parser, ConstF(0) + ConstF(1));
640                     }
641                     else
642                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
643                     break;
644                 case TYPE_VECTOR:
645                     if (CanConstFold(exprs[0], exprs[1]))
646                         out = (ast_expression*)parser_const_vector(parser, vec3_add(ConstV(0), ConstV(1)));
647                     else
648                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
649                     break;
650                 default:
651                     parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
652                                type_name[exprs[0]->expression.vtype],
653                                type_name[exprs[1]->expression.vtype]);
654                     return false;
655             };
656             break;
657         case opid1('-'):
658             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
659                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
660             {
661                 parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
662                            type_name[exprs[1]->expression.vtype],
663                            type_name[exprs[0]->expression.vtype]);
664                 return false;
665             }
666             switch (exprs[0]->expression.vtype) {
667                 case TYPE_FLOAT:
668                     if (CanConstFold(exprs[0], exprs[1]))
669                         out = (ast_expression*)parser_const_float(parser, ConstF(0) - ConstF(1));
670                     else
671                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
672                     break;
673                 case TYPE_VECTOR:
674                     if (CanConstFold(exprs[0], exprs[1]))
675                         out = (ast_expression*)parser_const_vector(parser, vec3_sub(ConstV(0), ConstV(1)));
676                     else
677                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
678                     break;
679                 default:
680                     parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
681                                type_name[exprs[1]->expression.vtype],
682                                type_name[exprs[0]->expression.vtype]);
683                     return false;
684             };
685             break;
686         case opid1('*'):
687             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype &&
688                 exprs[0]->expression.vtype != TYPE_VECTOR &&
689                 exprs[0]->expression.vtype != TYPE_FLOAT &&
690                 exprs[1]->expression.vtype != TYPE_VECTOR &&
691                 exprs[1]->expression.vtype != TYPE_FLOAT)
692             {
693                 parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",
694                            type_name[exprs[1]->expression.vtype],
695                            type_name[exprs[0]->expression.vtype]);
696                 return false;
697             }
698             switch (exprs[0]->expression.vtype) {
699                 case TYPE_FLOAT:
700                     if (exprs[1]->expression.vtype == TYPE_VECTOR)
701                     {
702                         if (CanConstFold(exprs[0], exprs[1]))
703                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(1), ConstF(0)));
704                         else
705                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
706                     }
707                     else
708                     {
709                         if (CanConstFold(exprs[0], exprs[1]))
710                             out = (ast_expression*)parser_const_float(parser, ConstF(0) * ConstF(1));
711                         else
712                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
713                     }
714                     break;
715                 case TYPE_VECTOR:
716                     if (exprs[1]->expression.vtype == TYPE_FLOAT)
717                     {
718                         if (CanConstFold(exprs[0], exprs[1]))
719                             out = (ast_expression*)parser_const_vector(parser, vec3_mulvf(ConstV(0), ConstF(1)));
720                         else
721                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
722                     }
723                     else
724                     {
725                         if (CanConstFold(exprs[0], exprs[1]))
726                             out = (ast_expression*)parser_const_float(parser, vec3_mulvv(ConstV(0), ConstV(1)));
727                         else
728                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
729                     }
730                     break;
731                 default:
732                     parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",
733                                type_name[exprs[1]->expression.vtype],
734                                type_name[exprs[0]->expression.vtype]);
735                     return false;
736             };
737             break;
738         case opid1('/'):
739             if (NotSameType(TYPE_FLOAT)) {
740                 parseerror(parser, "invalid types used in expression: cannot divide types %s and %s",
741                            type_name[exprs[0]->expression.vtype],
742                            type_name[exprs[1]->expression.vtype]);
743                 return false;
744             }
745             if (CanConstFold(exprs[0], exprs[1]))
746                 out = (ast_expression*)parser_const_float(parser, ConstF(0) / ConstF(1));
747             else
748                 out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
749             break;
750         case opid1('%'):
751         case opid2('%','='):
752             parseerror(parser, "qc does not have a modulo operator");
753             return false;
754         case opid1('|'):
755         case opid1('&'):
756             if (NotSameType(TYPE_FLOAT)) {
757                 parseerror(parser, "invalid types used in expression: cannot perform bit operations between types %s and %s",
758                            type_name[exprs[0]->expression.vtype],
759                            type_name[exprs[1]->expression.vtype]);
760                 return false;
761             }
762             if (CanConstFold(exprs[0], exprs[1]))
763                 out = (ast_expression*)parser_const_float(parser,
764                     (op->id == opid1('|') ? (float)( ((qcint)ConstF(0)) | ((qcint)ConstF(1)) ) :
765                                             (float)( ((qcint)ConstF(0)) & ((qcint)ConstF(1)) ) ));
766             else
767                 out = (ast_expression*)ast_binary_new(ctx,
768                     (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
769                     exprs[0], exprs[1]);
770             break;
771         case opid1('^'):
772             parseerror(parser, "TODO: bitxor");
773             return false;
774
775         case opid2('<','<'):
776         case opid2('>','>'):
777         case opid3('<','<','='):
778         case opid3('>','>','='):
779             parseerror(parser, "TODO: shifts");
780             return false;
781
782         case opid2('|','|'):
783             generated_op += 1; /* INSTR_OR */
784         case opid2('&','&'):
785             generated_op += INSTR_AND;
786             if (NotSameType(TYPE_FLOAT)) {
787                 parseerror(parser, "invalid types used in expression: cannot perform logical operations between types %s and %s",
788                            type_name[exprs[0]->expression.vtype],
789                            type_name[exprs[1]->expression.vtype]);
790                 parseerror(parser, "TODO: logical ops for arbitrary types using INSTR_NOT");
791                 parseerror(parser, "TODO: optional early out");
792                 return false;
793             }
794             if (opts_standard == COMPILER_GMQCC)
795                 con_out("TODO: early out logic\n");
796             if (CanConstFold(exprs[0], exprs[1]))
797                 out = (ast_expression*)parser_const_float(parser,
798                     (generated_op == INSTR_OR ? (ConstF(0) || ConstF(1)) : (ConstF(0) && ConstF(1))));
799             else
800                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
801             break;
802
803         case opid2('?',':'):
804             if (exprs[1]->expression.vtype != exprs[2]->expression.vtype) {
805                 ast_type_to_string(exprs[1], ty1, sizeof(ty1));
806                 ast_type_to_string(exprs[2], ty2, sizeof(ty2));
807                 parseerror(parser, "iperands of ternary expression must have the same type, got %s and %s", ty1, ty2);
808                 return false;
809             }
810             if (CanConstFold1(exprs[0]))
811                 out = (ConstF(0) ? exprs[1] : exprs[2]);
812             else
813                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
814             break;
815
816         case opid1('>'):
817             generated_op += 1; /* INSTR_GT */
818         case opid1('<'):
819             generated_op += 1; /* INSTR_LT */
820         case opid2('>', '='):
821             generated_op += 1; /* INSTR_GE */
822         case opid2('<', '='):
823             generated_op += INSTR_LE;
824             if (NotSameType(TYPE_FLOAT)) {
825                 parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
826                            type_name[exprs[0]->expression.vtype],
827                            type_name[exprs[1]->expression.vtype]);
828                 return false;
829             }
830             out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
831             break;
832         case opid2('!', '='):
833             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
834                 parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
835                            type_name[exprs[0]->expression.vtype],
836                            type_name[exprs[1]->expression.vtype]);
837                 return false;
838             }
839             out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
840             break;
841         case opid2('=', '='):
842             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
843                 parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
844                            type_name[exprs[0]->expression.vtype],
845                            type_name[exprs[1]->expression.vtype]);
846                 return false;
847             }
848             out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->expression.vtype], exprs[0], exprs[1]);
849             break;
850
851         case opid1('='):
852             if (ast_istype(exprs[0], ast_entfield)) {
853                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
854                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
855                     exprs[0]->expression.vtype == TYPE_FIELD &&
856                     exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
857                 {
858                     assignop = type_storep_instr[TYPE_VECTOR];
859                 }
860                 else
861                     assignop = type_storep_instr[exprs[0]->expression.vtype];
862                 if (!ast_compare_type(field->expression.next, exprs[1])) {
863                     ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
864                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
865                     if (opts_standard == COMPILER_QCC &&
866                         field->expression.next->expression.vtype == TYPE_FUNCTION &&
867                         exprs[1]->expression.vtype == TYPE_FUNCTION)
868                     {
869                         if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
870                                          "invalid types in assignment: cannot assign %s to %s", ty2, ty1))
871                         {
872                             parser->errors++;
873                         }
874                     }
875                     else
876                         parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
877                 }
878             }
879             else
880             {
881                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
882                     exprs[0]->expression.vtype == TYPE_FIELD &&
883                     exprs[0]->expression.next->expression.vtype == TYPE_VECTOR)
884                 {
885                     assignop = type_store_instr[TYPE_VECTOR];
886                 }
887                 else {
888                     assignop = type_store_instr[exprs[0]->expression.vtype];
889                 }
890
891                 if (assignop == AINSTR_END) {
892                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
893                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
894                     parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
895                 }
896                 else if (!ast_compare_type(exprs[0], exprs[1])) {
897                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
898                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
899                     if (opts_standard == COMPILER_QCC &&
900                         exprs[0]->expression.vtype == TYPE_FUNCTION &&
901                         exprs[1]->expression.vtype == TYPE_FUNCTION)
902                     {
903                         if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
904                                          "invalid types in assignment: cannot assign %s to %s", ty2, ty1))
905                         {
906                             parser->errors++;
907                         }
908                     }
909                     else
910                         parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
911                 }
912             }
913             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
914             break;
915         case opid3('+','+','P'):
916         case opid3('-','-','P'):
917             /* prefix ++ */
918             if (exprs[0]->expression.vtype != TYPE_FLOAT) {
919                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
920                 parseerror(parser, "invalid type for prefix increment: %s", ty1);
921                 return false;
922             }
923             if (op->id == opid3('+','+','P'))
924                 addop = INSTR_ADD_F;
925             else
926                 addop = INSTR_SUB_F;
927             if (ast_istype(exprs[0], ast_entfield)) {
928                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
929                                                         exprs[0],
930                                                         (ast_expression*)parser_const_float_1(parser));
931             } else {
932                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
933                                                         exprs[0],
934                                                         (ast_expression*)parser_const_float_1(parser));
935             }
936             break;
937         case opid3('S','+','+'):
938         case opid3('S','-','-'):
939             /* prefix ++ */
940             if (exprs[0]->expression.vtype != TYPE_FLOAT) {
941                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
942                 parseerror(parser, "invalid type for suffix increment: %s", ty1);
943                 return false;
944             }
945             if (op->id == opid3('S','+','+')) {
946                 addop = INSTR_ADD_F;
947                 subop = INSTR_SUB_F;
948             } else {
949                 addop = INSTR_SUB_F;
950                 subop = INSTR_ADD_F;
951             }
952             if (ast_istype(exprs[0], ast_entfield)) {
953                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
954                                                         exprs[0],
955                                                         (ast_expression*)parser_const_float_1(parser));
956             } else {
957                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
958                                                         exprs[0],
959                                                         (ast_expression*)parser_const_float_1(parser));
960             }
961             if (!out)
962                 return false;
963             out = (ast_expression*)ast_binary_new(ctx, subop,
964                                                   out,
965                                                   (ast_expression*)parser_const_float_1(parser));
966             break;
967         case opid2('+','='):
968         case opid2('-','='):
969             if (exprs[0]->expression.vtype != exprs[1]->expression.vtype ||
970                 (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) )
971             {
972                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
973                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
974                 parseerror(parser, "invalid types used in expression: cannot add or subtract type %s and %s",
975                            ty1, ty2);
976                 return false;
977             }
978             if (ast_istype(exprs[0], ast_entfield))
979                 assignop = type_storep_instr[exprs[0]->expression.vtype];
980             else
981                 assignop = type_store_instr[exprs[0]->expression.vtype];
982             switch (exprs[0]->expression.vtype) {
983                 case TYPE_FLOAT:
984                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
985                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
986                                                             exprs[0], exprs[1]);
987                     break;
988                 case TYPE_VECTOR:
989                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
990                                                             (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V),
991                                                             exprs[0], exprs[1]);
992                     break;
993                 default:
994                     parseerror(parser, "invalid types used in expression: cannot add or subtract type %s and %s",
995                                type_name[exprs[0]->expression.vtype],
996                                type_name[exprs[1]->expression.vtype]);
997                     return false;
998             };
999             break;
1000         case opid2('*','='):
1001         case opid2('/','='):
1002             if (exprs[1]->expression.vtype != TYPE_FLOAT ||
1003                 !(exprs[0]->expression.vtype == TYPE_FLOAT ||
1004                   exprs[0]->expression.vtype == TYPE_VECTOR))
1005             {
1006                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1007                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1008                 parseerror(parser, "invalid types used in expression: %s and %s",
1009                            ty1, ty2);
1010                 return false;
1011             }
1012             if (ast_istype(exprs[0], ast_entfield))
1013                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1014             else
1015                 assignop = type_store_instr[exprs[0]->expression.vtype];
1016             switch (exprs[0]->expression.vtype) {
1017                 case TYPE_FLOAT:
1018                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1019                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
1020                                                             exprs[0], exprs[1]);
1021                     break;
1022                 case TYPE_VECTOR:
1023                     if (op->id == opid2('*','=')) {
1024                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1025                                                                 exprs[0], exprs[1]);
1026                     } else {
1027                         /* there's no DIV_VF */
1028                         out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
1029                                                               (ast_expression*)parser_const_float_1(parser),
1030                                                               exprs[1]);
1031                         if (!out)
1032                             return false;
1033                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1034                                                                 exprs[0], out);
1035                     }
1036                     break;
1037                 default:
1038                     parseerror(parser, "invalid types used in expression: cannot add or subtract type %s and %s",
1039                                type_name[exprs[0]->expression.vtype],
1040                                type_name[exprs[1]->expression.vtype]);
1041                     return false;
1042             };
1043             break;
1044         case opid2('&','='):
1045         case opid2('|','='):
1046             if (NotSameType(TYPE_FLOAT)) {
1047                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1048                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1049                 parseerror(parser, "invalid types used in expression: %s and %s",
1050                            ty1, ty2);
1051                 return false;
1052             }
1053             if (ast_istype(exprs[0], ast_entfield))
1054                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1055             else
1056                 assignop = type_store_instr[exprs[0]->expression.vtype];
1057             out = (ast_expression*)ast_binstore_new(ctx, assignop,
1058                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
1059                                                     exprs[0], exprs[1]);
1060             break;
1061         case opid3('&','~','='):
1062             /* This is like: a &= ~(b);
1063              * But QC has no bitwise-not, so we implement it as
1064              * a -= a & (b);
1065              */
1066             if (NotSameType(TYPE_FLOAT)) {
1067                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1068                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1069                 parseerror(parser, "invalid types used in expression: %s and %s",
1070                            ty1, ty2);
1071                 return false;
1072             }
1073             if (ast_istype(exprs[0], ast_entfield))
1074                 assignop = type_storep_instr[exprs[0]->expression.vtype];
1075             else
1076                 assignop = type_store_instr[exprs[0]->expression.vtype];
1077             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
1078             if (!out)
1079                 return false;
1080             out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
1081             break;
1082     }
1083 #undef NotSameType
1084
1085     if (!out) {
1086         parseerror(parser, "failed to apply operand %s", op->op);
1087         return false;
1088     }
1089
1090     DEBUGSHUNTDO(con_out("applied %s\n", op->op));
1091     vec_push(sy->out, syexp(ctx, out));
1092     return true;
1093 }
1094
1095 static bool parser_close_call(parser_t *parser, shunt *sy)
1096 {
1097     /* was a function call */
1098     ast_expression *fun;
1099     ast_call       *call;
1100
1101     size_t          fid;
1102     size_t          paramcount;
1103
1104     vec_shrinkby(sy->ops, 1);
1105     fid = sy->ops[vec_size(sy->ops)].off;
1106
1107     /* out[fid] is the function
1108      * everything above is parameters...
1109      * 0 params = nothing
1110      * 1 params = ast_expression
1111      * more = ast_block
1112      */
1113
1114     if (vec_size(sy->out) < 1 || vec_size(sy->out) <= fid) {
1115         parseerror(parser, "internal error: function call needs function and parameter list...");
1116         return false;
1117     }
1118
1119     fun = sy->out[fid].out;
1120
1121     call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
1122     if (!call) {
1123         parseerror(parser, "out of memory");
1124         return false;
1125     }
1126
1127     if (fid+1 == vec_size(sy->out)) {
1128         /* no arguments */
1129         paramcount = 0;
1130     } else if (fid+2 == vec_size(sy->out)) {
1131         ast_block *params;
1132         vec_shrinkby(sy->out, 1);
1133         params = sy->out[vec_size(sy->out)].block;
1134         if (!params) {
1135             /* 1 param */
1136             paramcount = 1;
1137             vec_push(call->params, sy->out[vec_size(sy->out)].out);
1138         } else {
1139             paramcount = vec_size(params->exprs);
1140             call->params = params->exprs;
1141             params->exprs = NULL;
1142             ast_delete(params);
1143         }
1144         if (!ast_call_check_types(call))
1145             parser->errors++;
1146     } else {
1147         parseerror(parser, "invalid function call");
1148         return false;
1149     }
1150
1151     /* overwrite fid, the function, with a call */
1152     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
1153
1154     if (fun->expression.vtype != TYPE_FUNCTION) {
1155         parseerror(parser, "not a function (%s)", type_name[fun->expression.vtype]);
1156         return false;
1157     }
1158
1159     if (!fun->expression.next) {
1160         parseerror(parser, "could not determine function return type");
1161         return false;
1162     } else {
1163         if (vec_size(fun->expression.params) != paramcount &&
1164             !(fun->expression.variadic &&
1165               vec_size(fun->expression.params) < paramcount))
1166         {
1167             ast_value *fval;
1168             const char *fewmany = (vec_size(fun->expression.params) > paramcount) ? "few" : "many";
1169
1170             fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
1171             if (opts_standard == COMPILER_GMQCC)
1172             {
1173                 if (fval)
1174                     parseerror(parser, "too %s parameters for call to %s: expected %i, got %i\n"
1175                                " -> `%s` has been declared here: %s:%i",
1176                                fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
1177                                fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1178                 else
1179                     parseerror(parser, "too %s parameters for function call: expected %i, got %i\n"
1180                                " -> `%s` has been declared here: %s:%i",
1181                                fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
1182                                fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1183                 return false;
1184             }
1185             else
1186             {
1187                 if (fval)
1188                     return !parsewarning(parser, WARN_TOO_FEW_PARAMETERS,
1189                                          "too %s parameters for call to %s: expected %i, got %i\n"
1190                                          " -> `%s` has been declared here: %s:%i",
1191                                          fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
1192                                          fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1193                 else
1194                     return !parsewarning(parser, WARN_TOO_FEW_PARAMETERS,
1195                                          "too %s parameters for function call: expected %i, got %i\n"
1196                                          " -> `%s` has been declared here: %s:%i",
1197                                          fewmany, fval->name, (int)vec_size(fun->expression.params), (int)paramcount,
1198                                          fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1199             }
1200         }
1201     }
1202
1203     return true;
1204 }
1205
1206 static bool parser_close_paren(parser_t *parser, shunt *sy, bool functions_only)
1207 {
1208     if (!vec_size(sy->ops)) {
1209         parseerror(parser, "unmatched closing paren");
1210         return false;
1211     }
1212     /* this would for bit a + (x) because there are no operators inside (x)
1213     if (sy->ops[vec_size(sy->ops)-1].paren == 1) {
1214         parseerror(parser, "empty parenthesis expression");
1215         return false;
1216     }
1217     */
1218     while (vec_size(sy->ops)) {
1219         if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_FUNC) {
1220             if (!parser_close_call(parser, sy))
1221                 return false;
1222             break;
1223         }
1224         if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_EXPR) {
1225             vec_shrinkby(sy->ops, 1);
1226             return !functions_only;
1227         }
1228         if (sy->ops[vec_size(sy->ops)-1].paren == SY_PAREN_INDEX) {
1229             if (functions_only)
1230                 return false;
1231             /* pop off the parenthesis */
1232             vec_shrinkby(sy->ops, 1);
1233             /* then apply the index operator */
1234             if (!parser_sy_pop(parser, sy))
1235                 return false;
1236             return true;
1237         }
1238         if (!parser_sy_pop(parser, sy))
1239             return false;
1240     }
1241     return true;
1242 }
1243
1244 static void parser_reclassify_token(parser_t *parser)
1245 {
1246     size_t i;
1247     for (i = 0; i < operator_count; ++i) {
1248         if (!strcmp(parser_tokval(parser), operators[i].op)) {
1249             parser->tok = TOKEN_OPERATOR;
1250             return;
1251         }
1252     }
1253 }
1254
1255 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma)
1256 {
1257     ast_expression *expr = NULL;
1258     shunt sy;
1259     bool wantop = false;
1260     bool gotmemberof = false;
1261
1262     /* count the parens because an if starts with one, so the
1263      * end of a condition is an unmatched closing paren
1264      */
1265     int parens = 0;
1266     int ternaries = 0;
1267
1268     sy.out = NULL;
1269     sy.ops = NULL;
1270
1271     parser->lex->flags.noops = false;
1272
1273     parser_reclassify_token(parser);
1274
1275     while (true)
1276     {
1277         if (gotmemberof)
1278             gotmemberof = false;
1279         else
1280             parser->memberof = 0;
1281
1282         if (parser->tok == TOKEN_IDENT)
1283         {
1284             ast_expression *var;
1285             if (wantop) {
1286                 parseerror(parser, "expected operator or end of statement");
1287                 goto onerr;
1288             }
1289             wantop = true;
1290             /* variable */
1291             if (opts_standard == COMPILER_GMQCC)
1292             {
1293                 if (parser->memberof == TYPE_ENTITY) {
1294                     /* still get vars first since there could be a fieldpointer */
1295                     var = parser_find_var(parser, parser_tokval(parser));
1296                     if (!var)
1297                         var = parser_find_field(parser, parser_tokval(parser));
1298                 }
1299                 else if (parser->memberof == TYPE_VECTOR)
1300                 {
1301                     parseerror(parser, "TODO: implement effective vector member access");
1302                     goto onerr;
1303                 }
1304                 else if (parser->memberof) {
1305                     parseerror(parser, "namespace for member not found");
1306                     goto onerr;
1307                 }
1308                 else
1309                     var = parser_find_var(parser, parser_tokval(parser));
1310             } else {
1311                 var = parser_find_var(parser, parser_tokval(parser));
1312                 if (!var)
1313                     var = parser_find_field(parser, parser_tokval(parser));
1314             }
1315             if (!var) {
1316                 parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
1317                 goto onerr;
1318             }
1319             if (ast_istype(var, ast_value))
1320                 ((ast_value*)var)->uses++;
1321             vec_push(sy.out, syexp(parser_ctx(parser), var));
1322             DEBUGSHUNTDO(con_out("push %s\n", parser_tokval(parser)));
1323         }
1324         else if (parser->tok == TOKEN_FLOATCONST) {
1325             ast_value *val;
1326             if (wantop) {
1327                 parseerror(parser, "expected operator or end of statement, got constant");
1328                 goto onerr;
1329             }
1330             wantop = true;
1331             val = parser_const_float(parser, (parser_token(parser)->constval.f));
1332             if (!val)
1333                 return false;
1334             vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
1335             DEBUGSHUNTDO(con_out("push %g\n", parser_token(parser)->constval.f));
1336         }
1337         else if (parser->tok == TOKEN_INTCONST) {
1338             ast_value *val;
1339             if (wantop) {
1340                 parseerror(parser, "expected operator or end of statement, got constant");
1341                 goto onerr;
1342             }
1343             wantop = true;
1344             val = parser_const_float(parser, (double)(parser_token(parser)->constval.i));
1345             if (!val)
1346                 return false;
1347             vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
1348             DEBUGSHUNTDO(con_out("push %i\n", parser_token(parser)->constval.i));
1349         }
1350         else if (parser->tok == TOKEN_STRINGCONST) {
1351             ast_value *val;
1352             if (wantop) {
1353                 parseerror(parser, "expected operator or end of statement, got constant");
1354                 goto onerr;
1355             }
1356             wantop = true;
1357             val = parser_const_string(parser, parser_tokval(parser));
1358             if (!val)
1359                 return false;
1360             vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
1361             DEBUGSHUNTDO(con_out("push string\n"));
1362         }
1363         else if (parser->tok == TOKEN_VECTORCONST) {
1364             ast_value *val;
1365             if (wantop) {
1366                 parseerror(parser, "expected operator or end of statement, got constant");
1367                 goto onerr;
1368             }
1369             wantop = true;
1370             val = parser_const_vector(parser, parser_token(parser)->constval.v);
1371             if (!val)
1372                 return false;
1373             vec_push(sy.out, syexp(parser_ctx(parser), (ast_expression*)val));
1374             DEBUGSHUNTDO(con_out("push '%g %g %g'\n",
1375                                 parser_token(parser)->constval.v.x,
1376                                 parser_token(parser)->constval.v.y,
1377                                 parser_token(parser)->constval.v.z));
1378         }
1379         else if (parser->tok == '(') {
1380             parseerror(parser, "internal error: '(' should be classified as operator");
1381             goto onerr;
1382         }
1383         else if (parser->tok == '[') {
1384             parseerror(parser, "internal error: '[' should be classified as operator");
1385             goto onerr;
1386         }
1387         else if (parser->tok == ')') {
1388             if (wantop) {
1389                 DEBUGSHUNTDO(con_out("do[op] )\n"));
1390                 --parens;
1391                 if (parens < 0)
1392                     break;
1393                 /* we do expect an operator next */
1394                 /* closing an opening paren */
1395                 if (!parser_close_paren(parser, &sy, false))
1396                     goto onerr;
1397             } else {
1398                 DEBUGSHUNTDO(con_out("do[nop] )\n"));
1399                 --parens;
1400                 if (parens < 0)
1401                     break;
1402                 /* allowed for function calls */
1403                 if (!parser_close_paren(parser, &sy, true))
1404                     goto onerr;
1405             }
1406             wantop = true;
1407         }
1408         else if (parser->tok == ']') {
1409             if (!wantop)
1410                 parseerror(parser, "operand expected");
1411             --parens;
1412             if (parens < 0)
1413                 break;
1414             if (!parser_close_paren(parser, &sy, false))
1415                 goto onerr;
1416             wantop = true;
1417         }
1418         else if (parser->tok != TOKEN_OPERATOR) {
1419             if (wantop) {
1420                 parseerror(parser, "expected operator or end of statement");
1421                 goto onerr;
1422             }
1423             break;
1424         }
1425         else
1426         {
1427             /* classify the operator */
1428             const oper_info *op;
1429             const oper_info *olast = NULL;
1430             size_t o;
1431             for (o = 0; o < operator_count; ++o) {
1432                 if ((!(operators[o].flags & OP_PREFIX) == wantop) &&
1433                     /* !(operators[o].flags & OP_SUFFIX) && / * remove this */
1434                     !strcmp(parser_tokval(parser), operators[o].op))
1435                 {
1436                     break;
1437                 }
1438             }
1439             if (o == operator_count) {
1440                 /* no operator found... must be the end of the statement */
1441                 break;
1442             }
1443             /* found an operator */
1444             op = &operators[o];
1445
1446             /* when declaring variables, a comma starts a new variable */
1447             if (op->id == opid1(',') && !parens && stopatcomma) {
1448                 /* fixup the token */
1449                 parser->tok = ',';
1450                 break;
1451             }
1452
1453             /* a colon without a pervious question mark cannot be a ternary */
1454             if (!ternaries && op->id == opid2(':','?')) {
1455                 parser->tok = ':';
1456                 break;
1457             }
1458
1459             if (vec_size(sy.ops) && !vec_last(sy.ops).paren)
1460                 olast = &operators[vec_last(sy.ops).etype-1];
1461
1462             while (olast && (
1463                     (op->prec < olast->prec) ||
1464                     (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
1465             {
1466                 if (!parser_sy_pop(parser, &sy))
1467                     goto onerr;
1468                 if (vec_size(sy.ops) && !vec_last(sy.ops).paren)
1469                     olast = &operators[vec_last(sy.ops).etype-1];
1470                 else
1471                     olast = NULL;
1472             }
1473
1474             if (op->id == opid1('.') && opts_standard == COMPILER_GMQCC) {
1475                 /* for gmqcc standard: open up the namespace of the previous type */
1476                 ast_expression *prevex = vec_last(sy.out).out;
1477                 if (!prevex) {
1478                     parseerror(parser, "unexpected member operator");
1479                     goto onerr;
1480                 }
1481                 if (prevex->expression.vtype == TYPE_ENTITY)
1482                     parser->memberof = TYPE_ENTITY;
1483                 else if (prevex->expression.vtype == TYPE_VECTOR)
1484                     parser->memberof = TYPE_VECTOR;
1485                 else {
1486                     parseerror(parser, "type error: type has no members");
1487                     goto onerr;
1488                 }
1489                 gotmemberof = true;
1490             }
1491
1492             if (op->id == opid1('(')) {
1493                 if (wantop) {
1494                     size_t sycount = vec_size(sy.out);
1495                     DEBUGSHUNTDO(con_out("push [op] (\n"));
1496                     ++parens;
1497                     /* we expected an operator, this is the function-call operator */
1498                     vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_FUNC, sycount-1));
1499                 } else {
1500                     ++parens;
1501                     vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_EXPR, 0));
1502                     DEBUGSHUNTDO(con_out("push [nop] (\n"));
1503                 }
1504                 wantop = false;
1505             } else if (op->id == opid1('[')) {
1506                 if (!wantop) {
1507                     parseerror(parser, "unexpected array subscript");
1508                     goto onerr;
1509                 }
1510                 ++parens;
1511                 /* push both the operator and the paren, this makes life easier */
1512                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1513                 vec_push(sy.ops, syparen(parser_ctx(parser), SY_PAREN_INDEX, 0));
1514                 wantop = false;
1515             } else if (op->id == opid2('?',':')) {
1516                 wantop = false;
1517                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1518                 wantop = false;
1519                 --ternaries;
1520             } else if (op->id == opid2(':','?')) {
1521                 /* we don't push this operator */
1522                 wantop = false;
1523                 ++ternaries;
1524             } else {
1525                 DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
1526                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1527                 wantop = !!(op->flags & OP_SUFFIX);
1528             }
1529         }
1530         if (!parser_next(parser)) {
1531             goto onerr;
1532         }
1533         if (parser->tok == ';' ||
1534             (!parens && parser->tok == ']'))
1535         {
1536             break;
1537         }
1538     }
1539
1540     while (vec_size(sy.ops)) {
1541         if (!parser_sy_pop(parser, &sy))
1542             goto onerr;
1543     }
1544
1545     parser->lex->flags.noops = true;
1546     if (!vec_size(sy.out)) {
1547         parseerror(parser, "empty expression");
1548         expr = NULL;
1549     } else
1550         expr = sy.out[0].out;
1551     vec_free(sy.out);
1552     vec_free(sy.ops);
1553     DEBUGSHUNTDO(con_out("shunt done\n"));
1554     return expr;
1555
1556 onerr:
1557     parser->lex->flags.noops = true;
1558     vec_free(sy.out);
1559     vec_free(sy.ops);
1560     return NULL;
1561 }
1562
1563 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma)
1564 {
1565     ast_expression *e = parse_expression_leave(parser, stopatcomma);
1566     if (!e)
1567         return NULL;
1568     if (!parser_next(parser)) {
1569         ast_delete(e);
1570         return NULL;
1571     }
1572     return e;
1573 }
1574
1575 static void parser_enterblock(parser_t *parser)
1576 {
1577     vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
1578     vec_push(parser->_blocklocals, vec_size(parser->_locals));
1579 }
1580
1581 static bool parser_leaveblock(parser_t *parser)
1582 {
1583     bool   rv = true;
1584     size_t locals;
1585
1586     if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
1587         parseerror(parser, "internal error: parser_leaveblock with no block");
1588         return false;
1589     }
1590
1591     util_htdel(vec_last(parser->variables));
1592     vec_pop(parser->variables);
1593     if (!vec_size(parser->_blocklocals)) {
1594         parseerror(parser, "internal error: parser_leaveblock with no block (2)");
1595         return false;
1596     }
1597
1598     locals = vec_last(parser->_blocklocals);
1599     vec_pop(parser->_blocklocals);
1600     while (vec_size(parser->_locals) != locals) {
1601         ast_expression *e = vec_last(parser->_locals);
1602         ast_value      *v = (ast_value*)e;
1603         vec_pop(parser->_locals);
1604         if (ast_istype(e, ast_value) && !v->uses) {
1605             if (parsewarning(parser, WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
1606                 rv = false;
1607         }
1608     }
1609
1610     return rv;
1611 }
1612
1613 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
1614 {
1615     vec_push(parser->_locals, e);
1616     util_htset(vec_last(parser->variables), name, (void*)e);
1617 }
1618
1619 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
1620 {
1621     ast_ifthen *ifthen;
1622     ast_expression *cond, *ontrue, *onfalse = NULL;
1623     bool ifnot = false;
1624
1625     lex_ctx ctx = parser_ctx(parser);
1626
1627     (void)block; /* not touching */
1628
1629     /* skip the 'if', parse an optional 'not' and check for an opening paren */
1630     if (!parser_next(parser)) {
1631         parseerror(parser, "expected condition or 'not'");
1632         return false;
1633     }
1634     if (parser->tok == TOKEN_KEYWORD && !strcmp(parser_tokval(parser), "not")) {
1635         ifnot = true;
1636         if (!parser_next(parser)) {
1637             parseerror(parser, "expected condition in parenthesis");
1638             return false;
1639         }
1640     }
1641     if (parser->tok != '(') {
1642         parseerror(parser, "expected 'if' condition in parenthesis");
1643         return false;
1644     }
1645     /* parse into the expression */
1646     if (!parser_next(parser)) {
1647         parseerror(parser, "expected 'if' condition after opening paren");
1648         return false;
1649     }
1650     /* parse the condition */
1651     cond = parse_expression_leave(parser, false);
1652     if (!cond)
1653         return false;
1654     /* closing paren */
1655     if (parser->tok != ')') {
1656         parseerror(parser, "expected closing paren after 'if' condition");
1657         ast_delete(cond);
1658         return false;
1659     }
1660     /* parse into the 'then' branch */
1661     if (!parser_next(parser)) {
1662         parseerror(parser, "expected statement for on-true branch of 'if'");
1663         ast_delete(cond);
1664         return false;
1665     }
1666     ontrue = parse_statement_or_block(parser);
1667     if (!ontrue) {
1668         ast_delete(cond);
1669         return false;
1670     }
1671     /* check for an else */
1672     if (!strcmp(parser_tokval(parser), "else")) {
1673         /* parse into the 'else' branch */
1674         if (!parser_next(parser)) {
1675             parseerror(parser, "expected on-false branch after 'else'");
1676             ast_delete(ontrue);
1677             ast_delete(cond);
1678             return false;
1679         }
1680         onfalse = parse_statement_or_block(parser);
1681         if (!onfalse) {
1682             ast_delete(ontrue);
1683             ast_delete(cond);
1684             return false;
1685         }
1686     }
1687
1688     if (ifnot)
1689         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
1690     else
1691         ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
1692     *out = (ast_expression*)ifthen;
1693     return true;
1694 }
1695
1696 static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out)
1697 {
1698     ast_loop *aloop;
1699     ast_expression *cond, *ontrue;
1700
1701     lex_ctx ctx = parser_ctx(parser);
1702
1703     (void)block; /* not touching */
1704
1705     /* skip the 'while' and check for opening paren */
1706     if (!parser_next(parser) || parser->tok != '(') {
1707         parseerror(parser, "expected 'while' condition in parenthesis");
1708         return false;
1709     }
1710     /* parse into the expression */
1711     if (!parser_next(parser)) {
1712         parseerror(parser, "expected 'while' condition after opening paren");
1713         return false;
1714     }
1715     /* parse the condition */
1716     cond = parse_expression_leave(parser, false);
1717     if (!cond)
1718         return false;
1719     /* closing paren */
1720     if (parser->tok != ')') {
1721         parseerror(parser, "expected closing paren after 'while' condition");
1722         ast_delete(cond);
1723         return false;
1724     }
1725     /* parse into the 'then' branch */
1726     if (!parser_next(parser)) {
1727         parseerror(parser, "expected while-loop body");
1728         ast_delete(cond);
1729         return false;
1730     }
1731     ontrue = parse_statement_or_block(parser);
1732     if (!ontrue) {
1733         ast_delete(cond);
1734         return false;
1735     }
1736
1737     aloop = ast_loop_new(ctx, NULL, cond, NULL, NULL, ontrue);
1738     *out = (ast_expression*)aloop;
1739     return true;
1740 }
1741
1742 static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
1743 {
1744     ast_loop *aloop;
1745     ast_expression *cond, *ontrue;
1746
1747     lex_ctx ctx = parser_ctx(parser);
1748
1749     (void)block; /* not touching */
1750
1751     /* skip the 'do' and get the body */
1752     if (!parser_next(parser)) {
1753         parseerror(parser, "expected loop body");
1754         return false;
1755     }
1756     ontrue = parse_statement_or_block(parser);
1757     if (!ontrue)
1758         return false;
1759
1760     /* expect the "while" */
1761     if (parser->tok != TOKEN_KEYWORD ||
1762         strcmp(parser_tokval(parser), "while"))
1763     {
1764         parseerror(parser, "expected 'while' and condition");
1765         ast_delete(ontrue);
1766         return false;
1767     }
1768
1769     /* skip the 'while' and check for opening paren */
1770     if (!parser_next(parser) || parser->tok != '(') {
1771         parseerror(parser, "expected 'while' condition in parenthesis");
1772         ast_delete(ontrue);
1773         return false;
1774     }
1775     /* parse into the expression */
1776     if (!parser_next(parser)) {
1777         parseerror(parser, "expected 'while' condition after opening paren");
1778         ast_delete(ontrue);
1779         return false;
1780     }
1781     /* parse the condition */
1782     cond = parse_expression_leave(parser, false);
1783     if (!cond)
1784         return false;
1785     /* closing paren */
1786     if (parser->tok != ')') {
1787         parseerror(parser, "expected closing paren after 'while' condition");
1788         ast_delete(ontrue);
1789         ast_delete(cond);
1790         return false;
1791     }
1792     /* parse on */
1793     if (!parser_next(parser) || parser->tok != ';') {
1794         parseerror(parser, "expected semicolon after condition");
1795         ast_delete(ontrue);
1796         ast_delete(cond);
1797         return false;
1798     }
1799
1800     if (!parser_next(parser)) {
1801         parseerror(parser, "parse error");
1802         ast_delete(ontrue);
1803         ast_delete(cond);
1804         return false;
1805     }
1806
1807     aloop = ast_loop_new(ctx, NULL, NULL, cond, NULL, ontrue);
1808     *out = (ast_expression*)aloop;
1809     return true;
1810 }
1811
1812 static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
1813 {
1814     ast_loop *aloop;
1815     ast_expression *initexpr, *cond, *increment, *ontrue;
1816     bool   retval = true;
1817
1818     lex_ctx ctx = parser_ctx(parser);
1819
1820     parser_enterblock(parser);
1821
1822     initexpr  = NULL;
1823     cond      = NULL;
1824     increment = NULL;
1825     ontrue    = NULL;
1826
1827     /* skip the 'while' and check for opening paren */
1828     if (!parser_next(parser) || parser->tok != '(') {
1829         parseerror(parser, "expected 'for' expressions in parenthesis");
1830         goto onerr;
1831     }
1832     /* parse into the expression */
1833     if (!parser_next(parser)) {
1834         parseerror(parser, "expected 'for' initializer after opening paren");
1835         goto onerr;
1836     }
1837
1838     if (parser->tok == TOKEN_TYPENAME) {
1839         if (opts_standard != COMPILER_GMQCC) {
1840             if (parsewarning(parser, WARN_EXTENSIONS,
1841                              "current standard does not allow variable declarations in for-loop initializers"))
1842                 goto onerr;
1843         }
1844
1845         parseerror(parser, "TODO: assignment of new variables to be non-const");
1846         goto onerr;
1847         if (!parse_variable(parser, block, true, false))
1848             goto onerr;
1849     }
1850     else if (parser->tok != ';')
1851     {
1852         initexpr = parse_expression_leave(parser, false);
1853         if (!initexpr)
1854             goto onerr;
1855     }
1856
1857     /* move on to condition */
1858     if (parser->tok != ';') {
1859         parseerror(parser, "expected semicolon after for-loop initializer");
1860         goto onerr;
1861     }
1862     if (!parser_next(parser)) {
1863         parseerror(parser, "expected for-loop condition");
1864         goto onerr;
1865     }
1866
1867     /* parse the condition */
1868     if (parser->tok != ';') {
1869         cond = parse_expression_leave(parser, false);
1870         if (!cond)
1871             goto onerr;
1872     }
1873
1874     /* move on to incrementor */
1875     if (parser->tok != ';') {
1876         parseerror(parser, "expected semicolon after for-loop initializer");
1877         goto onerr;
1878     }
1879     if (!parser_next(parser)) {
1880         parseerror(parser, "expected for-loop condition");
1881         goto onerr;
1882     }
1883
1884     /* parse the incrementor */
1885     if (parser->tok != ')') {
1886         increment = parse_expression_leave(parser, false);
1887         if (!increment)
1888             goto onerr;
1889         if (!ast_istype(increment, ast_store) &&
1890             !ast_istype(increment, ast_call) &&
1891             !ast_istype(increment, ast_binstore))
1892         {
1893             if (genwarning(ast_ctx(increment), WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
1894                 goto onerr;
1895         }
1896     }
1897
1898     /* closing paren */
1899     if (parser->tok != ')') {
1900         parseerror(parser, "expected closing paren after 'for-loop' incrementor");
1901         goto onerr;
1902     }
1903     /* parse into the 'then' branch */
1904     if (!parser_next(parser)) {
1905         parseerror(parser, "expected for-loop body");
1906         goto onerr;
1907     }
1908     ontrue = parse_statement_or_block(parser);
1909     if (!ontrue) {
1910         goto onerr;
1911     }
1912
1913     aloop = ast_loop_new(ctx, initexpr, cond, NULL, increment, ontrue);
1914     *out = (ast_expression*)aloop;
1915
1916     if (!parser_leaveblock(parser))
1917         retval = false;
1918     return retval;
1919 onerr:
1920     if (initexpr)  ast_delete(initexpr);
1921     if (cond)      ast_delete(cond);
1922     if (increment) ast_delete(increment);
1923     (void)!parser_leaveblock(parser);
1924     return false;
1925 }
1926
1927 static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
1928 {
1929     ast_expression *exp = NULL;
1930     ast_return     *ret = NULL;
1931     ast_value      *expected = parser->function->vtype;
1932
1933     (void)block; /* not touching */
1934
1935     if (!parser_next(parser)) {
1936         parseerror(parser, "expected return expression");
1937         return false;
1938     }
1939
1940     if (parser->tok != ';') {
1941         exp = parse_expression(parser, false);
1942         if (!exp)
1943             return false;
1944
1945         if (exp->expression.vtype != expected->expression.next->expression.vtype) {
1946             parseerror(parser, "return with invalid expression");
1947         }
1948
1949         ret = ast_return_new(exp->expression.node.context, exp);
1950         if (!ret) {
1951             ast_delete(exp);
1952             return false;
1953         }
1954     } else {
1955         if (!parser_next(parser))
1956             parseerror(parser, "parse error");
1957         if (expected->expression.next->expression.vtype != TYPE_VOID) {
1958             if (opts_standard != COMPILER_GMQCC)
1959                 (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
1960             else
1961                 parseerror(parser, "return without value");
1962         }
1963         ret = ast_return_new(parser_ctx(parser), NULL);
1964     }
1965     *out = (ast_expression*)ret;
1966     return true;
1967 }
1968
1969 static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
1970 {
1971     lex_ctx ctx = parser_ctx(parser);
1972
1973     (void)block; /* not touching */
1974
1975     if (!parser_next(parser) || parser->tok != ';') {
1976         parseerror(parser, "expected semicolon");
1977         return false;
1978     }
1979
1980     if (!parser_next(parser))
1981         parseerror(parser, "parse error");
1982
1983     *out = (ast_expression*)ast_breakcont_new(ctx, is_continue);
1984     return true;
1985 }
1986
1987 static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
1988 {
1989     ast_expression *operand;
1990     ast_value      *opval;
1991     ast_switch     *switchnode;
1992     ast_switch_case swcase;
1993
1994     lex_ctx ctx = parser_ctx(parser);
1995
1996     (void)block; /* not touching */
1997
1998     /* parse over the opening paren */
1999     if (!parser_next(parser) || parser->tok != '(') {
2000         parseerror(parser, "expected switch operand in parenthesis");
2001         return false;
2002     }
2003
2004     /* parse into the expression */
2005     if (!parser_next(parser)) {
2006         parseerror(parser, "expected switch operand");
2007         return false;
2008     }
2009     /* parse the operand */
2010     operand = parse_expression_leave(parser, false);
2011     if (!operand)
2012         return false;
2013
2014     if (!OPTS_FLAG(RELAXED_SWITCH)) {
2015         opval = (ast_value*)operand;
2016         if (!ast_istype(operand, ast_value) || !opval->isconst) {
2017             parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
2018             ast_unref(operand);
2019             return false;
2020         }
2021     }
2022
2023     switchnode = ast_switch_new(ctx, operand);
2024
2025     /* closing paren */
2026     if (parser->tok != ')') {
2027         ast_delete(switchnode);
2028         parseerror(parser, "expected closing paren after 'switch' operand");
2029         return false;
2030     }
2031
2032     /* parse over the opening paren */
2033     if (!parser_next(parser) || parser->tok != '{') {
2034         ast_delete(switchnode);
2035         parseerror(parser, "expected list of cases");
2036         return false;
2037     }
2038
2039     if (!parser_next(parser)) {
2040         ast_delete(switchnode);
2041         parseerror(parser, "expected 'case' or 'default'");
2042         return false;
2043     }
2044
2045     /* case list! */
2046     while (parser->tok != '}') {
2047         ast_block *caseblock;
2048
2049         if (parser->tok != TOKEN_KEYWORD) {
2050             ast_delete(switchnode);
2051             parseerror(parser, "expected 'case' or 'default'");
2052             return false;
2053         }
2054         if (!strcmp(parser_tokval(parser), "case")) {
2055             if (!parser_next(parser)) {
2056                 ast_delete(switchnode);
2057                 parseerror(parser, "expected expression for case");
2058                 return false;
2059             }
2060             swcase.value = parse_expression_leave(parser, false);
2061             if (!swcase.value) {
2062                 ast_delete(switchnode);
2063                 parseerror(parser, "expected expression for case");
2064                 return false;
2065             }
2066         }
2067         else if (!strcmp(parser_tokval(parser), "default")) {
2068             swcase.value = NULL;
2069             if (!parser_next(parser)) {
2070                 ast_delete(switchnode);
2071                 parseerror(parser, "expected colon");
2072                 return false;
2073             }
2074         }
2075
2076         /* Now the colon and body */
2077         if (parser->tok != ':') {
2078             if (swcase.value) ast_unref(swcase.value);
2079             ast_delete(switchnode);
2080             parseerror(parser, "expected colon");
2081             return false;
2082         }
2083
2084         if (!parser_next(parser)) {
2085             if (swcase.value) ast_unref(swcase.value);
2086             ast_delete(switchnode);
2087             parseerror(parser, "expected statements or case");
2088             return false;
2089         }
2090         caseblock = ast_block_new(parser_ctx(parser));
2091         if (!caseblock) {
2092             if (swcase.value) ast_unref(swcase.value);
2093             ast_delete(switchnode);
2094             return false;
2095         }
2096         swcase.code = (ast_expression*)caseblock;
2097         vec_push(switchnode->cases, swcase);
2098         while (true) {
2099             ast_expression *expr;
2100             if (parser->tok == '}')
2101                 break;
2102             if (parser->tok == TOKEN_KEYWORD) {
2103                 if (!strcmp(parser_tokval(parser), "case") ||
2104                     !strcmp(parser_tokval(parser), "default"))
2105                 {
2106                     break;
2107                 }
2108             }
2109             if (!parse_statement(parser, caseblock, &expr, true)) {
2110                 ast_delete(switchnode);
2111                 return false;
2112             }
2113             if (!expr)
2114                 continue;
2115             vec_push(caseblock->exprs, expr);
2116         }
2117     }
2118
2119     /* closing paren */
2120     if (parser->tok != '}') {
2121         ast_delete(switchnode);
2122         parseerror(parser, "expected closing paren of case list");
2123         return false;
2124     }
2125     if (!parser_next(parser)) {
2126         ast_delete(switchnode);
2127         parseerror(parser, "parse error after switch");
2128         return false;
2129     }
2130     *out = (ast_expression*)switchnode;
2131     return true;
2132 }
2133
2134 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
2135 {
2136     if (parser->tok == TOKEN_TYPENAME || parser->tok == '.')
2137     {
2138         /* local variable */
2139         if (!block) {
2140             parseerror(parser, "cannot declare a variable from here");
2141             return false;
2142         }
2143         if (opts_standard == COMPILER_QCC) {
2144             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
2145                 return false;
2146         }
2147         if (!parse_variable(parser, block, false, false))
2148             return false;
2149         *out = NULL;
2150         return true;
2151     }
2152     else if (parser->tok == TOKEN_KEYWORD)
2153     {
2154         if (!strcmp(parser_tokval(parser), "local"))
2155         {
2156             if (!block) {
2157                 parseerror(parser, "cannot declare a local variable here");
2158                 return false;
2159             }
2160             if (!parser_next(parser)) {
2161                 parseerror(parser, "expected variable declaration");
2162                 return false;
2163             }
2164             if (!parse_variable(parser, block, true, false))
2165                 return false;
2166             *out = NULL;
2167             return true;
2168         }
2169         else if (!strcmp(parser_tokval(parser), "return"))
2170         {
2171             return parse_return(parser, block, out);
2172         }
2173         else if (!strcmp(parser_tokval(parser), "if"))
2174         {
2175             return parse_if(parser, block, out);
2176         }
2177         else if (!strcmp(parser_tokval(parser), "while"))
2178         {
2179             return parse_while(parser, block, out);
2180         }
2181         else if (!strcmp(parser_tokval(parser), "do"))
2182         {
2183             return parse_dowhile(parser, block, out);
2184         }
2185         else if (!strcmp(parser_tokval(parser), "for"))
2186         {
2187             if (opts_standard == COMPILER_QCC) {
2188                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
2189                     return false;
2190             }
2191             return parse_for(parser, block, out);
2192         }
2193         else if (!strcmp(parser_tokval(parser), "break"))
2194         {
2195             return parse_break_continue(parser, block, out, false);
2196         }
2197         else if (!strcmp(parser_tokval(parser), "continue"))
2198         {
2199             return parse_break_continue(parser, block, out, true);
2200         }
2201         else if (!strcmp(parser_tokval(parser), "switch"))
2202         {
2203             return parse_switch(parser, block, out);
2204         }
2205         else if (!strcmp(parser_tokval(parser), "case") ||
2206                  !strcmp(parser_tokval(parser), "default"))
2207         {
2208             if (!allow_cases) {
2209                 parseerror(parser, "unexpected 'case' label");
2210                 return false;
2211             }
2212             return true;
2213         }
2214         parseerror(parser, "Unexpected keyword");
2215         return false;
2216     }
2217     else if (parser->tok == '{')
2218     {
2219         ast_block *inner;
2220         inner = parse_block(parser, false);
2221         if (!inner)
2222             return false;
2223         *out = (ast_expression*)inner;
2224         return true;
2225     }
2226     else
2227     {
2228         ast_expression *exp = parse_expression(parser, false);
2229         if (!exp)
2230             return false;
2231         *out = exp;
2232         if (!ast_istype(exp, ast_store) &&
2233             !ast_istype(exp, ast_call) &&
2234             !ast_istype(exp, ast_binstore))
2235         {
2236             if (genwarning(ast_ctx(exp), WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
2237                 return false;
2238         }
2239         return true;
2240     }
2241 }
2242
2243 static bool parse_block_into(parser_t *parser, ast_block *block, bool warnreturn)
2244 {
2245     bool   retval = true;
2246
2247     parser_enterblock(parser);
2248
2249     if (!parser_next(parser)) { /* skip the '{' */
2250         parseerror(parser, "expected function body");
2251         goto cleanup;
2252     }
2253
2254     while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
2255     {
2256         ast_expression *expr;
2257         if (parser->tok == '}')
2258             break;
2259
2260         if (!parse_statement(parser, block, &expr, false)) {
2261             /* parseerror(parser, "parse error"); */
2262             block = NULL;
2263             goto cleanup;
2264         }
2265         if (!expr)
2266             continue;
2267         vec_push(block->exprs, expr);
2268     }
2269
2270     if (parser->tok != '}') {
2271         block = NULL;
2272     } else {
2273         if (warnreturn && parser->function->vtype->expression.next->expression.vtype != TYPE_VOID)
2274         {
2275             if (!vec_size(block->exprs) ||
2276                 !ast_istype(vec_last(block->exprs), ast_return))
2277             {
2278                 if (parsewarning(parser, WARN_MISSING_RETURN_VALUES, "control reaches end of non-void function")) {
2279                     block = NULL;
2280                     goto cleanup;
2281                 }
2282             }
2283         }
2284         (void)parser_next(parser);
2285     }
2286
2287 cleanup:
2288     if (!parser_leaveblock(parser))
2289         retval = false;
2290     return !!block;
2291 }
2292
2293 static ast_block* parse_block(parser_t *parser, bool warnreturn)
2294 {
2295     ast_block *block;
2296     block = ast_block_new(parser_ctx(parser));
2297     if (!block)
2298         return NULL;
2299     if (!parse_block_into(parser, block, warnreturn)) {
2300         ast_block_delete(block);
2301         return NULL;
2302     }
2303     return block;
2304 }
2305
2306 static ast_expression* parse_statement_or_block(parser_t *parser)
2307 {
2308     ast_expression *expr = NULL;
2309     if (parser->tok == '{')
2310         return (ast_expression*)parse_block(parser, false);
2311     if (!parse_statement(parser, NULL, &expr, false))
2312         return NULL;
2313     return expr;
2314 }
2315
2316 static bool create_vector_members(ast_value *var, ast_member **me)
2317 {
2318     size_t i;
2319     size_t len = strlen(var->name);
2320
2321     for (i = 0; i < 3; ++i) {
2322         char *name = mem_a(len+3);
2323         memcpy(name, var->name, len);
2324         name[len+0] = '_';
2325         name[len+1] = 'x'+i;
2326         name[len+2] = 0;
2327         me[i] = ast_member_new(ast_ctx(var), (ast_expression*)var, i, name);
2328         mem_d(name);
2329         if (!me[i])
2330             break;
2331     }
2332     if (i == 3)
2333         return true;
2334
2335     /* unroll */
2336     do { ast_member_delete(me[--i]); } while(i);
2337     return false;
2338 }
2339
2340 static bool parse_function_body(parser_t *parser, ast_value *var)
2341 {
2342     ast_block      *block = NULL;
2343     ast_function   *func;
2344     ast_function   *old;
2345     size_t          parami;
2346
2347     ast_expression *framenum  = NULL;
2348     ast_expression *nextthink = NULL;
2349     /* None of the following have to be deleted */
2350     ast_expression *fld_think = NULL, *fld_nextthink = NULL, *fld_frame = NULL;
2351     ast_expression *gbl_time = NULL, *gbl_self = NULL;
2352     bool            has_frame_think;
2353
2354     bool retval = true;
2355
2356     has_frame_think = false;
2357     old = parser->function;
2358
2359     if (var->expression.variadic) {
2360         if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
2361                          "variadic function with implementation will not be able to access additional parameters"))
2362         {
2363             return false;
2364         }
2365     }
2366
2367     if (parser->tok == '[') {
2368         /* got a frame definition: [ framenum, nextthink ]
2369          * this translates to:
2370          * self.frame = framenum;
2371          * self.nextthink = time + 0.1;
2372          * self.think = nextthink;
2373          */
2374         nextthink = NULL;
2375
2376         fld_think     = parser_find_field(parser, "think");
2377         fld_nextthink = parser_find_field(parser, "nextthink");
2378         fld_frame     = parser_find_field(parser, "frame");
2379         if (!fld_think || !fld_nextthink || !fld_frame) {
2380             parseerror(parser, "cannot use [frame,think] notation without the required fields");
2381             parseerror(parser, "please declare the following entityfields: `frame`, `think`, `nextthink`");
2382             return false;
2383         }
2384         gbl_time      = parser_find_global(parser, "time");
2385         gbl_self      = parser_find_global(parser, "self");
2386         if (!gbl_time || !gbl_self) {
2387             parseerror(parser, "cannot use [frame,think] notation without the required globals");
2388             parseerror(parser, "please declare the following globals: `time`, `self`");
2389             return false;
2390         }
2391
2392         if (!parser_next(parser))
2393             return false;
2394
2395         framenum = parse_expression_leave(parser, true);
2396         if (!framenum) {
2397             parseerror(parser, "expected a framenumber constant in[frame,think] notation");
2398             return false;
2399         }
2400         if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->isconst) {
2401             ast_unref(framenum);
2402             parseerror(parser, "framenumber in [frame,think] notation must be a constant");
2403             return false;
2404         }
2405
2406         if (parser->tok != ',') {
2407             ast_unref(framenum);
2408             parseerror(parser, "expected comma after frame number in [frame,think] notation");
2409             parseerror(parser, "Got a %i\n", parser->tok);
2410             return false;
2411         }
2412
2413         if (!parser_next(parser)) {
2414             ast_unref(framenum);
2415             return false;
2416         }
2417
2418         if (parser->tok == TOKEN_IDENT && !parser_find_var(parser, parser_tokval(parser)))
2419         {
2420             /* qc allows the use of not-yet-declared functions here
2421              * - this automatically creates a prototype */
2422             ast_value      *thinkfunc;
2423             ast_expression *functype = fld_think->expression.next;
2424
2425             thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype);
2426             if (!thinkfunc || !ast_type_adopt(thinkfunc, functype)) {
2427                 ast_unref(framenum);
2428                 parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser));
2429                 return false;
2430             }
2431
2432             if (!parser_next(parser)) {
2433                 ast_unref(framenum);
2434                 ast_delete(thinkfunc);
2435                 return false;
2436             }
2437
2438             vec_push(parser->globals, (ast_expression*)thinkfunc);
2439             util_htset(parser->htglobals, thinkfunc->name, thinkfunc);
2440             nextthink = (ast_expression*)thinkfunc;
2441
2442         } else {
2443             nextthink = parse_expression_leave(parser, true);
2444             if (!nextthink) {
2445                 ast_unref(framenum);
2446                 parseerror(parser, "expected a think-function in [frame,think] notation");
2447                 return false;
2448             }
2449         }
2450
2451         if (!ast_istype(nextthink, ast_value)) {
2452             parseerror(parser, "think-function in [frame,think] notation must be a constant");
2453             retval = false;
2454         }
2455
2456         if (retval && parser->tok != ']') {
2457             parseerror(parser, "expected closing `]` for [frame,think] notation");
2458             retval = false;
2459         }
2460
2461         if (retval && !parser_next(parser)) {
2462             retval = false;
2463         }
2464
2465         if (retval && parser->tok != '{') {
2466             parseerror(parser, "a function body has to be declared after a [frame,think] declaration");
2467             retval = false;
2468         }
2469
2470         if (!retval) {
2471             ast_unref(nextthink);
2472             ast_unref(framenum);
2473             return false;
2474         }
2475
2476         has_frame_think = true;
2477     }
2478
2479     block = ast_block_new(parser_ctx(parser));
2480     if (!block) {
2481         parseerror(parser, "failed to allocate block");
2482         if (has_frame_think) {
2483             ast_unref(nextthink);
2484             ast_unref(framenum);
2485         }
2486         return false;
2487     }
2488
2489     if (has_frame_think) {
2490         lex_ctx ctx;
2491         ast_expression *self_frame;
2492         ast_expression *self_nextthink;
2493         ast_expression *self_think;
2494         ast_expression *time_plus_1;
2495         ast_store *store_frame;
2496         ast_store *store_nextthink;
2497         ast_store *store_think;
2498
2499         ctx = parser_ctx(parser);
2500         self_frame     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_frame);
2501         self_nextthink = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_nextthink);
2502         self_think     = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think);
2503
2504         time_plus_1    = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F,
2505                          gbl_time, (ast_expression*)parser_const_float(parser, 0.1));
2506
2507         if (!self_frame || !self_nextthink || !self_think || !time_plus_1) {
2508             if (self_frame)     ast_delete(self_frame);
2509             if (self_nextthink) ast_delete(self_nextthink);
2510             if (self_think)     ast_delete(self_think);
2511             if (time_plus_1)    ast_delete(time_plus_1);
2512             retval = false;
2513         }
2514
2515         if (retval)
2516         {
2517             store_frame     = ast_store_new(ctx, INSTR_STOREP_F,   self_frame,     framenum);
2518             store_nextthink = ast_store_new(ctx, INSTR_STOREP_F,   self_nextthink, time_plus_1);
2519             store_think     = ast_store_new(ctx, INSTR_STOREP_FNC, self_think,     nextthink);
2520
2521             if (!store_frame) {
2522                 ast_delete(self_frame);
2523                 retval = false;
2524             }
2525             if (!store_nextthink) {
2526                 ast_delete(self_nextthink);
2527                 retval = false;
2528             }
2529             if (!store_think) {
2530                 ast_delete(self_think);
2531                 retval = false;
2532             }
2533             if (!retval) {
2534                 if (store_frame)     ast_delete(store_frame);
2535                 if (store_nextthink) ast_delete(store_nextthink);
2536                 if (store_think)     ast_delete(store_think);
2537                 retval = false;
2538             }
2539             vec_push(block->exprs, (ast_expression*)store_frame);
2540             vec_push(block->exprs, (ast_expression*)store_nextthink);
2541             vec_push(block->exprs, (ast_expression*)store_think);
2542         }
2543
2544         if (!retval) {
2545             parseerror(parser, "failed to generate code for [frame,think]");
2546             ast_unref(nextthink);
2547             ast_unref(framenum);
2548             ast_delete(block);
2549             return false;
2550         }
2551     }
2552
2553     parser_enterblock(parser);
2554
2555     for (parami = 0; parami < vec_size(var->expression.params); ++parami) {
2556         size_t     e;
2557         ast_value *param = var->expression.params[parami];
2558         ast_member *me[3];
2559
2560         if (param->expression.vtype != TYPE_VECTOR &&
2561             (param->expression.vtype != TYPE_FIELD ||
2562              param->expression.next->expression.vtype != TYPE_VECTOR))
2563         {
2564             continue;
2565         }
2566
2567         if (!create_vector_members(param, me)) {
2568             ast_block_delete(block);
2569             return false;
2570         }
2571
2572         for (e = 0; e < 3; ++e) {
2573             parser_addlocal(parser, me[e]->name, (ast_expression*)me[e]);
2574             ast_block_collect(block, (ast_expression*)me[e]);
2575         }
2576     }
2577
2578     func = ast_function_new(ast_ctx(var), var->name, var);
2579     if (!func) {
2580         parseerror(parser, "failed to allocate function for `%s`", var->name);
2581         ast_block_delete(block);
2582         goto enderr;
2583     }
2584     vec_push(parser->functions, func);
2585
2586     parser->function = func;
2587     if (!parse_block_into(parser, block, true)) {
2588         ast_block_delete(block);
2589         goto enderrfn;
2590     }
2591
2592     vec_push(func->blocks, block);
2593
2594     parser->function = old;
2595     if (!parser_leaveblock(parser))
2596         retval = false;
2597     if (vec_size(parser->variables) != PARSER_HT_LOCALS) {
2598         parseerror(parser, "internal error: local scopes left");
2599         retval = false;
2600     }
2601
2602     if (parser->tok == ';')
2603         return parser_next(parser);
2604     else if (opts_standard == COMPILER_QCC)
2605         parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
2606     return retval;
2607
2608 enderrfn:
2609     vec_pop(parser->functions);
2610     ast_function_delete(func);
2611     var->constval.vfunc = NULL;
2612
2613 enderr:
2614     (void)!parser_leaveblock(parser);
2615     parser->function = old;
2616     return false;
2617 }
2618
2619 static ast_expression *array_accessor_split(
2620     parser_t  *parser,
2621     ast_value *array,
2622     ast_value *index,
2623     size_t     middle,
2624     ast_expression *left,
2625     ast_expression *right
2626     )
2627 {
2628     ast_ifthen *ifthen;
2629     ast_binary *cmp;
2630
2631     lex_ctx ctx = ast_ctx(array);
2632
2633     if (!left || !right) {
2634         if (left)  ast_delete(left);
2635         if (right) ast_delete(right);
2636         return NULL;
2637     }
2638
2639     cmp = ast_binary_new(ctx, INSTR_LT,
2640                          (ast_expression*)index,
2641                          (ast_expression*)parser_const_float(parser, middle));
2642     if (!cmp) {
2643         ast_delete(left);
2644         ast_delete(right);
2645         parseerror(parser, "internal error: failed to create comparison for array setter");
2646         return NULL;
2647     }
2648
2649     ifthen = ast_ifthen_new(ctx, (ast_expression*)cmp, left, right);
2650     if (!ifthen) {
2651         ast_delete(cmp); /* will delete left and right */
2652         parseerror(parser, "internal error: failed to create conditional jump for array setter");
2653         return NULL;
2654     }
2655
2656     return (ast_expression*)ifthen;
2657 }
2658
2659 static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast_value *index, ast_value *value, size_t from, size_t afterend)
2660 {
2661     lex_ctx ctx = ast_ctx(array);
2662
2663     if (from+1 == afterend) {
2664         /* set this value */
2665         ast_block       *block;
2666         ast_return      *ret;
2667         ast_array_index *subscript;
2668         ast_store       *st;
2669         int assignop = type_store_instr[value->expression.vtype];
2670
2671         if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
2672             assignop = INSTR_STORE_V;
2673
2674         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
2675         if (!subscript)
2676             return NULL;
2677
2678         st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value);
2679         if (!st) {
2680             ast_delete(subscript);
2681             return NULL;
2682         }
2683
2684         block = ast_block_new(ctx);
2685         if (!block) {
2686             ast_delete(st);
2687             return NULL;
2688         }
2689
2690         vec_push(block->exprs, (ast_expression*)st);
2691
2692         ret = ast_return_new(ctx, NULL);
2693         if (!ret) {
2694             ast_delete(block);
2695             return NULL;
2696         }
2697
2698         vec_push(block->exprs, (ast_expression*)ret);
2699
2700         return (ast_expression*)block;
2701     } else {
2702         ast_expression *left, *right;
2703         size_t diff = afterend - from;
2704         size_t middle = from + diff/2;
2705         left  = array_setter_node(parser, array, index, value, from, middle);
2706         right = array_setter_node(parser, array, index, value, middle, afterend);
2707         return array_accessor_split(parser, array, index, middle, left, right);
2708     }
2709 }
2710
2711 static ast_expression *array_field_setter_node(
2712     parser_t  *parser,
2713     ast_value *array,
2714     ast_value *entity,
2715     ast_value *index,
2716     ast_value *value,
2717     size_t     from,
2718     size_t     afterend)
2719 {
2720     lex_ctx ctx = ast_ctx(array);
2721
2722     if (from+1 == afterend) {
2723         /* set this value */
2724         ast_block       *block;
2725         ast_return      *ret;
2726         ast_entfield    *entfield;
2727         ast_array_index *subscript;
2728         ast_store       *st;
2729         int assignop = type_storep_instr[value->expression.vtype];
2730
2731         if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR)
2732             assignop = INSTR_STOREP_V;
2733
2734         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
2735         if (!subscript)
2736             return NULL;
2737
2738         entfield = ast_entfield_new_force(ctx,
2739                                           (ast_expression*)entity,
2740                                           (ast_expression*)subscript,
2741                                           (ast_expression*)subscript);
2742         if (!entfield) {
2743             ast_delete(subscript);
2744             return NULL;
2745         }
2746
2747         st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value);
2748         if (!st) {
2749             ast_delete(entfield);
2750             return NULL;
2751         }
2752
2753         block = ast_block_new(ctx);
2754         if (!block) {
2755             ast_delete(st);
2756             return NULL;
2757         }
2758
2759         vec_push(block->exprs, (ast_expression*)st);
2760
2761         ret = ast_return_new(ctx, NULL);
2762         if (!ret) {
2763             ast_delete(block);
2764             return NULL;
2765         }
2766
2767         vec_push(block->exprs, (ast_expression*)ret);
2768
2769         return (ast_expression*)block;
2770     } else {
2771         ast_expression *left, *right;
2772         size_t diff = afterend - from;
2773         size_t middle = from + diff/2;
2774         left  = array_field_setter_node(parser, array, entity, index, value, from, middle);
2775         right = array_field_setter_node(parser, array, entity, index, value, middle, afterend);
2776         return array_accessor_split(parser, array, index, middle, left, right);
2777     }
2778 }
2779
2780 static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast_value *index, size_t from, size_t afterend)
2781 {
2782     lex_ctx ctx = ast_ctx(array);
2783
2784     if (from+1 == afterend) {
2785         ast_return      *ret;
2786         ast_array_index *subscript;
2787
2788         subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser_const_float(parser, from));
2789         if (!subscript)
2790             return NULL;
2791
2792         ret = ast_return_new(ctx, (ast_expression*)subscript);
2793         if (!ret) {
2794             ast_delete(subscript);
2795             return NULL;
2796         }
2797
2798         return (ast_expression*)ret;
2799     } else {
2800         ast_expression *left, *right;
2801         size_t diff = afterend - from;
2802         size_t middle = from + diff/2;
2803         left  = array_getter_node(parser, array, index, from, middle);
2804         right = array_getter_node(parser, array, index, middle, afterend);
2805         return array_accessor_split(parser, array, index, middle, left, right);
2806     }
2807 }
2808
2809 static bool parser_create_array_accessor(parser_t *parser, ast_value *array, const char *funcname, ast_value **out)
2810 {
2811     ast_function   *func = NULL;
2812     ast_value      *fval = NULL;
2813     ast_block      *body = NULL;
2814
2815     fval = ast_value_new(ast_ctx(array), funcname, TYPE_FUNCTION);
2816     if (!fval) {
2817         parseerror(parser, "failed to create accessor function value");
2818         return false;
2819     }
2820
2821     func = ast_function_new(ast_ctx(array), funcname, fval);
2822     if (!func) {
2823         ast_delete(fval);
2824         parseerror(parser, "failed to create accessor function node");
2825         return false;
2826     }
2827
2828     body = ast_block_new(ast_ctx(array));
2829     if (!body) {
2830         parseerror(parser, "failed to create block for array accessor");
2831         ast_delete(fval);
2832         ast_delete(func);
2833         return false;
2834     }
2835
2836     vec_push(func->blocks, body);
2837     *out = fval;
2838
2839     vec_push(parser->accessors, fval);
2840
2841     return true;
2842 }
2843
2844 static bool parser_create_array_setter(parser_t *parser, ast_value *array, const char *funcname)
2845 {
2846     ast_expression *root = NULL;
2847     ast_value      *index = NULL;
2848     ast_value      *value = NULL;
2849     ast_function   *func;
2850     ast_value      *fval;
2851
2852     if (!ast_istype(array->expression.next, ast_value)) {
2853         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
2854         return false;
2855     }
2856
2857     if (!parser_create_array_accessor(parser, array, funcname, &fval))
2858         return false;
2859     func = fval->constval.vfunc;
2860     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
2861
2862     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
2863     value = ast_value_copy((ast_value*)array->expression.next);
2864
2865     if (!index || !value) {
2866         parseerror(parser, "failed to create locals for array accessor");
2867         goto cleanup;
2868     }
2869     (void)!ast_value_set_name(value, "value"); /* not important */
2870     vec_push(fval->expression.params, index);
2871     vec_push(fval->expression.params, value);
2872
2873     root = array_setter_node(parser, array, index, value, 0, array->expression.count);
2874     if (!root) {
2875         parseerror(parser, "failed to build accessor search tree");
2876         goto cleanup;
2877     }
2878
2879     vec_push(func->blocks[0]->exprs, root);
2880     array->setter = fval;
2881     return true;
2882 cleanup:
2883     if (index) ast_delete(index);
2884     if (value) ast_delete(value);
2885     if (root)  ast_delete(root);
2886     ast_delete(func);
2887     ast_delete(fval);
2888     return false;
2889 }
2890
2891 static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, const char *funcname)
2892 {
2893     ast_expression *root = NULL;
2894     ast_value      *entity = NULL;
2895     ast_value      *index = NULL;
2896     ast_value      *value = NULL;
2897     ast_function   *func;
2898     ast_value      *fval;
2899
2900     if (!ast_istype(array->expression.next, ast_value)) {
2901         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
2902         return false;
2903     }
2904
2905     if (!parser_create_array_accessor(parser, array, funcname, &fval))
2906         return false;
2907     func = fval->constval.vfunc;
2908     fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "<void>", TYPE_VOID);
2909
2910     entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY);
2911     index  = ast_value_new(ast_ctx(array), "index",  TYPE_FLOAT);
2912     value  = ast_value_copy((ast_value*)array->expression.next);
2913     if (!entity || !index || !value) {
2914         parseerror(parser, "failed to create locals for array accessor");
2915         goto cleanup;
2916     }
2917     (void)!ast_value_set_name(value, "value"); /* not important */
2918     vec_push(fval->expression.params, entity);
2919     vec_push(fval->expression.params, index);
2920     vec_push(fval->expression.params, value);
2921
2922     root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count);
2923     if (!root) {
2924         parseerror(parser, "failed to build accessor search tree");
2925         goto cleanup;
2926     }
2927
2928     vec_push(func->blocks[0]->exprs, root);
2929     array->setter = fval;
2930     return true;
2931 cleanup:
2932     if (entity) ast_delete(entity);
2933     if (index)  ast_delete(index);
2934     if (value)  ast_delete(value);
2935     if (root)   ast_delete(root);
2936     ast_delete(func);
2937     ast_delete(fval);
2938     return false;
2939 }
2940
2941 static bool parser_create_array_getter(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname)
2942 {
2943     ast_expression *root = NULL;
2944     ast_value      *index = NULL;
2945     ast_value      *fval;
2946     ast_function   *func;
2947
2948     /* NOTE: checking array->expression.next rather than elemtype since
2949      * for fields elemtype is a temporary fieldtype.
2950      */
2951     if (!ast_istype(array->expression.next, ast_value)) {
2952         parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type");
2953         return false;
2954     }
2955
2956     if (!parser_create_array_accessor(parser, array, funcname, &fval))
2957         return false;
2958     func = fval->constval.vfunc;
2959     fval->expression.next = ast_type_copy(ast_ctx(array), elemtype);
2960
2961     index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT);
2962
2963     if (!index) {
2964         parseerror(parser, "failed to create locals for array accessor");
2965         goto cleanup;
2966     }
2967     vec_push(fval->expression.params, index);
2968
2969     root = array_getter_node(parser, array, index, 0, array->expression.count);
2970     if (!root) {
2971         parseerror(parser, "failed to build accessor search tree");
2972         goto cleanup;
2973     }
2974
2975     vec_push(func->blocks[0]->exprs, root);
2976     array->getter = fval;
2977     return true;
2978 cleanup:
2979     if (index) ast_delete(index);
2980     if (root)  ast_delete(root);
2981     ast_delete(func);
2982     ast_delete(fval);
2983     return false;
2984 }
2985
2986 static ast_value *parse_typename(parser_t *parser, ast_value **storebase);
2987 static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
2988 {
2989     lex_ctx     ctx;
2990     size_t      i;
2991     ast_value **params;
2992     ast_value  *param;
2993     ast_value  *fval;
2994     bool        first = true;
2995     bool        variadic = false;
2996
2997     ctx = parser_ctx(parser);
2998
2999     /* for the sake of less code we parse-in in this function */
3000     if (!parser_next(parser)) {
3001         parseerror(parser, "expected parameter list");
3002         return NULL;
3003     }
3004
3005     params = NULL;
3006
3007     /* parse variables until we hit a closing paren */
3008     while (parser->tok != ')') {
3009         if (!first) {
3010             /* there must be commas between them */
3011             if (parser->tok != ',') {
3012                 parseerror(parser, "expected comma or end of parameter list");
3013                 goto on_error;
3014             }
3015             if (!parser_next(parser)) {
3016                 parseerror(parser, "expected parameter");
3017                 goto on_error;
3018             }
3019         }
3020         first = false;
3021
3022         if (parser->tok == TOKEN_DOTS) {
3023             /* '...' indicates a varargs function */
3024             variadic = true;
3025             if (!parser_next(parser)) {
3026                 parseerror(parser, "expected parameter");
3027                 return NULL;
3028             }
3029             if (parser->tok != ')') {
3030                 parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
3031                 goto on_error;
3032             }
3033         }
3034         else
3035         {
3036             /* for anything else just parse a typename */
3037             param = parse_typename(parser, NULL);
3038             if (!param)
3039                 goto on_error;
3040             vec_push(params, param);
3041             if (param->expression.vtype >= TYPE_VARIANT) {
3042                 char typename[1024];
3043                 ast_type_to_string((ast_expression*)param, typename, sizeof(typename));
3044                 parseerror(parser, "type not supported as part of a parameter list: %s", typename);
3045                 goto on_error;
3046             }
3047         }
3048     }
3049
3050     /* sanity check */
3051     if (vec_size(params) > 8 && opts_standard == COMPILER_QCC)
3052         (void)!parsewarning(parser, WARN_EXTENSIONS, "more than 8 parameters are not supported by this standard");
3053
3054     /* parse-out */
3055     if (!parser_next(parser)) {
3056         parseerror(parser, "parse error after typename");
3057         goto on_error;
3058     }
3059
3060     /* now turn 'var' into a function type */
3061     fval = ast_value_new(ctx, "<type()>", TYPE_FUNCTION);
3062     fval->expression.next     = (ast_expression*)var;
3063     fval->expression.variadic = variadic;
3064     var = fval;
3065
3066     var->expression.params = params;
3067     params = NULL;
3068
3069     return var;
3070
3071 on_error:
3072     ast_delete(var);
3073     for (i = 0; i < vec_size(params); ++i)
3074         ast_delete(params[i]);
3075     vec_free(params);
3076     return NULL;
3077 }
3078
3079 static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
3080 {
3081     ast_expression *cexp;
3082     ast_value      *cval, *tmp;
3083     lex_ctx ctx;
3084
3085     ctx = parser_ctx(parser);
3086
3087     if (!parser_next(parser)) {
3088         ast_delete(var);
3089         parseerror(parser, "expected array-size");
3090         return NULL;
3091     }
3092
3093     cexp = parse_expression_leave(parser, true);
3094
3095     if (!cexp || !ast_istype(cexp, ast_value)) {
3096         if (cexp)
3097             ast_unref(cexp);
3098         ast_delete(var);
3099         parseerror(parser, "expected array-size as constant positive integer");
3100         return NULL;
3101     }
3102     cval = (ast_value*)cexp;
3103
3104     tmp = ast_value_new(ctx, "<type[]>", TYPE_ARRAY);
3105     tmp->expression.next = (ast_expression*)var;
3106     var = tmp;
3107
3108     if (cval->expression.vtype == TYPE_INTEGER)
3109         tmp->expression.count = cval->constval.vint;
3110     else if (cval->expression.vtype == TYPE_FLOAT)
3111         tmp->expression.count = cval->constval.vfloat;
3112     else {
3113         ast_unref(cexp);
3114         ast_delete(var);
3115         parseerror(parser, "array-size must be a positive integer constant");
3116         return NULL;
3117     }
3118     ast_unref(cexp);
3119
3120     if (parser->tok != ']') {
3121         ast_delete(var);
3122         parseerror(parser, "expected ']' after array-size");
3123         return NULL;
3124     }
3125     if (!parser_next(parser)) {
3126         ast_delete(var);
3127         parseerror(parser, "error after parsing array size");
3128         return NULL;
3129     }
3130     return var;
3131 }
3132
3133 /* Parse a complete typename.
3134  * for single-variables (ie. function parameters or typedefs) storebase should be NULL
3135  * but when parsing variables separated by comma
3136  * 'storebase' should point to where the base-type should be kept.
3137  * The base type makes up every bit of type information which comes *before* the
3138  * variable name.
3139  *
3140  * The following will be parsed in its entirety:
3141  *     void() foo()
3142  * The 'basetype' in this case is 'void()'
3143  * and if there's a comma after it, say:
3144  *     void() foo(), bar
3145  * then the type-information 'void()' can be stored in 'storebase'
3146  */
3147 static ast_value *parse_typename(parser_t *parser, ast_value **storebase)
3148 {
3149     ast_value *var, *tmp;
3150     lex_ctx    ctx;
3151
3152     const char *name = NULL;
3153     bool        isfield  = false;
3154     bool        wasarray = false;
3155
3156     ctx = parser_ctx(parser);
3157
3158     /* types may start with a dot */
3159     if (parser->tok == '.') {
3160         isfield = true;
3161         /* if we parsed a dot we need a typename now */
3162         if (!parser_next(parser)) {
3163             parseerror(parser, "expected typename for field definition");
3164             return NULL;
3165         }
3166         if (parser->tok != TOKEN_TYPENAME) {
3167             parseerror(parser, "expected typename");
3168             return NULL;
3169         }
3170     }
3171
3172     /* generate the basic type value */
3173     var = ast_value_new(ctx, "<type>", parser_token(parser)->constval.t);
3174     /* do not yet turn into a field - remember:
3175      * .void() foo; is a field too
3176      * .void()() foo; is a function
3177      */
3178
3179     /* parse on */
3180     if (!parser_next(parser)) {
3181         ast_delete(var);
3182         parseerror(parser, "parse error after typename");
3183         return NULL;
3184     }
3185
3186     /* an opening paren now starts the parameter-list of a function
3187      * this is where original-QC has parameter lists.
3188      * We allow a single parameter list here.
3189      * Much like fteqcc we don't allow `float()() x`
3190      */
3191     if (parser->tok == '(') {
3192         var = parse_parameter_list(parser, var);
3193         if (!var)
3194             return NULL;
3195     }
3196
3197     /* store the base if requested */
3198     if (storebase) {
3199         *storebase = ast_value_copy(var);
3200         if (isfield) {
3201             tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
3202             tmp->expression.next = (ast_expression*)*storebase;
3203             *storebase = tmp;
3204         }
3205     }
3206
3207     /* there may be a name now */
3208     if (parser->tok == TOKEN_IDENT) {
3209         name = util_strdup(parser_tokval(parser));
3210         /* parse on */
3211         if (!parser_next(parser)) {
3212             ast_delete(var);
3213             parseerror(parser, "error after variable or field declaration");
3214             return NULL;
3215         }
3216     }
3217
3218     /* now this may be an array */
3219     if (parser->tok == '[') {
3220         wasarray = true;
3221         var = parse_arraysize(parser, var);
3222         if (!var)
3223             return NULL;
3224     }
3225
3226     /* This is the point where we can turn it into a field */
3227     if (isfield) {
3228         /* turn it into a field if desired */
3229         tmp = ast_value_new(ctx, "<type:f>", TYPE_FIELD);
3230         tmp->expression.next = (ast_expression*)var;
3231         var = tmp;
3232     }
3233
3234     /* now there may be function parens again */
3235     if (parser->tok == '(' && opts_standard == COMPILER_QCC)
3236         parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
3237     if (parser->tok == '(' && wasarray)
3238         parseerror(parser, "arrays as part of a return type is not supported");
3239     while (parser->tok == '(') {
3240         var = parse_parameter_list(parser, var);
3241         if (!var) {
3242             if (name)
3243                 mem_d((void*)name);
3244             ast_delete(var);
3245             return NULL;
3246         }
3247     }
3248
3249     /* finally name it */
3250     if (name) {
3251         if (!ast_value_set_name(var, name)) {
3252             ast_delete(var);
3253             parseerror(parser, "internal error: failed to set name");
3254             return NULL;
3255         }
3256         /* free the name, ast_value_set_name duplicates */
3257         mem_d((void*)name);
3258     }
3259
3260     return var;
3261 }
3262
3263 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, bool is_const)
3264 {
3265     ast_value *var;
3266     ast_value *proto;
3267     ast_expression *old;
3268     bool       was_end;
3269     size_t     i;
3270
3271     ast_value *basetype = NULL;
3272     bool      retval    = true;
3273     bool      isparam   = false;
3274     bool      isvector  = false;
3275     bool      cleanvar  = true;
3276     bool      wasarray  = false;
3277
3278     ast_member *me[3];
3279
3280     /* get the first complete variable */
3281     var = parse_typename(parser, &basetype);
3282     if (!var) {
3283         if (basetype)
3284             ast_delete(basetype);
3285         return false;
3286     }
3287
3288     while (true) {
3289         proto = NULL;
3290         wasarray = false;
3291
3292         /* Part 0: finish the type */
3293         if (parser->tok == '(') {
3294             if (opts_standard == COMPILER_QCC)
3295                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
3296             var = parse_parameter_list(parser, var);
3297             if (!var) {
3298                 retval = false;
3299                 goto cleanup;
3300             }
3301         }
3302         /* we only allow 1-dimensional arrays */
3303         if (parser->tok == '[') {
3304             wasarray = true;
3305             var = parse_arraysize(parser, var);
3306             if (!var) {
3307                 retval = false;
3308                 goto cleanup;
3309             }
3310         }
3311         if (parser->tok == '(' && wasarray) {
3312             parseerror(parser, "arrays as part of a return type is not supported");
3313             /* we'll still parse the type completely for now */
3314         }
3315         /* for functions returning functions */
3316         while (parser->tok == '(') {
3317             if (opts_standard == COMPILER_QCC)
3318                 parseerror(parser, "C-style function syntax is not allowed in -std=qcc");
3319             var = parse_parameter_list(parser, var);
3320             if (!var) {
3321                 retval = false;
3322                 goto cleanup;
3323             }
3324         }
3325
3326         /* Part 1:
3327          * check for validity: (end_sys_..., multiple-definitions, prototypes, ...)
3328          * Also: if there was a prototype, `var` will be deleted and set to `proto` which
3329          * is then filled with the previous definition and the parameter-names replaced.
3330          */
3331         if (!localblock) {
3332             /* Deal with end_sys_ vars */
3333             was_end = false;
3334             if (!strcmp(var->name, "end_sys_globals")) {
3335                 parser->crc_globals = vec_size(parser->globals);
3336                 was_end = true;
3337             }
3338             else if (!strcmp(var->name, "end_sys_fields")) {
3339                 parser->crc_fields = vec_size(parser->fields);
3340                 was_end = true;
3341             }
3342             if (was_end && var->expression.vtype == TYPE_FIELD) {
3343                 if (parsewarning(parser, WARN_END_SYS_FIELDS,
3344                                  "global '%s' hint should not be a field",
3345                                  parser_tokval(parser)))
3346                 {
3347                     retval = false;
3348                     goto cleanup;
3349                 }
3350             }
3351
3352             if (!nofields && var->expression.vtype == TYPE_FIELD)
3353             {
3354                 /* deal with field declarations */
3355                 old = parser_find_field(parser, var->name);
3356                 if (old) {
3357                     if (parsewarning(parser, WARN_FIELD_REDECLARED, "field `%s` already declared here: %s:%i",
3358                                      var->name, ast_ctx(old).file, (int)ast_ctx(old).line))
3359                     {
3360                         retval = false;
3361                         goto cleanup;
3362                     }
3363                     ast_delete(var);
3364                     var = NULL;
3365                     goto skipvar;
3366                     /*
3367                     parseerror(parser, "field `%s` already declared here: %s:%i",
3368                                var->name, ast_ctx(old).file, ast_ctx(old).line);
3369                     retval = false;
3370                     goto cleanup;
3371                     */
3372                 }
3373                 if (opts_standard == COMPILER_QCC &&
3374                     (old = parser_find_global(parser, var->name)))
3375                 {
3376                     parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
3377                     parseerror(parser, "field `%s` already declared here: %s:%i",
3378                                var->name, ast_ctx(old).file, ast_ctx(old).line);
3379                     retval = false;
3380                     goto cleanup;
3381                 }
3382             }
3383             else
3384             {
3385                 /* deal with other globals */
3386                 old = parser_find_global(parser, var->name);
3387                 if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
3388                 {
3389                     /* This is a function which had a prototype */
3390                     if (!ast_istype(old, ast_value)) {
3391                         parseerror(parser, "internal error: prototype is not an ast_value");
3392                         retval = false;
3393                         goto cleanup;
3394                     }
3395                     proto = (ast_value*)old;
3396                     if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) {
3397                         parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i",
3398                                    proto->name,
3399                                    ast_ctx(proto).file, ast_ctx(proto).line);
3400                         retval = false;
3401                         goto cleanup;
3402                     }
3403                     /* we need the new parameter-names */
3404                     for (i = 0; i < vec_size(proto->expression.params); ++i)
3405                         ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name);
3406                     ast_delete(var);
3407                     var = proto;
3408                 }
3409                 else
3410                 {
3411                     /* other globals */
3412                     if (old) {
3413                         if (opts_standard == COMPILER_GMQCC) {
3414                             parseerror(parser, "global `%s` already declared here: %s:%i",
3415                                        var->name, ast_ctx(old).file, ast_ctx(old).line);
3416                             retval = false;
3417                             goto cleanup;
3418                         } else {
3419                             if (parsewarning(parser, WARN_DOUBLE_DECLARATION,
3420                                              "global `%s` already declared here: %s:%i",
3421                                              var->name, ast_ctx(old).file, ast_ctx(old).line))
3422                             {
3423                                 retval = false;
3424                                 goto cleanup;
3425                             }
3426                         }
3427                     }
3428                     if (opts_standard == COMPILER_QCC &&
3429                         (old = parser_find_field(parser, var->name)))
3430                     {
3431                         parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
3432                         parseerror(parser, "global `%s` already declared here: %s:%i",
3433                                    var->name, ast_ctx(old).file, ast_ctx(old).line);
3434                         retval = false;
3435                         goto cleanup;
3436                     }
3437                 }
3438             }
3439         }
3440         else /* it's not a global */
3441         {
3442             old = parser_find_local(parser, var->name, vec_size(parser->variables)-1, &isparam);
3443             if (old && !isparam) {
3444                 parseerror(parser, "local `%s` already declared here: %s:%i",
3445                            var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
3446                 retval = false;
3447                 goto cleanup;
3448             }
3449             old = parser_find_local(parser, var->name, 0, &isparam);
3450             if (old && isparam) {
3451                 if (parsewarning(parser, WARN_LOCAL_SHADOWS,
3452                                  "local `%s` is shadowing a parameter", var->name))
3453                 {
3454                     parseerror(parser, "local `%s` already declared here: %s:%i",
3455                                var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
3456                     retval = false;
3457                     goto cleanup;
3458                 }
3459                 if (opts_standard != COMPILER_GMQCC) {
3460                     ast_delete(var);
3461                     var = NULL;
3462                     goto skipvar;
3463                 }
3464             }
3465         }
3466
3467         if (is_const)
3468             var->isconst = true;
3469
3470         /* Part 2:
3471          * Create the global/local, and deal with vector types.
3472          */
3473         if (!proto) {
3474             if (var->expression.vtype == TYPE_VECTOR)
3475                 isvector = true;
3476             else if (var->expression.vtype == TYPE_FIELD &&
3477                      var->expression.next->expression.vtype == TYPE_VECTOR)
3478                 isvector = true;
3479
3480             if (isvector) {
3481                 if (!create_vector_members(var, me)) {
3482                     retval = false;
3483                     goto cleanup;
3484                 }
3485             }
3486
3487             if (!localblock) {
3488                 /* deal with global variables, fields, functions */
3489                 if (!nofields && var->expression.vtype == TYPE_FIELD) {
3490                     vec_push(parser->fields, (ast_expression*)var);
3491                     util_htset(parser->htfields, var->name, var);
3492                     if (isvector) {
3493                         for (i = 0; i < 3; ++i) {
3494                             vec_push(parser->fields, (ast_expression*)me[i]);
3495                             util_htset(parser->htfields, me[i]->name, me[i]);
3496                         }
3497                     }
3498                 }
3499                 else {
3500                     vec_push(parser->globals, (ast_expression*)var);
3501                     util_htset(parser->htglobals, var->name, var);
3502                     if (isvector) {
3503                         for (i = 0; i < 3; ++i) {
3504                             vec_push(parser->globals, (ast_expression*)me[i]);
3505                             util_htset(parser->htglobals, me[i]->name, me[i]);
3506                         }
3507                     }
3508                 }
3509             } else {
3510                 vec_push(localblock->locals, var);
3511                 parser_addlocal(parser, var->name, (ast_expression*)var);
3512                 if (isvector) {
3513                     for (i = 0; i < 3; ++i) {
3514                         parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]);
3515                         ast_block_collect(localblock, (ast_expression*)me[i]);
3516                     }
3517                 }
3518             }
3519
3520             me[0] = me[1] = me[2] = NULL;
3521             cleanvar = false;
3522         }
3523         /* Part 2.2
3524          * deal with arrays
3525          */
3526         if (var->expression.vtype == TYPE_ARRAY) {
3527             char name[1024];
3528             snprintf(name, sizeof(name), "%s##SET", var->name);
3529             if (!parser_create_array_setter(parser, var, name))
3530                 goto cleanup;
3531             snprintf(name, sizeof(name), "%s##GET", var->name);
3532             if (!parser_create_array_getter(parser, var, var->expression.next, name))
3533                 goto cleanup;
3534         }
3535         else if (!localblock && !nofields &&
3536                  var->expression.vtype == TYPE_FIELD &&
3537                  var->expression.next->expression.vtype == TYPE_ARRAY)
3538         {
3539             char name[1024];
3540             ast_expression *telem;
3541             ast_value      *tfield;
3542             ast_value      *array = (ast_value*)var->expression.next;
3543
3544             if (!ast_istype(var->expression.next, ast_value)) {
3545                 parseerror(parser, "internal error: field element type must be an ast_value");
3546                 goto cleanup;
3547             }
3548
3549             snprintf(name, sizeof(name), "%s##SETF", var->name);
3550             if (!parser_create_array_field_setter(parser, array, name))
3551                 goto cleanup;
3552
3553             telem = ast_type_copy(ast_ctx(var), array->expression.next);
3554             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
3555             tfield->expression.next = telem;
3556             snprintf(name, sizeof(name), "%s##GETFP", var->name);
3557             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
3558                 ast_delete(tfield);
3559                 goto cleanup;
3560             }
3561             ast_delete(tfield);
3562         }
3563
3564 skipvar:
3565         if (parser->tok == ';') {
3566             ast_delete(basetype);
3567             if (!parser_next(parser)) {
3568                 parseerror(parser, "error after variable declaration");
3569                 return false;
3570             }
3571             return true;
3572         }
3573
3574         if (parser->tok == ',')
3575             goto another;
3576
3577         if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
3578             parseerror(parser, "missing comma or semicolon while parsing variables");
3579             break;
3580         }
3581
3582         if (localblock && opts_standard == COMPILER_QCC) {
3583             if (parsewarning(parser, WARN_LOCAL_CONSTANTS,
3584                              "initializing expression turns variable `%s` into a constant in this standard",
3585                              var->name) )
3586             {
3587                 break;
3588             }
3589         }
3590
3591         if (parser->tok != '{') {
3592             if (parser->tok != '=') {
3593                 parseerror(parser, "missing semicolon or initializer");
3594                 break;
3595             }
3596
3597             if (!parser_next(parser)) {
3598                 parseerror(parser, "error parsing initializer");
3599                 break;
3600             }
3601         }
3602         else if (opts_standard == COMPILER_QCC) {
3603             parseerror(parser, "expected '=' before function body in this standard");
3604         }
3605
3606         if (parser->tok == '#') {
3607             ast_function *func;
3608
3609             if (localblock) {
3610                 parseerror(parser, "cannot declare builtins within functions");
3611                 break;
3612             }
3613             if (var->expression.vtype != TYPE_FUNCTION) {
3614                 parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name);
3615                 break;
3616             }
3617             if (!parser_next(parser)) {
3618                 parseerror(parser, "expected builtin number");
3619                 break;
3620             }
3621             if (parser->tok != TOKEN_INTCONST) {
3622                 parseerror(parser, "builtin number must be an integer constant");
3623                 break;
3624             }
3625             if (parser_token(parser)->constval.i <= 0) {
3626                 parseerror(parser, "builtin number must be an integer greater than zero");
3627                 break;
3628             }
3629
3630             if (var->isconst) {
3631                 (void)!parsewarning(parser, WARN_DOUBLE_DECLARATION,
3632                                     "builtin `%s` has already been defined\n"
3633                                     " -> previous declaration here: %s:%i",
3634                                     var->name, ast_ctx(var).file, (int)ast_ctx(var).line);
3635             }
3636             else
3637             {
3638                 func = ast_function_new(ast_ctx(var), var->name, var);
3639                 if (!func) {
3640                     parseerror(parser, "failed to allocate function for `%s`", var->name);
3641                     break;
3642                 }
3643                 vec_push(parser->functions, func);
3644
3645                 func->builtin = -parser_token(parser)->constval.i;
3646             }
3647
3648             if (!parser_next(parser)) {
3649                 parseerror(parser, "expected comma or semicolon");
3650                 ast_function_delete(func);
3651                 var->constval.vfunc = NULL;
3652                 break;
3653             }
3654         }
3655         else if (parser->tok == '{' || parser->tok == '[')
3656         {
3657             if (localblock) {
3658                 parseerror(parser, "cannot declare functions within functions");
3659                 break;
3660             }
3661
3662             if (!parse_function_body(parser, var))
3663                 break;
3664             ast_delete(basetype);
3665             return true;
3666         } else {
3667             ast_expression *cexp;
3668             ast_value      *cval;
3669
3670             cexp = parse_expression_leave(parser, true);
3671             if (!cexp)
3672                 break;
3673
3674             if (!localblock) {
3675                 cval = (ast_value*)cexp;
3676                 if (!ast_istype(cval, ast_value) || !cval->isconst)
3677                     parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
3678                 else
3679                 {
3680                     var->isconst = true;
3681                     if (cval->expression.vtype == TYPE_STRING)
3682                         var->constval.vstring = parser_strdup(cval->constval.vstring);
3683                     else
3684                         memcpy(&var->constval, &cval->constval, sizeof(var->constval));
3685                     ast_unref(cval);
3686                 }
3687             } else {
3688                 shunt sy = { NULL, NULL };
3689                 vec_push(sy.out, syexp(ast_ctx(var), (ast_expression*)var));
3690                 vec_push(sy.out, syexp(ast_ctx(cexp), (ast_expression*)cexp));
3691                 vec_push(sy.ops, syop(ast_ctx(var), parser->assign_op));
3692                 if (!parser_sy_pop(parser, &sy))
3693                     ast_unref(cexp);
3694                 else {
3695                     if (vec_size(sy.out) != 1 && vec_size(sy.ops) != 0)
3696                         parseerror(parser, "internal error: leaked operands");
3697                     vec_push(localblock->exprs, (ast_expression*)sy.out[0].out);
3698                 }
3699                 vec_free(sy.out);
3700                 vec_free(sy.ops);
3701             }
3702         }
3703
3704 another:
3705         if (parser->tok == ',') {
3706             if (!parser_next(parser)) {
3707                 parseerror(parser, "expected another variable");
3708                 break;
3709             }
3710
3711             if (parser->tok != TOKEN_IDENT) {
3712                 parseerror(parser, "expected another variable");
3713                 break;
3714             }
3715             var = ast_value_copy(basetype);
3716             cleanvar = true;
3717             ast_value_set_name(var, parser_tokval(parser));
3718             if (!parser_next(parser)) {
3719                 parseerror(parser, "error parsing variable declaration");
3720                 break;
3721             }
3722             continue;
3723         }
3724
3725         if (parser->tok != ';') {
3726             parseerror(parser, "missing semicolon after variables");
3727             break;
3728         }
3729
3730         if (!parser_next(parser)) {
3731             parseerror(parser, "parse error after variable declaration");
3732             break;
3733         }
3734
3735         ast_delete(basetype);
3736         return true;
3737     }
3738
3739     if (cleanvar && var)
3740         ast_delete(var);
3741     ast_delete(basetype);
3742     return false;
3743
3744 cleanup:
3745     ast_delete(basetype);
3746     if (cleanvar && var)
3747         ast_delete(var);
3748     if (me[0]) ast_member_delete(me[0]);
3749     if (me[1]) ast_member_delete(me[1]);
3750     if (me[2]) ast_member_delete(me[2]);
3751     return retval;
3752 }
3753
3754 static bool parser_global_statement(parser_t *parser)
3755 {
3756     if (parser->tok == TOKEN_TYPENAME || parser->tok == '.')
3757     {
3758         return parse_variable(parser, NULL, false, false);
3759     }
3760     else if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "var"))
3761     {
3762         if (!strcmp(parser_tokval(parser), "var")) {
3763             if (!parser_next(parser)) {
3764                 parseerror(parser, "expected variable declaration after 'var'");
3765                 return false;
3766             }
3767             return parse_variable(parser, NULL, true, false);
3768         }
3769     }
3770     else if (parser->tok == TOKEN_KEYWORD)
3771     {
3772         if (!strcmp(parser_tokval(parser), "const")) {
3773             if (!parser_next(parser)) {
3774                 parseerror(parser, "expected variable declaration after 'const'");
3775                 return false;
3776             }
3777             return parse_variable(parser, NULL, true, true);
3778         }
3779         parseerror(parser, "unrecognized keyword `%s`", parser_tokval(parser));
3780         return false;
3781     }
3782     else if (parser->tok == '$')
3783     {
3784         if (!parser_next(parser)) {
3785             parseerror(parser, "parse error");
3786             return false;
3787         }
3788     }
3789     else
3790     {
3791         parseerror(parser, "unexpected token: %s", parser->lex->tok.value);
3792         return false;
3793     }
3794     return true;
3795 }
3796
3797 static uint16_t progdefs_crc_sum(uint16_t old, const char *str)
3798 {
3799     return util_crc16(old, str, strlen(str));
3800 }
3801
3802 static void progdefs_crc_file(const char *str)
3803 {
3804     /* write to progdefs.h here */
3805     (void)str;
3806 }
3807
3808 static uint16_t progdefs_crc_both(uint16_t old, const char *str)
3809 {
3810     old = progdefs_crc_sum(old, str);
3811     progdefs_crc_file(str);
3812     return old;
3813 }
3814
3815 static void generate_checksum(parser_t *parser)
3816 {
3817     uint16_t   crc = 0xFFFF;
3818     size_t     i;
3819     ast_value *value;
3820
3821         crc = progdefs_crc_both(crc, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{");
3822         crc = progdefs_crc_sum(crc, "\tint\tpad[28];\n");
3823         /*
3824         progdefs_crc_file("\tint\tpad;\n");
3825         progdefs_crc_file("\tint\tofs_return[3];\n");
3826         progdefs_crc_file("\tint\tofs_parm0[3];\n");
3827         progdefs_crc_file("\tint\tofs_parm1[3];\n");
3828         progdefs_crc_file("\tint\tofs_parm2[3];\n");
3829         progdefs_crc_file("\tint\tofs_parm3[3];\n");
3830         progdefs_crc_file("\tint\tofs_parm4[3];\n");
3831         progdefs_crc_file("\tint\tofs_parm5[3];\n");
3832         progdefs_crc_file("\tint\tofs_parm6[3];\n");
3833         progdefs_crc_file("\tint\tofs_parm7[3];\n");
3834         */
3835         for (i = 0; i < parser->crc_globals; ++i) {
3836             if (!ast_istype(parser->globals[i], ast_value))
3837                 continue;
3838             value = (ast_value*)(parser->globals[i]);
3839             switch (value->expression.vtype) {
3840                 case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
3841                 case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
3842                 case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
3843                 case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
3844                 default:
3845                     crc = progdefs_crc_both(crc, "\tint\t");
3846                     break;
3847             }
3848             crc = progdefs_crc_both(crc, value->name);
3849             crc = progdefs_crc_both(crc, ";\n");
3850         }
3851         crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n");
3852         for (i = 0; i < parser->crc_fields; ++i) {
3853             if (!ast_istype(parser->fields[i], ast_value))
3854                 continue;
3855             value = (ast_value*)(parser->fields[i]);
3856             switch (value->expression.next->expression.vtype) {
3857                 case TYPE_FLOAT:    crc = progdefs_crc_both(crc, "\tfloat\t"); break;
3858                 case TYPE_VECTOR:   crc = progdefs_crc_both(crc, "\tvec3_t\t"); break;
3859                 case TYPE_STRING:   crc = progdefs_crc_both(crc, "\tstring_t\t"); break;
3860                 case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break;
3861                 default:
3862                     crc = progdefs_crc_both(crc, "\tint\t");
3863                     break;
3864             }
3865             crc = progdefs_crc_both(crc, value->name);
3866             crc = progdefs_crc_both(crc, ";\n");
3867         }
3868         crc = progdefs_crc_both(crc, "} entvars_t;\n\n");
3869
3870         code_crc = crc;
3871 }
3872
3873 static parser_t *parser;
3874
3875 bool parser_init()
3876 {
3877     size_t i;
3878
3879     parser = (parser_t*)mem_a(sizeof(parser_t));
3880     if (!parser)
3881         return false;
3882
3883     memset(parser, 0, sizeof(*parser));
3884
3885     for (i = 0; i < operator_count; ++i) {
3886         if (operators[i].id == opid1('=')) {
3887             parser->assign_op = operators+i;
3888             break;
3889         }
3890     }
3891     if (!parser->assign_op) {
3892         printf("internal error: initializing parser: failed to find assign operator\n");
3893         mem_d(parser);
3894         return false;
3895     }
3896
3897     vec_push(parser->variables, parser->htfields  = util_htnew(PARSER_HT_SIZE));
3898     vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE));
3899     return true;
3900 }
3901
3902 bool parser_compile()
3903 {
3904     /* initial lexer/parser state */
3905     parser->lex->flags.noops = true;
3906
3907     if (parser_next(parser))
3908     {
3909         while (parser->tok != TOKEN_EOF && parser->tok < TOKEN_ERROR)
3910         {
3911             if (!parser_global_statement(parser)) {
3912                 if (parser->tok == TOKEN_EOF)
3913                     parseerror(parser, "unexpected eof");
3914                 else if (!parser->errors)
3915                     parseerror(parser, "there have been errors, bailing out");
3916                 lex_close(parser->lex);
3917                 parser->lex = NULL;
3918                 return false;
3919             }
3920         }
3921     } else {
3922         parseerror(parser, "parse error");
3923         lex_close(parser->lex);
3924         parser->lex = NULL;
3925         return false;
3926     }
3927
3928     lex_close(parser->lex);
3929     parser->lex = NULL;
3930
3931     return !parser->errors;
3932 }
3933
3934 bool parser_compile_file(const char *filename)
3935 {
3936     parser->lex = lex_open(filename);
3937     if (!parser->lex) {
3938         con_err("failed to open file \"%s\"\n", filename);
3939         return false;
3940     }
3941     return parser_compile();
3942 }
3943
3944 bool parser_compile_string_len(const char *name, const char *str, size_t len)
3945 {
3946     parser->lex = lex_open_string(str, len, name);
3947     if (!parser->lex) {
3948         con_err("failed to create lexer for string \"%s\"\n", name);
3949         return false;
3950     }
3951     return parser_compile();
3952 }
3953
3954 bool parser_compile_string(const char *name, const char *str)
3955 {
3956     parser->lex = lex_open_string(str, strlen(str), name);
3957     if (!parser->lex) {
3958         con_err("failed to create lexer for string \"%s\"\n", name);
3959         return false;
3960     }
3961     return parser_compile();
3962 }
3963
3964 void parser_cleanup()
3965 {
3966     size_t i;
3967     for (i = 0; i < vec_size(parser->accessors); ++i) {
3968         ast_delete(parser->accessors[i]->constval.vfunc);
3969         parser->accessors[i]->constval.vfunc = NULL;
3970         ast_delete(parser->accessors[i]);
3971     }
3972     for (i = 0; i < vec_size(parser->functions); ++i) {
3973         ast_delete(parser->functions[i]);
3974     }
3975     for (i = 0; i < vec_size(parser->imm_vector); ++i) {
3976         ast_delete(parser->imm_vector[i]);
3977     }
3978     for (i = 0; i < vec_size(parser->imm_string); ++i) {
3979         ast_delete(parser->imm_string[i]);
3980     }
3981     for (i = 0; i < vec_size(parser->imm_float); ++i) {
3982         ast_delete(parser->imm_float[i]);
3983     }
3984     for (i = 0; i < vec_size(parser->fields); ++i) {
3985         ast_delete(parser->fields[i]);
3986     }
3987     for (i = 0; i < vec_size(parser->globals); ++i) {
3988         ast_delete(parser->globals[i]);
3989     }
3990     vec_free(parser->accessors);
3991     vec_free(parser->functions);
3992     vec_free(parser->imm_vector);
3993     vec_free(parser->imm_string);
3994     vec_free(parser->imm_float);
3995     vec_free(parser->globals);
3996     vec_free(parser->fields);
3997
3998     for (i = 0; i < vec_size(parser->variables); ++i)
3999         util_htdel(parser->variables[i]);
4000     vec_free(parser->variables);
4001
4002     mem_d(parser);
4003 }
4004
4005 bool parser_finish(const char *output)
4006 {
4007     size_t i;
4008     ir_builder *ir;
4009     bool retval = true;
4010
4011     if (!parser->errors)
4012     {
4013         ir = ir_builder_new("gmqcc_out");
4014         if (!ir) {
4015             con_out("failed to allocate builder\n");
4016             return false;
4017         }
4018
4019         for (i = 0; i < vec_size(parser->fields); ++i) {
4020             ast_value *field;
4021             bool isconst;
4022             if (!ast_istype(parser->fields[i], ast_value))
4023                 continue;
4024             field = (ast_value*)parser->fields[i];
4025             isconst = field->isconst;
4026             field->isconst = false;
4027             if (!ast_global_codegen((ast_value*)field, ir, true)) {
4028                 con_out("failed to generate field %s\n", field->name);
4029                 ir_builder_delete(ir);
4030                 return false;
4031             }
4032             if (isconst) {
4033                 ir_value *ifld;
4034                 ast_expression *subtype;
4035                 field->isconst = true;
4036                 subtype = field->expression.next;
4037                 ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
4038                 if (subtype->expression.vtype == TYPE_FIELD)
4039                     ifld->fieldtype = subtype->expression.next->expression.vtype;
4040                 else if (subtype->expression.vtype == TYPE_FUNCTION)
4041                     ifld->outtype = subtype->expression.next->expression.vtype;
4042                 (void)!ir_value_set_field(field->ir_v, ifld);
4043             }
4044         }
4045         for (i = 0; i < vec_size(parser->globals); ++i) {
4046             ast_value *asvalue;
4047             if (!ast_istype(parser->globals[i], ast_value))
4048                 continue;
4049             asvalue = (ast_value*)(parser->globals[i]);
4050             if (!asvalue->uses && !asvalue->isconst && asvalue->expression.vtype != TYPE_FUNCTION) {
4051                 if (strcmp(asvalue->name, "end_sys_globals") &&
4052                     strcmp(asvalue->name, "end_sys_fields"))
4053                 {
4054                     retval = retval && !genwarning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
4055                                                    "unused global: `%s`", asvalue->name);
4056                 }
4057             }
4058             if (!ast_global_codegen(asvalue, ir, false)) {
4059                 con_out("failed to generate global %s\n", asvalue->name);
4060                 ir_builder_delete(ir);
4061                 return false;
4062             }
4063         }
4064         for (i = 0; i < vec_size(parser->imm_float); ++i) {
4065             if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
4066                 con_out("failed to generate global %s\n", parser->imm_float[i]->name);
4067                 ir_builder_delete(ir);
4068                 return false;
4069             }
4070         }
4071         for (i = 0; i < vec_size(parser->imm_string); ++i) {
4072             if (!ast_global_codegen(parser->imm_string[i], ir, false)) {
4073                 con_out("failed to generate global %s\n", parser->imm_string[i]->name);
4074                 ir_builder_delete(ir);
4075                 return false;
4076             }
4077         }
4078         for (i = 0; i < vec_size(parser->imm_vector); ++i) {
4079             if (!ast_global_codegen(parser->imm_vector[i], ir, false)) {
4080                 con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
4081                 ir_builder_delete(ir);
4082                 return false;
4083             }
4084         }
4085         for (i = 0; i < vec_size(parser->globals); ++i) {
4086             ast_value *asvalue;
4087             if (!ast_istype(parser->globals[i], ast_value))
4088                 continue;
4089             asvalue = (ast_value*)(parser->globals[i]);
4090             if (asvalue->setter) {
4091                 if (!ast_global_codegen(asvalue->setter, ir, false) ||
4092                     !ast_function_codegen(asvalue->setter->constval.vfunc, ir) ||
4093                     !ir_function_finalize(asvalue->setter->constval.vfunc->ir_func))
4094                 {
4095                     printf("failed to generate setter for %s\n", asvalue->name);
4096                     ir_builder_delete(ir);
4097                     return false;
4098                 }
4099             }
4100             if (asvalue->getter) {
4101                 if (!ast_global_codegen(asvalue->getter, ir, false) ||
4102                     !ast_function_codegen(asvalue->getter->constval.vfunc, ir) ||
4103                     !ir_function_finalize(asvalue->getter->constval.vfunc->ir_func))
4104                 {
4105                     printf("failed to generate getter for %s\n", asvalue->name);
4106                     ir_builder_delete(ir);
4107                     return false;
4108                 }
4109             }
4110         }
4111         for (i = 0; i < vec_size(parser->fields); ++i) {
4112             ast_value *asvalue;
4113             asvalue = (ast_value*)(parser->fields[i]->expression.next);
4114
4115             if (!ast_istype((ast_expression*)asvalue, ast_value))
4116                 continue;
4117             if (asvalue->expression.vtype != TYPE_ARRAY)
4118                 continue;
4119             if (asvalue->setter) {
4120                 if (!ast_global_codegen(asvalue->setter, ir, false) ||
4121                     !ast_function_codegen(asvalue->setter->constval.vfunc, ir) ||
4122                     !ir_function_finalize(asvalue->setter->constval.vfunc->ir_func))
4123                 {
4124                     printf("failed to generate setter for %s\n", asvalue->name);
4125                     ir_builder_delete(ir);
4126                     return false;
4127                 }
4128             }
4129             if (asvalue->getter) {
4130                 if (!ast_global_codegen(asvalue->getter, ir, false) ||
4131                     !ast_function_codegen(asvalue->getter->constval.vfunc, ir) ||
4132                     !ir_function_finalize(asvalue->getter->constval.vfunc->ir_func))
4133                 {
4134                     printf("failed to generate getter for %s\n", asvalue->name);
4135                     ir_builder_delete(ir);
4136                     return false;
4137                 }
4138             }
4139         }
4140         for (i = 0; i < vec_size(parser->functions); ++i) {
4141             if (!ast_function_codegen(parser->functions[i], ir)) {
4142                 con_out("failed to generate function %s\n", parser->functions[i]->name);
4143                 ir_builder_delete(ir);
4144                 return false;
4145             }
4146         }
4147         if (opts_dump)
4148             ir_builder_dump(ir, con_out);
4149         for (i = 0; i < vec_size(parser->functions); ++i) {
4150             if (!ir_function_finalize(parser->functions[i]->ir_func)) {
4151                 con_out("failed to finalize function %s\n", parser->functions[i]->name);
4152                 ir_builder_delete(ir);
4153                 return false;
4154             }
4155         }
4156
4157         if (retval) {
4158             if (opts_dumpfin)
4159                 ir_builder_dump(ir, con_out);
4160
4161             generate_checksum(parser);
4162
4163             if (!ir_builder_generate(ir, output)) {
4164                 con_out("*** failed to generate output file\n");
4165                 ir_builder_delete(ir);
4166                 return false;
4167             }
4168         }
4169
4170         ir_builder_delete(ir);
4171         return retval;
4172     }
4173
4174     con_out("*** there were compile errors\n");
4175     return false;
4176 }