fixed vector ops constant folding.
[xonotic/gmqcc.git] / parser.c
1 /*
2  * Copyright (C) 2012, 2013
3  *     Wolfgang Bumiller
4  *     Dale Weiler
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy of
7  * this software and associated documentation files (the "Software"), to deal in
8  * the Software without restriction, including without limitation the rights to
9  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is furnished to do
11  * so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include <string.h>
25 #include <math.h>
26 #include "parser.h"
27
28 #define PARSER_HT_LOCALS  2
29 #define PARSER_HT_SIZE    512
30 #define TYPEDEF_HT_SIZE   512
31
32 static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
33
34 static void parser_enterblock(parser_t *parser);
35 static bool parser_leaveblock(parser_t *parser);
36 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
37 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e);
38 static bool parse_typedef(parser_t *parser);
39 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
40 static ast_block* parse_block(parser_t *parser);
41 static bool parse_block_into(parser_t *parser, ast_block *block);
42 static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
43 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
44 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels);
45 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
46 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
47 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname);
48 static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
49
50 static void parseerror(parser_t *parser, const char *fmt, ...)
51 {
52     va_list ap;
53     va_start(ap, fmt);
54     vcompile_error(parser->lex->tok.ctx, fmt, ap);
55     va_end(ap);
56 }
57
58 /* returns true if it counts as an error */
59 static bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ...)
60 {
61     bool    r;
62     va_list ap;
63     va_start(ap, fmt);
64     r = vcompile_warning(parser->lex->tok.ctx, warntype, fmt, ap);
65     va_end(ap);
66     return r;
67 }
68
69 /**********************************************************************
70  * parsing
71  */
72
73 static bool parser_next(parser_t *parser)
74 {
75     /* lex_do kills the previous token */
76     parser->tok = lex_do(parser->lex);
77     if (parser->tok == TOKEN_EOF)
78         return true;
79     if (parser->tok >= TOKEN_ERROR) {
80         parseerror(parser, "lex error");
81         return false;
82     }
83     return true;
84 }
85
86 #define parser_tokval(p) ((p)->lex->tok.value)
87 #define parser_token(p)  (&((p)->lex->tok))
88
89 char *parser_strdup(const char *str)
90 {
91     if (str && !*str) {
92         /* actually dup empty strings */
93         char *out = (char*)mem_a(1);
94         *out = 0;
95         return out;
96     }
97     return util_strdup(str);
98 }
99
100 static ast_expression* parser_find_field(parser_t *parser, const char *name)
101 {
102     return ( ast_expression*)util_htget(parser->htfields, name);
103 }
104
105 static ast_expression* parser_find_label(parser_t *parser, const char *name)
106 {
107     size_t i;
108     for(i = 0; i < vec_size(parser->labels); i++)
109         if (!strcmp(parser->labels[i]->name, name))
110             return (ast_expression*)parser->labels[i];
111     return NULL;
112 }
113
114 static ast_expression* parser_find_global(parser_t *parser, const char *name)
115 {
116     ast_expression *var = (ast_expression*)util_htget(parser->aliases, parser_tokval(parser));
117     if (var)
118         return var;
119     return (ast_expression*)util_htget(parser->htglobals, name);
120 }
121
122 static ast_expression* parser_find_param(parser_t *parser, const char *name)
123 {
124     size_t i;
125     ast_value *fun;
126     if (!parser->function)
127         return NULL;
128     fun = parser->function->vtype;
129     for (i = 0; i < vec_size(fun->expression.params); ++i) {
130         if (!strcmp(fun->expression.params[i]->name, name))
131             return (ast_expression*)(fun->expression.params[i]);
132     }
133     return NULL;
134 }
135
136 static ast_expression* parser_find_local(parser_t *parser, const char *name, size_t upto, bool *isparam)
137 {
138     size_t          i, hash;
139     ast_expression *e;
140
141     hash = util_hthash(parser->htglobals, name);
142
143     *isparam = false;
144     for (i = vec_size(parser->variables); i > upto;) {
145         --i;
146         if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) )
147             return e;
148     }
149     *isparam = true;
150     return parser_find_param(parser, name);
151 }
152
153 static ast_expression* parser_find_var(parser_t *parser, const char *name)
154 {
155     bool dummy;
156     ast_expression *v;
157     v         = parser_find_local(parser, name, 0, &dummy);
158     if (!v) v = parser_find_global(parser, name);
159     return v;
160 }
161
162 static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t upto)
163 {
164     size_t     i, hash;
165     ast_value *e;
166     hash = util_hthash(parser->typedefs[0], name);
167
168     for (i = vec_size(parser->typedefs); i > upto;) {
169         --i;
170         if ( (e = (ast_value*)util_htgeth(parser->typedefs[i], name, hash)) )
171             return e;
172     }
173     return NULL;
174 }
175
176 /* include intrinsics */
177 #include "intrin.h"
178
179 typedef struct
180 {
181     size_t etype; /* 0 = expression, others are operators */
182     bool            isparen;
183     size_t          off;
184     ast_expression *out;
185     ast_block      *block; /* for commas and function calls */
186     lex_ctx_t ctx;
187 } sy_elem;
188
189 enum {
190     PAREN_EXPR,
191     PAREN_FUNC,
192     PAREN_INDEX,
193     PAREN_TERNARY1,
194     PAREN_TERNARY2
195 };
196 typedef struct
197 {
198     sy_elem        *out;
199     sy_elem        *ops;
200     size_t         *argc;
201     unsigned int   *paren;
202 } shunt;
203
204 static sy_elem syexp(lex_ctx_t ctx, ast_expression *v) {
205     sy_elem e;
206     e.etype = 0;
207     e.off   = 0;
208     e.out   = v;
209     e.block = NULL;
210     e.ctx   = ctx;
211     e.isparen = false;
212     return e;
213 }
214
215 static sy_elem syblock(lex_ctx_t ctx, ast_block *v) {
216     sy_elem e;
217     e.etype = 0;
218     e.off   = 0;
219     e.out   = (ast_expression*)v;
220     e.block = v;
221     e.ctx   = ctx;
222     e.isparen = false;
223     return e;
224 }
225
226 static sy_elem syop(lex_ctx_t ctx, const oper_info *op) {
227     sy_elem e;
228     e.etype = 1 + (op - operators);
229     e.off   = 0;
230     e.out   = NULL;
231     e.block = NULL;
232     e.ctx   = ctx;
233     e.isparen = false;
234     return e;
235 }
236
237 static sy_elem syparen(lex_ctx_t ctx, size_t off) {
238     sy_elem e;
239     e.etype = 0;
240     e.off   = off;
241     e.out   = NULL;
242     e.block = NULL;
243     e.ctx   = ctx;
244     e.isparen = true;
245     return e;
246 }
247
248 /* With regular precedence rules, ent.foo[n] is the same as (ent.foo)[n],
249  * so we need to rotate it to become ent.(foo[n]).
250  */
251 static bool rotate_entfield_array_index_nodes(ast_expression **out)
252 {
253     ast_array_index *index, *oldindex;
254     ast_entfield    *entfield;
255
256     ast_value       *field;
257     ast_expression  *sub;
258     ast_expression  *entity;
259
260     lex_ctx_t ctx = ast_ctx(*out);
261
262     if (!ast_istype(*out, ast_array_index))
263         return false;
264     index = (ast_array_index*)*out;
265
266     if (!ast_istype(index->array, ast_entfield))
267         return false;
268     entfield = (ast_entfield*)index->array;
269
270     if (!ast_istype(entfield->field, ast_value))
271         return false;
272     field = (ast_value*)entfield->field;
273
274     sub    = index->index;
275     entity = entfield->entity;
276
277     oldindex = index;
278
279     index = ast_array_index_new(ctx, (ast_expression*)field, sub);
280     entfield = ast_entfield_new(ctx, entity, (ast_expression*)index);
281     *out = (ast_expression*)entfield;
282
283     oldindex->array = NULL;
284     oldindex->index = NULL;
285     ast_delete(oldindex);
286
287     return true;
288 }
289
290 static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
291 {
292     const oper_info *op;
293     lex_ctx_t ctx;
294     ast_expression *out = NULL;
295     ast_expression *exprs[3];
296     ast_block      *blocks[3];
297     ast_value      *asvalue[3];
298     ast_binstore   *asbinstore;
299     size_t i, assignop, addop, subop;
300     qcint_t  generated_op = 0;
301
302     char ty1[1024];
303     char ty2[1024];
304
305     if (!vec_size(sy->ops)) {
306         parseerror(parser, "internal error: missing operator");
307         return false;
308     }
309
310     if (vec_last(sy->ops).isparen) {
311         parseerror(parser, "unmatched parenthesis");
312         return false;
313     }
314
315     op = &operators[vec_last(sy->ops).etype - 1];
316     ctx = vec_last(sy->ops).ctx;
317
318     if (vec_size(sy->out) < op->operands) {
319         compile_error(ctx, "internal error: not enough operands: %i (operator %s (%i))", vec_size(sy->out),
320                       op->op, (int)op->id);
321         return false;
322     }
323
324     vec_shrinkby(sy->ops, 1);
325
326     /* op(:?) has no input and no output */
327     if (!op->operands)
328         return true;
329
330     vec_shrinkby(sy->out, op->operands);
331     for (i = 0; i < op->operands; ++i) {
332         exprs[i]  = sy->out[vec_size(sy->out)+i].out;
333         blocks[i] = sy->out[vec_size(sy->out)+i].block;
334         asvalue[i] = (ast_value*)exprs[i];
335
336         if (exprs[i]->vtype == TYPE_NOEXPR &&
337             !(i != 0 && op->id == opid2('?',':')) &&
338             !(i == 1 && op->id == opid1('.')))
339         {
340             if (ast_istype(exprs[i], ast_label))
341                 compile_error(ast_ctx(exprs[i]), "expected expression, got an unknown identifier");
342             else
343                 compile_error(ast_ctx(exprs[i]), "not an expression");
344             (void)!compile_warning(ast_ctx(exprs[i]), WARN_DEBUG, "expression %u\n", (unsigned int)i);
345         }
346     }
347
348     if (blocks[0] && !vec_size(blocks[0]->exprs) && op->id != opid1(',')) {
349         compile_error(ctx, "internal error: operator cannot be applied on empty blocks");
350         return false;
351     }
352
353 #define NotSameType(T) \
354              (exprs[0]->vtype != exprs[1]->vtype || \
355               exprs[0]->vtype != T)
356
357     /* preform any constant folding on operator usage first */
358     /*if ((out = fold_op(parser->fold, op, exprs)))*/
359     /*goto complete;*/
360
361     switch (op->id)
362     {
363         default:
364             compile_error(ctx, "internal error: unhandled operator: %s (%i)", op->op, (int)op->id);
365             return false;
366
367         case opid1('.'):
368             if (exprs[0]->vtype == TYPE_VECTOR &&
369                 exprs[1]->vtype == TYPE_NOEXPR)
370             {
371                 if      (exprs[1] == (ast_expression*)parser->const_vec[0])
372                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL);
373                 else if (exprs[1] == (ast_expression*)parser->const_vec[1])
374                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL);
375                 else if (exprs[1] == (ast_expression*)parser->const_vec[2])
376                     out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL);
377                 else {
378                     compile_error(ctx, "access to invalid vector component");
379                     return false;
380                 }
381             }
382             else if (exprs[0]->vtype == TYPE_ENTITY) {
383                 if (exprs[1]->vtype != TYPE_FIELD) {
384                     compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field");
385                     return false;
386                 }
387                 out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]);
388             }
389             else if (exprs[0]->vtype == TYPE_VECTOR) {
390                 compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way");
391                 return false;
392             }
393             else {
394                 compile_error(ast_ctx(exprs[1]), "type error: member-of operator on something that is not an entity or vector");
395                 return false;
396             }
397             break;
398
399         case opid1('['):
400             if (exprs[0]->vtype != TYPE_ARRAY &&
401                 !(exprs[0]->vtype == TYPE_FIELD &&
402                   exprs[0]->next->vtype == TYPE_ARRAY))
403             {
404                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
405                 compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1);
406                 return false;
407             }
408             if (exprs[1]->vtype != TYPE_FLOAT) {
409                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
410                 compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1);
411                 return false;
412             }
413             out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]);
414             if (rotate_entfield_array_index_nodes(&out))
415             {
416 #if 0
417                 /* This is not broken in fteqcc anymore */
418                 if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
419                     /* this error doesn't need to make us bail out */
420                     (void)!parsewarning(parser, WARN_EXTENSIONS,
421                                         "accessing array-field members of an entity without parenthesis\n"
422                                         " -> this is an extension from -std=gmqcc");
423                 }
424 #endif
425             }
426             break;
427
428         case opid1(','):
429             if (vec_size(sy->paren) && vec_last(sy->paren) == PAREN_FUNC) {
430                 vec_push(sy->out, syexp(ctx, exprs[0]));
431                 vec_push(sy->out, syexp(ctx, exprs[1]));
432                 vec_last(sy->argc)++;
433                 return true;
434             }
435             if (blocks[0]) {
436                 if (!ast_block_add_expr(blocks[0], exprs[1]))
437                     return false;
438             } else {
439                 blocks[0] = ast_block_new(ctx);
440                 if (!ast_block_add_expr(blocks[0], exprs[0]) ||
441                     !ast_block_add_expr(blocks[0], exprs[1]))
442                 {
443                     return false;
444                 }
445             }
446             ast_block_set_type(blocks[0], exprs[1]);
447
448             vec_push(sy->out, syblock(ctx, blocks[0]));
449             return true;
450
451         case opid2('+','P'):
452             out = exprs[0];
453             break;
454         case opid2('-','P'):
455             if (!(out = fold_op(parser->fold, op, exprs))) {
456                 switch (exprs[0]->vtype) {
457                     case TYPE_FLOAT:
458                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
459                                                                   (ast_expression*)parser->fold->imm_float[0],
460                                                                   exprs[0]);
461                         break;
462                     case TYPE_VECTOR:
463                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
464                                                                   (ast_expression*)parser->fold->imm_vector[0],
465                                                                   exprs[0]);
466                         break;
467                     default:
468                     compile_error(ctx, "invalid types used in expression: cannot negate type %s",
469                                   type_name[exprs[0]->vtype]);
470                     return false;
471                 }
472             }
473             break;
474
475         case opid2('!','P'):
476             if (!(out = fold_op(parser->fold, op, exprs))) {
477                 switch (exprs[0]->vtype) {
478                     case TYPE_FLOAT:
479                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
480                         break;
481                     case TYPE_VECTOR:
482                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[0]);
483                         break;
484                     case TYPE_STRING:
485                         if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
486                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]);
487                         else
488                             out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[0]);
489                         break;
490                     /* we don't constant-fold NOT for these types */
491                     case TYPE_ENTITY:
492                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_ENT, exprs[0]);
493                         break;
494                     case TYPE_FUNCTION:
495                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_FNC, exprs[0]);
496                         break;
497                     default:
498                     compile_error(ctx, "invalid types used in expression: cannot logically negate type %s",
499                                   type_name[exprs[0]->vtype]);
500                     return false;
501                 }
502             }
503             break;
504
505         case opid1('+'):
506             if (exprs[0]->vtype != exprs[1]->vtype ||
507                (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
508             {
509                 compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
510                               type_name[exprs[0]->vtype],
511                               type_name[exprs[1]->vtype]);
512                 return false;
513             }
514             if (!(out = fold_op(parser->fold, op, exprs))) {
515                 switch (exprs[0]->vtype) {
516                     case TYPE_FLOAT:
517                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
518                         break;
519                     case TYPE_VECTOR:
520                         out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
521                         break;
522                     default:
523                         compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
524                                       type_name[exprs[0]->vtype],
525                                       type_name[exprs[1]->vtype]);
526                         return false;
527                 }
528             }
529             break;
530         case opid1('-'):
531             if  (exprs[0]->vtype != exprs[1]->vtype ||
532                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT))
533             {
534                 compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
535                               type_name[exprs[1]->vtype],
536                               type_name[exprs[0]->vtype]);
537                 return false;
538             }
539             if (!(out = fold_op(parser->fold, op, exprs))) {
540                 switch (exprs[0]->vtype) {
541                     case TYPE_FLOAT:
542                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
543                         break;
544                     case TYPE_VECTOR:
545                         out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
546                         break;
547                     default:
548                         compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
549                                       type_name[exprs[1]->vtype],
550                                       type_name[exprs[0]->vtype]);
551                         return false;
552                 }
553             }
554             break;
555         case opid1('*'):
556             if (exprs[0]->vtype != exprs[1]->vtype &&
557                 !(exprs[0]->vtype == TYPE_VECTOR &&
558                   exprs[1]->vtype == TYPE_FLOAT) &&
559                 !(exprs[1]->vtype == TYPE_VECTOR &&
560                   exprs[0]->vtype == TYPE_FLOAT)
561                 )
562             {
563                 compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
564                               type_name[exprs[1]->vtype],
565                               type_name[exprs[0]->vtype]);
566                 return false;
567             }
568             if (!(out = fold_op(parser->fold, op, exprs))) {
569                 switch (exprs[0]->vtype) {
570                     case TYPE_FLOAT:
571                         if (exprs[1]->vtype == TYPE_VECTOR)
572                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
573                         else
574                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
575                         break;
576                     case TYPE_VECTOR:
577                         if (exprs[1]->vtype == TYPE_FLOAT)
578                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
579                         else
580                             out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
581                         break;
582                     default:
583                         compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
584                                       type_name[exprs[1]->vtype],
585                                       type_name[exprs[0]->vtype]);
586                         return false;
587                 }
588             }
589             break;
590
591         case opid1('/'):
592             if (exprs[1]->vtype != TYPE_FLOAT) {
593                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
594                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
595                 compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
596                 return false;
597             }
598             if (!(out = fold_op(parser->fold, op, exprs))) {
599                 if (exprs[0]->vtype == TYPE_FLOAT)
600                     out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
601                 else {
602                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
603                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
604                     compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2);
605                     return false;
606                 }
607             }
608             break;
609
610         case opid1('%'):
611             if (NotSameType(TYPE_FLOAT)) {
612                 compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s",
613                     type_name[exprs[0]->vtype],
614                     type_name[exprs[1]->vtype]);
615                 return false;
616             } else if (!(out = fold_op(parser->fold, op, exprs))) {
617                 /* generate a call to __builtin_mod */
618                 ast_expression *mod  = intrin_func(parser, "mod");
619                 ast_call       *call = NULL;
620                 if (!mod) return false; /* can return null for missing floor */
621
622                 call = ast_call_new(parser_ctx(parser), mod);
623                 vec_push(call->params, exprs[0]);
624                 vec_push(call->params, exprs[1]);
625
626                 out = (ast_expression*)call;
627             }
628             break;
629
630         case opid2('%','='):
631             compile_error(ctx, "%= is unimplemented");
632             return false;
633
634         case opid1('|'):
635         case opid1('&'):
636             if (NotSameType(TYPE_FLOAT)) {
637                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
638                               type_name[exprs[0]->vtype],
639                               type_name[exprs[1]->vtype]);
640                 return false;
641             }
642             if (!(out = fold_op(parser->fold, op, exprs)))
643                 out = (ast_expression*)ast_binary_new(ctx,
644                     (op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
645                     exprs[0], exprs[1]);
646             break;
647         case opid1('^'):
648             /*
649              * Okay lets designate what the hell is an acceptable use
650              * of the ^ operator. In many vector processing units, XOR
651              * is allowed to be used on vectors, but only if the first
652              * operand is a vector, the second operand can be a float
653              * or vector. It's never legal for the first operand to be
654              * a float, and then the following operand to be a vector.
655              * Further more, the only time it is legal to do XOR otherwise
656              * is when both operand are floats. This nicely crafted if
657              * statement catches them all.
658              *
659              * In the event that the first operand is a vector, two
660              * possible situations can arise, thus, each element of
661              * vector A (operand A) is exclusive-ORed with the corresponding
662              * element of vector B (operand B), If B is scalar, the
663              * scalar value is first replicated for each element.
664              *
665              * The QCVM itself lacks a BITXOR instruction. Thus emulating
666              * the mathematics of it is required. The following equation
667              * is used: (LHS | RHS) & ~(LHS & RHS). However, due to the
668              * QCVM also lacking a BITNEG instruction, we need to emulate
669              * ~FOO with -1 - FOO, the whole process becoming this nicely
670              * crafted expression: (LHS | RHS) & (-1 - (LHS & RHS)).
671              *
672              * When A is not scalar, this process is repeated for all
673              * components of vector A with the value in operand B,
674              * only if operand B is scalar. When A is not scalar, and B
675              * is also not scalar, this process is repeated for all
676              * components of the vector A with the components of vector B.
677              * Finally when A is scalar and B is scalar, this process is
678              * simply used once for A and B being LHS and RHS respectfully.
679              *
680              * Yes the semantics are a bit strange (no pun intended).
681              * But then again BITXOR is strange itself, consdering it's
682              * commutative, assocative, and elements of the BITXOR operation
683              * are their own inverse.
684              */
685             if ( !(exprs[0]->vtype == TYPE_FLOAT  && exprs[1]->vtype == TYPE_FLOAT) &&
686                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_FLOAT) &&
687                  !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_VECTOR))
688             {
689                 compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
690                               type_name[exprs[0]->vtype],
691                               type_name[exprs[1]->vtype]);
692                 return false;
693             }
694
695             if (!(out = fold_op(parser->fold, op, exprs))) {
696                 /*
697                  * IF the first expression is float, the following will be too
698                  * since scalar ^ vector is not allowed.
699                  */
700                 if (exprs[0]->vtype == TYPE_FLOAT) {
701                     ast_binary *expr = ast_binary_new(
702                         ctx,
703                         INSTR_SUB_F,
704                         (ast_expression*)parser->fold->imm_float[2],
705                         (ast_expression*)ast_binary_new(
706                             ctx,
707                             INSTR_BITAND,
708                             exprs[0],
709                             exprs[1]
710                         )
711                     );
712                     expr->refs = AST_REF_NONE;
713
714                     out = (ast_expression*)
715                         ast_binary_new(
716                             ctx,
717                             INSTR_BITAND,
718                             (ast_expression*)ast_binary_new(
719                                 ctx,
720                                 INSTR_BITOR,
721                                 exprs[0],
722                                 exprs[1]
723                             ),
724                             (ast_expression*)expr
725                         );
726                 } else {
727                     /*
728                      * The first is a vector: vector is allowed to xor with vector and
729                      * with scalar, branch here for the second operand.
730                      */
731                     if (exprs[1]->vtype == TYPE_VECTOR) {
732                         /*
733                          * Xor all the values of the vector components against the
734                          * vectors components in question.
735                          */
736                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against vector");
737                         return false;
738                     } else {
739                         compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor for vector against float");
740                         return false;
741                     }
742                 }
743             }
744             break;
745
746         case opid2('<','<'):
747         case opid2('>','>'):
748         case opid3('<','<','='):
749         case opid3('>','>','='):
750             if(!(out = fold_op(parser->fold, op, exprs))) {
751                 compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts");
752                 return false;
753             }
754
755         case opid2('|','|'):
756             generated_op += 1; /* INSTR_OR */
757         case opid2('&','&'):
758             generated_op += INSTR_AND;
759             if (!(out = fold_op(parser->fold, op, exprs))) {
760                 if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) {
761                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
762                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
763                     compile_error(ctx, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2);
764                     return false;
765                 }
766                 for (i = 0; i < 2; ++i) {
767                     if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) {
768                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
769                         if (!out) break;
770                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
771                         if (!out) break;
772                         exprs[i] = out; out = NULL;
773                         if (OPTS_FLAG(PERL_LOGIC)) {
774                             /* here we want to keep the right expressions' type */
775                             break;
776                         }
777                     }
778                     else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) {
779                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
780                         if (!out) break;
781                         out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
782                         if (!out) break;
783                         exprs[i] = out; out = NULL;
784                         if (OPTS_FLAG(PERL_LOGIC)) {
785                             /* here we want to keep the right expressions' type */
786                             break;
787                         }
788                     }
789                 }
790                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
791             }
792             break;
793
794         case opid2('?',':'):
795             if (vec_last(sy->paren) != PAREN_TERNARY2) {
796                 compile_error(ctx, "mismatched parenthesis/ternary");
797                 return false;
798             }
799             vec_pop(sy->paren);
800             if (!ast_compare_type(exprs[1], exprs[2])) {
801                 ast_type_to_string(exprs[1], ty1, sizeof(ty1));
802                 ast_type_to_string(exprs[2], ty2, sizeof(ty2));
803                 compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2);
804                 return false;
805             }
806             if (!(out = fold_op(parser->fold, op, exprs)))
807                 out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]);
808             break;
809
810         case opid2('*', '*'):
811             if (NotSameType(TYPE_FLOAT)) {
812                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
813                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
814                 compile_error(ctx, "invalid types used in exponentiation: %s and %s",
815                     ty1, ty2);
816                 return false;
817             }
818             
819             if (!(out = fold_op(parser->fold, op, exprs))) {
820                 ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser, "pow"));
821                 vec_push(gencall->params, exprs[0]);
822                 vec_push(gencall->params, exprs[1]);
823                 out = (ast_expression*)gencall;
824             }
825             break;
826
827         case opid3('<','=','>'): /* -1, 0, or 1 */
828             if (NotSameType(TYPE_FLOAT)) {
829                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
830                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
831                 compile_error(ctx, "invalid types used in comparision: %s and %s",
832                     ty1, ty2);
833
834                 return false;
835             } 
836
837             if (!(out = fold_op(parser->fold, op, exprs))) {
838                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
839
840                 eq->refs = AST_REF_NONE;
841
842                     /* if (lt) { */
843                 out = (ast_expression*)ast_ternary_new(ctx,
844                         (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]),
845                         /* out = -1 */
846                         (ast_expression*)parser->fold->imm_float[2],
847                     /* } else { */
848                         /* if (eq) { */
849                         (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq,
850                             /* out = 0 */
851                             (ast_expression*)parser->fold->imm_float[0],
852                         /* } else { */
853                             /* out = 1 */
854                             (ast_expression*)parser->fold->imm_float[1]
855                         /* } */
856                         )
857                     /* } */
858                     );
859
860             }
861             break;
862
863         case opid1('>'):
864             generated_op += 1; /* INSTR_GT */
865         case opid1('<'):
866             generated_op += 1; /* INSTR_LT */
867         case opid2('>', '='):
868             generated_op += 1; /* INSTR_GE */
869         case opid2('<', '='):
870             generated_op += INSTR_LE;
871             if (NotSameType(TYPE_FLOAT)) {
872                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
873                               type_name[exprs[0]->vtype],
874                               type_name[exprs[1]->vtype]);
875                 return false;
876             }
877             if (!(out = fold_op(parser->fold, op, exprs)))
878                 out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
879             break;
880         case opid2('!', '='):
881             if (exprs[0]->vtype != exprs[1]->vtype) {
882                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
883                               type_name[exprs[0]->vtype],
884                               type_name[exprs[1]->vtype]);
885                 return false;
886             }
887             if (!(out = fold_op(parser->fold, op, exprs)))
888                 out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
889             break;
890         case opid2('=', '='):
891             if (exprs[0]->vtype != exprs[1]->vtype) {
892                 compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s",
893                               type_name[exprs[0]->vtype],
894                               type_name[exprs[1]->vtype]);
895                 return false;
896             }
897             if (!(out = fold_op(parser->fold, op, exprs)))
898                 out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
899             break;
900
901         case opid1('='):
902             if (ast_istype(exprs[0], ast_entfield)) {
903                 ast_expression *field = ((ast_entfield*)exprs[0])->field;
904                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
905                     exprs[0]->vtype == TYPE_FIELD &&
906                     exprs[0]->next->vtype == TYPE_VECTOR)
907                 {
908                     assignop = type_storep_instr[TYPE_VECTOR];
909                 }
910                 else
911                     assignop = type_storep_instr[exprs[0]->vtype];
912                 if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1]))
913                 {
914                     ast_type_to_string(field->next, ty1, sizeof(ty1));
915                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
916                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
917                         field->next->vtype == TYPE_FUNCTION &&
918                         exprs[1]->vtype == TYPE_FUNCTION)
919                     {
920                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
921                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
922                     }
923                     else
924                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
925                 }
926             }
927             else
928             {
929                 if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
930                     exprs[0]->vtype == TYPE_FIELD &&
931                     exprs[0]->next->vtype == TYPE_VECTOR)
932                 {
933                     assignop = type_store_instr[TYPE_VECTOR];
934                 }
935                 else {
936                     assignop = type_store_instr[exprs[0]->vtype];
937                 }
938
939                 if (assignop == VINSTR_END) {
940                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
941                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
942                     compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
943                 }
944                 else if (!ast_compare_type(exprs[0], exprs[1]))
945                 {
946                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
947                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
948                     if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) &&
949                         exprs[0]->vtype == TYPE_FUNCTION &&
950                         exprs[1]->vtype == TYPE_FUNCTION)
951                     {
952                         (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES,
953                                                "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
954                     }
955                     else
956                         compile_error(ctx, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
957                 }
958             }
959             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
960                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
961             }
962             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
963             break;
964         case opid3('+','+','P'):
965         case opid3('-','-','P'):
966             /* prefix ++ */
967             if (exprs[0]->vtype != TYPE_FLOAT) {
968                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
969                 compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1);
970                 return false;
971             }
972             if (op->id == opid3('+','+','P'))
973                 addop = INSTR_ADD_F;
974             else
975                 addop = INSTR_SUB_F;
976             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
977                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
978             }
979             if (ast_istype(exprs[0], ast_entfield)) {
980                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
981                                                         exprs[0],
982                                                         (ast_expression*)parser->fold->imm_float[1]);
983             } else {
984                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
985                                                         exprs[0],
986                                                         (ast_expression*)parser->fold->imm_float[1]);
987             }
988             break;
989         case opid3('S','+','+'):
990         case opid3('S','-','-'):
991             /* prefix ++ */
992             if (exprs[0]->vtype != TYPE_FLOAT) {
993                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
994                 compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1);
995                 return false;
996             }
997             if (op->id == opid3('S','+','+')) {
998                 addop = INSTR_ADD_F;
999                 subop = INSTR_SUB_F;
1000             } else {
1001                 addop = INSTR_SUB_F;
1002                 subop = INSTR_ADD_F;
1003             }
1004             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1005                 compile_error(ast_ctx(exprs[0]), "assignment to constant `%s`", asvalue[0]->name);
1006             }
1007             if (ast_istype(exprs[0], ast_entfield)) {
1008                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop,
1009                                                         exprs[0],
1010                                                         (ast_expression*)parser->fold->imm_float[1]);
1011             } else {
1012                 out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop,
1013                                                         exprs[0],
1014                                                         (ast_expression*)parser->fold->imm_float[1]);
1015             }
1016             if (!out)
1017                 return false;
1018             out = (ast_expression*)ast_binary_new(ctx, subop,
1019                                                   out,
1020                                                   (ast_expression*)parser->fold->imm_float[1]);
1021             break;
1022         case opid2('+','='):
1023         case opid2('-','='):
1024             if (exprs[0]->vtype != exprs[1]->vtype ||
1025                 (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) )
1026             {
1027                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1028                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1029                 compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1030                               ty1, ty2);
1031                 return false;
1032             }
1033             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1034                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1035             }
1036             if (ast_istype(exprs[0], ast_entfield))
1037                 assignop = type_storep_instr[exprs[0]->vtype];
1038             else
1039                 assignop = type_store_instr[exprs[0]->vtype];
1040             switch (exprs[0]->vtype) {
1041                 case TYPE_FLOAT:
1042                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1043                                                             (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F),
1044                                                             exprs[0], exprs[1]);
1045                     break;
1046                 case TYPE_VECTOR:
1047                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1048                                                             (op->id == opid2('+','=') ? INSTR_ADD_V : INSTR_SUB_V),
1049                                                             exprs[0], exprs[1]);
1050                     break;
1051                 default:
1052                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1053                                   type_name[exprs[0]->vtype],
1054                                   type_name[exprs[1]->vtype]);
1055                     return false;
1056             };
1057             break;
1058         case opid2('*','='):
1059         case opid2('/','='):
1060             if (exprs[1]->vtype != TYPE_FLOAT ||
1061                 !(exprs[0]->vtype == TYPE_FLOAT ||
1062                   exprs[0]->vtype == TYPE_VECTOR))
1063             {
1064                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1065                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1066                 compile_error(ctx, "invalid types used in expression: %s and %s",
1067                               ty1, ty2);
1068                 return false;
1069             }
1070             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1071                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1072             }
1073             if (ast_istype(exprs[0], ast_entfield))
1074                 assignop = type_storep_instr[exprs[0]->vtype];
1075             else
1076                 assignop = type_store_instr[exprs[0]->vtype];
1077             switch (exprs[0]->vtype) {
1078                 case TYPE_FLOAT:
1079                     out = (ast_expression*)ast_binstore_new(ctx, assignop,
1080                                                             (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F),
1081                                                             exprs[0], exprs[1]);
1082                     break;
1083                 case TYPE_VECTOR:
1084                     if (op->id == opid2('*','=')) {
1085                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1086                                                                 exprs[0], exprs[1]);
1087                     } else {
1088                         out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
1089                                                                   (ast_expression*)parser->fold->imm_float[1],
1090                                                                   exprs[1]);
1091                         if (!out) {
1092                             compile_error(ctx, "internal error: failed to generate division");
1093                             return false;
1094                         }
1095                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
1096                                                                 exprs[0], out);
1097                     }
1098                     break;
1099                 default:
1100                     compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s",
1101                                   type_name[exprs[0]->vtype],
1102                                   type_name[exprs[1]->vtype]);
1103                     return false;
1104             };
1105             break;
1106         case opid2('&','='):
1107         case opid2('|','='):
1108             if (NotSameType(TYPE_FLOAT)) {
1109                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1110                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1111                 compile_error(ctx, "invalid types used in expression: %s and %s",
1112                               ty1, ty2);
1113                 return false;
1114             }
1115             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1116                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1117             }
1118             if (ast_istype(exprs[0], ast_entfield))
1119                 assignop = type_storep_instr[exprs[0]->vtype];
1120             else
1121                 assignop = type_store_instr[exprs[0]->vtype];
1122             out = (ast_expression*)ast_binstore_new(ctx, assignop,
1123                                                     (op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
1124                                                     exprs[0], exprs[1]);
1125             break;
1126         case opid3('&','~','='):
1127             /* This is like: a &= ~(b);
1128              * But QC has no bitwise-not, so we implement it as
1129              * a -= a & (b);
1130              */
1131             if (NotSameType(TYPE_FLOAT)) {
1132                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1133                 ast_type_to_string(exprs[1], ty2, sizeof(ty2));
1134                 compile_error(ctx, "invalid types used in expression: %s and %s",
1135                               ty1, ty2);
1136                 return false;
1137             }
1138             if (ast_istype(exprs[0], ast_entfield))
1139                 assignop = type_storep_instr[exprs[0]->vtype];
1140             else
1141                 assignop = type_store_instr[exprs[0]->vtype];
1142             out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
1143             if (!out)
1144                 return false;
1145             if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
1146                 compile_error(ctx, "assignment to constant `%s`", asvalue[0]->name);
1147             }
1148             asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
1149             asbinstore->keep_dest = true;
1150             out = (ast_expression*)asbinstore;
1151             break;
1152
1153         case opid2('~', 'P'):
1154             if (exprs[0]->vtype != TYPE_FLOAT) {
1155                 ast_type_to_string(exprs[0], ty1, sizeof(ty1));
1156                 compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1);
1157                 return false;
1158             }
1159             if (!(out = fold_op(parser->fold, op, exprs)))
1160                 out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]);
1161             break;
1162     }
1163 #undef NotSameType
1164 /*complete:*/
1165     if (!out) {
1166         compile_error(ctx, "failed to apply operator %s", op->op);
1167         return false;
1168     }
1169
1170     vec_push(sy->out, syexp(ctx, out));
1171     return true;
1172 }
1173
1174 static bool parser_close_call(parser_t *parser, shunt *sy)
1175 {
1176     /* was a function call */
1177     ast_expression *fun;
1178     ast_value      *funval = NULL;
1179     ast_call       *call;
1180
1181     size_t          fid;
1182     size_t          paramcount, i;
1183
1184     fid = vec_last(sy->ops).off;
1185     vec_shrinkby(sy->ops, 1);
1186
1187     /* out[fid] is the function
1188      * everything above is parameters...
1189      */
1190     if (!vec_size(sy->argc)) {
1191         parseerror(parser, "internal error: no argument counter available");
1192         return false;
1193     }
1194
1195     paramcount = vec_last(sy->argc);
1196     vec_pop(sy->argc);
1197
1198     if (vec_size(sy->out) < fid) {
1199         parseerror(parser, "internal error: broken function call%lu < %lu+%lu\n",
1200                    (unsigned long)vec_size(sy->out),
1201                    (unsigned long)fid,
1202                    (unsigned long)paramcount);
1203         return false;
1204     }
1205
1206     fun = sy->out[fid].out;
1207
1208     if (fun == intrinsic_debug_typestring) {
1209         char ty[1024];
1210         if (fid+2 != vec_size(sy->out) ||
1211             vec_last(sy->out).block)
1212         {
1213             parseerror(parser, "intrinsic __builtin_debug_typestring requires exactly 1 parameter");
1214             return false;
1215         }
1216         ast_type_to_string(vec_last(sy->out).out, ty, sizeof(ty));
1217         ast_unref(vec_last(sy->out).out);
1218         sy->out[fid] = syexp(ast_ctx(vec_last(sy->out).out),
1219                              (ast_expression*)fold_constgen_string(parser->fold, ty, false));
1220         vec_shrinkby(sy->out, 1);
1221         return true;
1222     }
1223
1224     call = ast_call_new(sy->ops[vec_size(sy->ops)].ctx, fun);
1225     if (!call)
1226         return false;
1227
1228     if (fid+1 < vec_size(sy->out))
1229         ++paramcount;
1230
1231     if (fid+1 + paramcount != vec_size(sy->out)) {
1232         parseerror(parser, "internal error: parameter count mismatch: (%lu+1+%lu), %lu",
1233                    (unsigned long)fid, (unsigned long)paramcount, (unsigned long)vec_size(sy->out));
1234         return false;
1235     }
1236
1237     for (i = 0; i < paramcount; ++i)
1238         vec_push(call->params, sy->out[fid+1 + i].out);
1239     vec_shrinkby(sy->out, paramcount);
1240     (void)!ast_call_check_types(call, parser->function->vtype->expression.varparam);
1241     if (parser->max_param_count < paramcount)
1242         parser->max_param_count = paramcount;
1243
1244     if (ast_istype(fun, ast_value)) {
1245         funval = (ast_value*)fun;
1246         if ((fun->flags & AST_FLAG_VARIADIC) &&
1247             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
1248         {
1249             call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount);
1250         }
1251     }
1252
1253     /* overwrite fid, the function, with a call */
1254     sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call);
1255
1256     if (fun->vtype != TYPE_FUNCTION) {
1257         parseerror(parser, "not a function (%s)", type_name[fun->vtype]);
1258         return false;
1259     }
1260
1261     if (!fun->next) {
1262         parseerror(parser, "could not determine function return type");
1263         return false;
1264     } else {
1265         ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
1266
1267         if (fun->flags & AST_FLAG_DEPRECATED) {
1268             if (!fval) {
1269                 return !parsewarning(parser, WARN_DEPRECATED,
1270                         "call to function (which is marked deprecated)\n",
1271                         "-> it has been declared here: %s:%i",
1272                         ast_ctx(fun).file, ast_ctx(fun).line);
1273             }
1274             if (!fval->desc) {
1275                 return !parsewarning(parser, WARN_DEPRECATED,
1276                         "call to `%s` (which is marked deprecated)\n"
1277                         "-> `%s` declared here: %s:%i",
1278                         fval->name, fval->name, ast_ctx(fun).file, ast_ctx(fun).line);
1279             }
1280             return !parsewarning(parser, WARN_DEPRECATED,
1281                     "call to `%s` (deprecated: %s)\n"
1282                     "-> `%s` declared here: %s:%i",
1283                     fval->name, fval->desc, fval->name, ast_ctx(fun).file,
1284                     ast_ctx(fun).line);
1285         }
1286
1287         if (vec_size(fun->params) != paramcount &&
1288             !((fun->flags & AST_FLAG_VARIADIC) &&
1289               vec_size(fun->params) < paramcount))
1290         {
1291             const char *fewmany = (vec_size(fun->params) > paramcount) ? "few" : "many";
1292             if (fval)
1293                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1294                                      "too %s parameters for call to %s: expected %i, got %i\n"
1295                                      " -> `%s` has been declared here: %s:%i",
1296                                      fewmany, fval->name, (int)vec_size(fun->params), (int)paramcount,
1297                                      fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line);
1298             else
1299                 return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT,
1300                                      "too %s parameters for function call: expected %i, got %i\n"
1301                                      " -> it has been declared here: %s:%i",
1302                                      fewmany, (int)vec_size(fun->params), (int)paramcount,
1303                                      ast_ctx(fun).file, (int)ast_ctx(fun).line);
1304         }
1305     }
1306
1307     return true;
1308 }
1309
1310 static bool parser_close_paren(parser_t *parser, shunt *sy)
1311 {
1312     if (!vec_size(sy->ops)) {
1313         parseerror(parser, "unmatched closing paren");
1314         return false;
1315     }
1316
1317     while (vec_size(sy->ops)) {
1318         if (vec_last(sy->ops).isparen) {
1319             if (vec_last(sy->paren) == PAREN_FUNC) {
1320                 vec_pop(sy->paren);
1321                 if (!parser_close_call(parser, sy))
1322                     return false;
1323                 break;
1324             }
1325             if (vec_last(sy->paren) == PAREN_EXPR) {
1326                 vec_pop(sy->paren);
1327                 if (!vec_size(sy->out)) {
1328                     compile_error(vec_last(sy->ops).ctx, "empty paren expression");
1329                     vec_shrinkby(sy->ops, 1);
1330                     return false;
1331                 }
1332                 vec_shrinkby(sy->ops, 1);
1333                 break;
1334             }
1335             if (vec_last(sy->paren) == PAREN_INDEX) {
1336                 vec_pop(sy->paren);
1337                 /* pop off the parenthesis */
1338                 vec_shrinkby(sy->ops, 1);
1339                 /* then apply the index operator */
1340                 if (!parser_sy_apply_operator(parser, sy))
1341                     return false;
1342                 break;
1343             }
1344             if (vec_last(sy->paren) == PAREN_TERNARY1) {
1345                 vec_last(sy->paren) = PAREN_TERNARY2;
1346                 /* pop off the parenthesis */
1347                 vec_shrinkby(sy->ops, 1);
1348                 break;
1349             }
1350             compile_error(vec_last(sy->ops).ctx, "invalid parenthesis");
1351             return false;
1352         }
1353         if (!parser_sy_apply_operator(parser, sy))
1354             return false;
1355     }
1356     return true;
1357 }
1358
1359 static void parser_reclassify_token(parser_t *parser)
1360 {
1361     size_t i;
1362     if (parser->tok >= TOKEN_START)
1363         return;
1364     for (i = 0; i < operator_count; ++i) {
1365         if (!strcmp(parser_tokval(parser), operators[i].op)) {
1366             parser->tok = TOKEN_OPERATOR;
1367             return;
1368         }
1369     }
1370 }
1371
1372 static ast_expression* parse_vararg_do(parser_t *parser)
1373 {
1374     ast_expression *idx, *out;
1375     ast_value      *typevar;
1376     ast_value      *funtype = parser->function->vtype;
1377     lex_ctx_t         ctx     = parser_ctx(parser);
1378
1379     if (!parser->function->varargs) {
1380         parseerror(parser, "function has no variable argument list");
1381         return NULL;
1382     }
1383
1384     if (!parser_next(parser) || parser->tok != '(') {
1385         parseerror(parser, "expected parameter index and type in parenthesis");
1386         return NULL;
1387     }
1388     if (!parser_next(parser)) {
1389         parseerror(parser, "error parsing parameter index");
1390         return NULL;
1391     }
1392
1393     idx = parse_expression_leave(parser, true, false, false);
1394     if (!idx)
1395         return NULL;
1396
1397     if (parser->tok != ',') {
1398         if (parser->tok != ')') {
1399             ast_unref(idx);
1400             parseerror(parser, "expected comma after parameter index");
1401             return NULL;
1402         }
1403         /* vararg piping: ...(start) */
1404         out = (ast_expression*)ast_argpipe_new(ctx, idx);
1405         return out;
1406     }
1407
1408     if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
1409         ast_unref(idx);
1410         parseerror(parser, "expected typename for vararg");
1411         return NULL;
1412     }
1413
1414     typevar = parse_typename(parser, NULL, NULL);
1415     if (!typevar) {
1416         ast_unref(idx);
1417         return NULL;
1418     }
1419
1420     if (parser->tok != ')') {
1421         ast_unref(idx);
1422         ast_delete(typevar);
1423         parseerror(parser, "expected closing paren");
1424         return NULL;
1425     }
1426
1427     if (funtype->expression.varparam &&
1428         !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
1429     {
1430         char ty1[1024];
1431         char ty2[1024];
1432         ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
1433         ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
1434         compile_error(ast_ctx(typevar),
1435                       "function was declared to take varargs of type `%s`, requested type is: %s",
1436                       ty2, ty1);
1437     }
1438
1439     out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx);
1440     ast_type_adopt(out, typevar);
1441     ast_delete(typevar);
1442     return out;
1443 }
1444
1445 static ast_expression* parse_vararg(parser_t *parser)
1446 {
1447     bool           old_noops = parser->lex->flags.noops;
1448
1449     ast_expression *out;
1450
1451     parser->lex->flags.noops = true;
1452     out = parse_vararg_do(parser);
1453
1454     parser->lex->flags.noops = old_noops;
1455     return out;
1456 }
1457
1458 /* not to be exposed */
1459 extern bool ftepp_predef_exists(const char *name);
1460
1461 static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
1462 {
1463     if (OPTS_FLAG(TRANSLATABLE_STRINGS) &&
1464         parser->tok == TOKEN_IDENT &&
1465         !strcmp(parser_tokval(parser), "_"))
1466     {
1467         /* a translatable string */
1468         ast_value *val;
1469
1470         parser->lex->flags.noops = true;
1471         if (!parser_next(parser) || parser->tok != '(') {
1472             parseerror(parser, "use _(\"string\") to create a translatable string constant");
1473             return false;
1474         }
1475         parser->lex->flags.noops = false;
1476         if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
1477             parseerror(parser, "expected a constant string in translatable-string extension");
1478             return false;
1479         }
1480         val = (ast_value*)fold_constgen_string(parser->fold, parser_tokval(parser), true);
1481         if (!val)
1482             return false;
1483         vec_push(sy->out, syexp(parser_ctx(parser), (ast_expression*)val));
1484
1485         if (!parser_next(parser) || parser->tok != ')') {
1486             parseerror(parser, "expected closing paren after translatable string");
1487             return false;
1488         }
1489         return true;
1490     }
1491     else if (parser->tok == TOKEN_DOTS)
1492     {
1493         ast_expression *va;
1494         if (!OPTS_FLAG(VARIADIC_ARGS)) {
1495             parseerror(parser, "cannot access varargs (try -fvariadic-args)");
1496             return false;
1497         }
1498         va = parse_vararg(parser);
1499         if (!va)
1500             return false;
1501         vec_push(sy->out, syexp(parser_ctx(parser), va));
1502         return true;
1503     }
1504     else if (parser->tok == TOKEN_FLOATCONST) {
1505         ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f));
1506         if (!val)
1507             return false;
1508         vec_push(sy->out, syexp(parser_ctx(parser), val));
1509         return true;
1510     }
1511     else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) {
1512         ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i));
1513         if (!val)
1514             return false;
1515         vec_push(sy->out, syexp(parser_ctx(parser), val));
1516         return true;
1517     }
1518     else if (parser->tok == TOKEN_STRINGCONST) {
1519         ast_expression *val = fold_constgen_string(parser->fold, parser_tokval(parser), false);
1520         if (!val)
1521             return false;
1522         vec_push(sy->out, syexp(parser_ctx(parser), val));
1523         return true;
1524     }
1525     else if (parser->tok == TOKEN_VECTORCONST) {
1526         ast_expression *val = fold_constgen_vector(parser->fold, parser_token(parser)->constval.v);
1527         if (!val)
1528             return false;
1529         vec_push(sy->out, syexp(parser_ctx(parser), val));
1530         return true;
1531     }
1532     else if (parser->tok == TOKEN_IDENT)
1533     {
1534         const char     *ctoken = parser_tokval(parser);
1535         ast_expression *prev = vec_size(sy->out) ? vec_last(sy->out).out : NULL;
1536         ast_expression *var;
1537         /* a_vector.{x,y,z} */
1538         if (!vec_size(sy->ops) ||
1539             !vec_last(sy->ops).etype ||
1540             operators[vec_last(sy->ops).etype-1].id != opid1('.') ||
1541             (prev >= intrinsic_debug_typestring &&
1542              prev <= intrinsic_debug_typestring))
1543         {
1544             /* When adding more intrinsics, fix the above condition */
1545             prev = NULL;
1546         }
1547         if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1])
1548         {
1549             var = (ast_expression*)parser->const_vec[ctoken[0]-'x'];
1550         } else {
1551             var = parser_find_var(parser, parser_tokval(parser));
1552             if (!var)
1553                 var = parser_find_field(parser, parser_tokval(parser));
1554         }
1555         if (!var && with_labels) {
1556             var = (ast_expression*)parser_find_label(parser, parser_tokval(parser));
1557             if (!with_labels) {
1558                 ast_label *lbl = ast_label_new(parser_ctx(parser), parser_tokval(parser), true);
1559                 var = (ast_expression*)lbl;
1560                 vec_push(parser->labels, lbl);
1561             }
1562         }
1563         if (!var && !strcmp(parser_tokval(parser), "__FUNC__"))
1564             var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false);
1565         if (!var) {
1566             /* intrinsics */
1567             if (!strcmp(parser_tokval(parser), "__builtin_debug_typestring")) {
1568                 var = (ast_expression*)intrinsic_debug_typestring;
1569             }
1570             /* now we try for the real intrinsic hashtable. If the string
1571              * begins with __builtin, we simply skip past it, otherwise we
1572              * use the identifier as is.
1573              */
1574             else if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
1575                 var = intrin_func(parser, parser_tokval(parser) + 10 /* skip __builtin */);
1576             }
1577
1578             if (!var) {
1579                 char *correct = NULL;
1580                 size_t i;
1581
1582                 /*
1583                  * sometimes people use preprocessing predefs without enabling them
1584                  * i've done this thousands of times already myself.  Lets check for
1585                  * it in the predef table.  And diagnose it better :)
1586                  */
1587                 if (!OPTS_FLAG(FTEPP_PREDEFS) && ftepp_predef_exists(parser_tokval(parser))) {
1588                     parseerror(parser, "unexpected identifier: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
1589                     return false;
1590                 }
1591
1592                 /*
1593                  * TODO: determine the best score for the identifier: be it
1594                  * a variable, a field.
1595                  *
1596                  * We should also consider adding correction tables for
1597                  * other things as well.
1598                  */
1599                 if (OPTS_OPTION_BOOL(OPTION_CORRECTION) && strlen(parser_tokval(parser)) <= 16) {
1600                     correction_t corr;
1601                     correct_init(&corr);
1602
1603                     for (i = 0; i < vec_size(parser->correct_variables); i++) {
1604                         correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser));
1605                         if (strcmp(correct, parser_tokval(parser))) {
1606                             break;
1607                         } else  {
1608                             mem_d(correct);
1609                             correct = NULL;
1610                         }
1611                     }
1612                     correct_free(&corr);
1613
1614                     if (correct) {
1615                         parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct);
1616                         mem_d(correct);
1617                         return false;
1618                     }
1619                 }
1620                 parseerror(parser, "unexpected identifier: %s", parser_tokval(parser));
1621                 return false;
1622             }
1623         }
1624         else
1625         {
1626             if (ast_istype(var, ast_value)) {
1627                 ((ast_value*)var)->uses++;
1628             }
1629             else if (ast_istype(var, ast_member)) {
1630                 ast_member *mem = (ast_member*)var;
1631                 if (ast_istype(mem->owner, ast_value))
1632                     ((ast_value*)(mem->owner))->uses++;
1633             }
1634         }
1635         vec_push(sy->out, syexp(parser_ctx(parser), var));
1636         return true;
1637     }
1638     parseerror(parser, "unexpected token `%s`", parser_tokval(parser));
1639     return false;
1640 }
1641
1642 static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels)
1643 {
1644     ast_expression *expr = NULL;
1645     shunt sy;
1646     size_t i;
1647     bool wantop = false;
1648     /* only warn once about an assignment in a truth value because the current code
1649      * would trigger twice on: if(a = b && ...), once for the if-truth-value, once for the && part
1650      */
1651     bool warn_truthvalue = true;
1652
1653     /* count the parens because an if starts with one, so the
1654      * end of a condition is an unmatched closing paren
1655      */
1656     int ternaries = 0;
1657
1658     memset(&sy, 0, sizeof(sy));
1659
1660     parser->lex->flags.noops = false;
1661
1662     parser_reclassify_token(parser);
1663
1664     while (true)
1665     {
1666         if (parser->tok == TOKEN_TYPENAME) {
1667             parseerror(parser, "unexpected typename `%s`", parser_tokval(parser));
1668             goto onerr;
1669         }
1670
1671         if (parser->tok == TOKEN_OPERATOR)
1672         {
1673             /* classify the operator */
1674             const oper_info *op;
1675             const oper_info *olast = NULL;
1676             size_t o;
1677             for (o = 0; o < operator_count; ++o) {
1678                 if (((!(operators[o].flags & OP_PREFIX) == !!wantop)) &&
1679                     /* !(operators[o].flags & OP_SUFFIX) && / * remove this */
1680                     !strcmp(parser_tokval(parser), operators[o].op))
1681                 {
1682                     break;
1683                 }
1684             }
1685             if (o == operator_count) {
1686                 compile_error(parser_ctx(parser), "unknown operator: %s", parser_tokval(parser));
1687                 goto onerr;
1688             }
1689             /* found an operator */
1690             op = &operators[o];
1691
1692             /* when declaring variables, a comma starts a new variable */
1693             if (op->id == opid1(',') && !vec_size(sy.paren) && stopatcomma) {
1694                 /* fixup the token */
1695                 parser->tok = ',';
1696                 break;
1697             }
1698
1699             /* a colon without a pervious question mark cannot be a ternary */
1700             if (!ternaries && op->id == opid2(':','?')) {
1701                 parser->tok = ':';
1702                 break;
1703             }
1704
1705             if (op->id == opid1(',')) {
1706                 if (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1707                     (void)!parsewarning(parser, WARN_TERNARY_PRECEDENCE, "suggesting parenthesis around ternary expression");
1708                 }
1709             }
1710
1711             if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1712                 olast = &operators[vec_last(sy.ops).etype-1];
1713
1714 #define IsAssignOp(x) (\
1715                 (x) == opid1('=') || \
1716                 (x) == opid2('+','=') || \
1717                 (x) == opid2('-','=') || \
1718                 (x) == opid2('*','=') || \
1719                 (x) == opid2('/','=') || \
1720                 (x) == opid2('%','=') || \
1721                 (x) == opid2('&','=') || \
1722                 (x) == opid2('|','=') || \
1723                 (x) == opid3('&','~','=') \
1724                 )
1725             if (warn_truthvalue) {
1726                 if ( (olast && IsAssignOp(olast->id) && (op->id == opid2('&','&') || op->id == opid2('|','|'))) ||
1727                      (olast && IsAssignOp(op->id) && (olast->id == opid2('&','&') || olast->id == opid2('|','|'))) ||
1728                      (truthvalue && !vec_size(sy.paren) && IsAssignOp(op->id))
1729                    )
1730                 {
1731                     (void)!parsewarning(parser, WARN_PARENTHESIS, "suggesting parenthesis around assignment used as truth value");
1732                     warn_truthvalue = false;
1733                 }
1734             }
1735
1736             while (olast && (
1737                     (op->prec < olast->prec) ||
1738                     (op->assoc == ASSOC_LEFT && op->prec <= olast->prec) ) )
1739             {
1740                 if (!parser_sy_apply_operator(parser, &sy))
1741                     goto onerr;
1742                 if (vec_size(sy.ops) && !vec_last(sy.ops).isparen)
1743                     olast = &operators[vec_last(sy.ops).etype-1];
1744                 else
1745                     olast = NULL;
1746             }
1747
1748             if (op->id == opid1('(')) {
1749                 if (wantop) {
1750                     size_t sycount = vec_size(sy.out);
1751                     /* we expected an operator, this is the function-call operator */
1752                     vec_push(sy.paren, PAREN_FUNC);
1753                     vec_push(sy.ops, syparen(parser_ctx(parser), sycount-1));
1754                     vec_push(sy.argc, 0);
1755                 } else {
1756                     vec_push(sy.paren, PAREN_EXPR);
1757                     vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1758                 }
1759                 wantop = false;
1760             } else if (op->id == opid1('[')) {
1761                 if (!wantop) {
1762                     parseerror(parser, "unexpected array subscript");
1763                     goto onerr;
1764                 }
1765                 vec_push(sy.paren, PAREN_INDEX);
1766                 /* push both the operator and the paren, this makes life easier */
1767                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1768                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1769                 wantop = false;
1770             } else if (op->id == opid2('?',':')) {
1771                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1772                 vec_push(sy.ops, syparen(parser_ctx(parser), 0));
1773                 wantop = false;
1774                 ++ternaries;
1775                 vec_push(sy.paren, PAREN_TERNARY1);
1776             } else if (op->id == opid2(':','?')) {
1777                 if (!vec_size(sy.paren)) {
1778                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1779                     goto onerr;
1780                 }
1781                 if (vec_last(sy.paren) != PAREN_TERNARY1) {
1782                     parseerror(parser, "unexpected colon outside ternary expression (missing parenthesis?)");
1783                     goto onerr;
1784                 }
1785                 if (!parser_close_paren(parser, &sy))
1786                     goto onerr;
1787                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1788                 wantop = false;
1789                 --ternaries;
1790             } else {
1791                 vec_push(sy.ops, syop(parser_ctx(parser), op));
1792                 wantop = !!(op->flags & OP_SUFFIX);
1793             }
1794         }
1795         else if (parser->tok == ')') {
1796             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1797                 if (!parser_sy_apply_operator(parser, &sy))
1798                     goto onerr;
1799             }
1800             if (!vec_size(sy.paren))
1801                 break;
1802             if (wantop) {
1803                 if (vec_last(sy.paren) == PAREN_TERNARY1) {
1804                     parseerror(parser, "mismatched parentheses (closing paren in ternary expression?)");
1805                     goto onerr;
1806                 }
1807                 if (!parser_close_paren(parser, &sy))
1808                     goto onerr;
1809             } else {
1810                 /* must be a function call without parameters */
1811                 if (vec_last(sy.paren) != PAREN_FUNC) {
1812                     parseerror(parser, "closing paren in invalid position");
1813                     goto onerr;
1814                 }
1815                 if (!parser_close_paren(parser, &sy))
1816                     goto onerr;
1817             }
1818             wantop = true;
1819         }
1820         else if (parser->tok == '(') {
1821             parseerror(parser, "internal error: '(' should be classified as operator");
1822             goto onerr;
1823         }
1824         else if (parser->tok == '[') {
1825             parseerror(parser, "internal error: '[' should be classified as operator");
1826             goto onerr;
1827         }
1828         else if (parser->tok == ']') {
1829             while (vec_size(sy.paren) && vec_last(sy.paren) == PAREN_TERNARY2) {
1830                 if (!parser_sy_apply_operator(parser, &sy))
1831                     goto onerr;
1832             }
1833             if (!vec_size(sy.paren))
1834                 break;
1835             if (vec_last(sy.paren) != PAREN_INDEX) {
1836                 parseerror(parser, "mismatched parentheses, unexpected ']'");
1837                 goto onerr;
1838             }
1839             if (!parser_close_paren(parser, &sy))
1840                 goto onerr;
1841             wantop = true;
1842         }
1843         else if (!wantop) {
1844             if (!parse_sya_operand(parser, &sy, with_labels))
1845                 goto onerr;
1846 #if 0
1847             if (vec_size(sy.paren) && vec_last(sy.ops).isparen && vec_last(sy.paren) == PAREN_FUNC)
1848                 vec_last(sy.argc)++;
1849 #endif
1850             wantop = true;
1851         }
1852         else {
1853             /* in this case we might want to allow constant string concatenation */
1854             bool concatenated = false;
1855             if (parser->tok == TOKEN_STRINGCONST && vec_size(sy.out)) {
1856                 ast_expression *lexpr = vec_last(sy.out).out;
1857                 if (ast_istype(lexpr, ast_value)) {
1858                     ast_value *last = (ast_value*)lexpr;
1859                     if (last->isimm == true && last->cvq == CV_CONST &&
1860                         last->hasvalue && last->expression.vtype == TYPE_STRING)
1861                     {
1862                         char *newstr = NULL;
1863                         util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser));
1864                         vec_last(sy.out).out = (ast_expression*)fold_constgen_string(parser->fold, newstr, false);
1865                         mem_d(newstr);
1866                         concatenated = true;
1867                     }
1868                 }
1869             }
1870             if (!concatenated) {
1871                 parseerror(parser, "expected operator or end of statement");
1872                 goto onerr;
1873             }
1874         }
1875
1876         if (!parser_next(parser)) {
1877             goto onerr;
1878         }
1879         if (parser->tok == ';' ||
1880             ((!vec_size(sy.paren) || (vec_size(sy.paren) == 1 && vec_last(sy.paren) == PAREN_TERNARY2)) &&
1881             (parser->tok == ']' || parser->tok == ')' || parser->tok == '}')))
1882         {
1883             break;
1884         }
1885     }
1886
1887     while (vec_size(sy.ops)) {
1888         if (!parser_sy_apply_operator(parser, &sy))
1889             goto onerr;
1890     }
1891
1892     parser->lex->flags.noops = true;
1893     if (vec_size(sy.out) != 1) {
1894         parseerror(parser, "expression with not 1 but %lu output values...", (unsigned long) vec_size(sy.out));
1895         expr = NULL;
1896     } else
1897         expr = sy.out[0].out;
1898     vec_free(sy.out);
1899     vec_free(sy.ops);
1900     if (vec_size(sy.paren)) {
1901         parseerror(parser, "internal error: vec_size(sy.paren) = %lu", (unsigned long)vec_size(sy.paren));
1902         return NULL;
1903     }
1904     vec_free(sy.paren);
1905     vec_free(sy.argc);
1906     return expr;
1907
1908 onerr:
1909     parser->lex->flags.noops = true;
1910     for (i = 0; i < vec_size(sy.out); ++i) {
1911         if (sy.out[i].out)
1912             ast_unref(sy.out[i].out);
1913     }
1914     vec_free(sy.out);
1915     vec_free(sy.ops);
1916     vec_free(sy.paren);
1917     vec_free(sy.argc);
1918     return NULL;
1919 }
1920
1921 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels)
1922 {
1923     ast_expression *e = parse_expression_leave(parser, stopatcomma, false, with_labels);
1924     if (!e)
1925         return NULL;
1926     if (parser->tok != ';') {
1927         parseerror(parser, "semicolon expected after expression");
1928         ast_unref(e);
1929         return NULL;
1930     }
1931     if (!parser_next(parser)) {
1932         ast_unref(e);
1933         return NULL;
1934     }
1935     return e;
1936 }
1937
1938 static void parser_enterblock(parser_t *parser)
1939 {
1940     vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
1941     vec_push(parser->_blocklocals, vec_size(parser->_locals));
1942     vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
1943     vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs));
1944     vec_push(parser->_block_ctx, parser_ctx(parser));
1945
1946     /* corrector */
1947     vec_push(parser->correct_variables, correct_trie_new());
1948     vec_push(parser->correct_variables_score, NULL);
1949 }
1950
1951 static bool parser_leaveblock(parser_t *parser)
1952 {
1953     bool   rv = true;
1954     size_t locals, typedefs;
1955
1956     if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
1957         parseerror(parser, "internal error: parser_leaveblock with no block");
1958         return false;
1959     }
1960
1961     util_htdel(vec_last(parser->variables));
1962     correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score));
1963
1964     vec_pop(parser->variables);
1965     vec_pop(parser->correct_variables);
1966     vec_pop(parser->correct_variables_score);
1967     if (!vec_size(parser->_blocklocals)) {
1968         parseerror(parser, "internal error: parser_leaveblock with no block (2)");
1969         return false;
1970     }
1971
1972     locals = vec_last(parser->_blocklocals);
1973     vec_pop(parser->_blocklocals);
1974     while (vec_size(parser->_locals) != locals) {
1975         ast_expression *e = vec_last(parser->_locals);
1976         ast_value      *v = (ast_value*)e;
1977         vec_pop(parser->_locals);
1978         if (ast_istype(e, ast_value) && !v->uses) {
1979             if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
1980                 rv = false;
1981         }
1982     }
1983
1984     typedefs = vec_last(parser->_blocktypedefs);
1985     while (vec_size(parser->_typedefs) != typedefs) {
1986         ast_delete(vec_last(parser->_typedefs));
1987         vec_pop(parser->_typedefs);
1988     }
1989     util_htdel(vec_last(parser->typedefs));
1990     vec_pop(parser->typedefs);
1991
1992     vec_pop(parser->_block_ctx);
1993
1994     return rv;
1995 }
1996
1997 static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
1998 {
1999     vec_push(parser->_locals, e);
2000     util_htset(vec_last(parser->variables), name, (void*)e);
2001
2002     /* corrector */
2003     correct_add (
2004          vec_last(parser->correct_variables),
2005         &vec_last(parser->correct_variables_score),
2006         name
2007     );
2008 }
2009
2010 static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e)
2011 {
2012     vec_push(parser->globals, e);
2013     util_htset(parser->htglobals, name, e);
2014
2015     /* corrector */
2016     correct_add (
2017          parser->correct_variables[0],
2018         &parser->correct_variables_score[0],
2019         name
2020     );
2021 }
2022
2023 static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
2024 {
2025     bool       ifnot = false;
2026     ast_unary *unary;
2027     ast_expression *prev;
2028
2029     if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) {
2030         char ty[1024];
2031         ast_type_to_string(cond, ty, sizeof(ty));
2032         compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty);
2033     }
2034
2035     if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING)
2036     {
2037         prev = cond;
2038         cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
2039         if (!cond) {
2040             ast_unref(prev);
2041             parseerror(parser, "internal error: failed to process condition");
2042             return NULL;
2043         }
2044         ifnot = !ifnot;
2045     }
2046     else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR)
2047     {
2048         /* vector types need to be cast to true booleans */
2049         ast_binary *bin = (ast_binary*)cond;
2050         if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
2051         {
2052             /* in perl-logic, AND and OR take care of the -fcorrect-logic */
2053             prev = cond;
2054             cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
2055             if (!cond) {
2056                 ast_unref(prev);
2057                 parseerror(parser, "internal error: failed to process condition");
2058                 return NULL;
2059             }
2060             ifnot = !ifnot;
2061         }
2062     }
2063
2064     unary = (ast_unary*)cond;
2065     /* ast_istype dereferences cond, should test here for safety */
2066     while (cond && ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
2067     {
2068         cond = unary->operand;
2069         unary->operand = NULL;
2070         ast_delete(unary);
2071         ifnot = !ifnot;
2072         unary = (ast_unary*)cond;
2073     }
2074
2075     if (!cond)
2076         parseerror(parser, "internal error: failed to process condition");
2077
2078     if (ifnot) *_ifnot = !*_ifnot;
2079     return cond;
2080 }
2081
2082 static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out)
2083 {
2084     ast_ifthen *ifthen;
2085     ast_expression *cond, *ontrue = NULL, *onfalse = NULL;
2086     bool ifnot = false;
2087
2088     lex_ctx_t ctx = parser_ctx(parser);
2089
2090     (void)block; /* not touching */
2091
2092     /* skip the 'if', parse an optional 'not' and check for an opening paren */
2093     if (!parser_next(parser)) {
2094         parseerror(parser, "expected condition or 'not'");
2095         return false;
2096     }
2097     if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "not")) {
2098         ifnot = true;
2099         if (!parser_next(parser)) {
2100             parseerror(parser, "expected condition in parenthesis");
2101             return false;
2102         }
2103     }
2104     if (parser->tok != '(') {
2105         parseerror(parser, "expected 'if' condition in parenthesis");
2106         return false;
2107     }
2108     /* parse into the expression */
2109     if (!parser_next(parser)) {
2110         parseerror(parser, "expected 'if' condition after opening paren");
2111         return false;
2112     }
2113     /* parse the condition */
2114     cond = parse_expression_leave(parser, false, true, false);
2115     if (!cond)
2116         return false;
2117     /* closing paren */
2118     if (parser->tok != ')') {
2119         parseerror(parser, "expected closing paren after 'if' condition");
2120         ast_unref(cond);
2121         return false;
2122     }
2123     /* parse into the 'then' branch */
2124     if (!parser_next(parser)) {
2125         parseerror(parser, "expected statement for on-true branch of 'if'");
2126         ast_unref(cond);
2127         return false;
2128     }
2129     if (!parse_statement_or_block(parser, &ontrue)) {
2130         ast_unref(cond);
2131         return false;
2132     }
2133     if (!ontrue)
2134         ontrue = (ast_expression*)ast_block_new(parser_ctx(parser));
2135     /* check for an else */
2136     if (!strcmp(parser_tokval(parser), "else")) {
2137         /* parse into the 'else' branch */
2138         if (!parser_next(parser)) {
2139             parseerror(parser, "expected on-false branch after 'else'");
2140             ast_delete(ontrue);
2141             ast_unref(cond);
2142             return false;
2143         }
2144         if (!parse_statement_or_block(parser, &onfalse)) {
2145             ast_delete(ontrue);
2146             ast_unref(cond);
2147             return false;
2148         }
2149     }
2150
2151     cond = process_condition(parser, cond, &ifnot);
2152     if (!cond) {
2153         if (ontrue)  ast_delete(ontrue);
2154         if (onfalse) ast_delete(onfalse);
2155         return false;
2156     }
2157
2158     if (ifnot)
2159         ifthen = ast_ifthen_new(ctx, cond, onfalse, ontrue);
2160     else
2161         ifthen = ast_ifthen_new(ctx, cond, ontrue, onfalse);
2162     *out = (ast_expression*)ifthen;
2163     return true;
2164 }
2165
2166 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out);
2167 static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out)
2168 {
2169     bool rv;
2170     char *label = NULL;
2171
2172     /* skip the 'while' and get the body */
2173     if (!parser_next(parser)) {
2174         if (OPTS_FLAG(LOOP_LABELS))
2175             parseerror(parser, "expected loop label or 'while' condition in parenthesis");
2176         else
2177             parseerror(parser, "expected 'while' condition in parenthesis");
2178         return false;
2179     }
2180
2181     if (parser->tok == ':') {
2182         if (!OPTS_FLAG(LOOP_LABELS))
2183             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2184         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2185             parseerror(parser, "expected loop label");
2186             return false;
2187         }
2188         label = util_strdup(parser_tokval(parser));
2189         if (!parser_next(parser)) {
2190             mem_d(label);
2191             parseerror(parser, "expected 'while' condition in parenthesis");
2192             return false;
2193         }
2194     }
2195
2196     if (parser->tok != '(') {
2197         parseerror(parser, "expected 'while' condition in parenthesis");
2198         return false;
2199     }
2200
2201     vec_push(parser->breaks, label);
2202     vec_push(parser->continues, label);
2203
2204     rv = parse_while_go(parser, block, out);
2205     if (label)
2206         mem_d(label);
2207     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2208         parseerror(parser, "internal error: label stack corrupted");
2209         rv = false;
2210         ast_delete(*out);
2211         *out = NULL;
2212     }
2213     else {
2214         vec_pop(parser->breaks);
2215         vec_pop(parser->continues);
2216     }
2217     return rv;
2218 }
2219
2220 static bool parse_while_go(parser_t *parser, ast_block *block, ast_expression **out)
2221 {
2222     ast_loop *aloop;
2223     ast_expression *cond, *ontrue;
2224
2225     bool ifnot = false;
2226
2227     lex_ctx_t ctx = parser_ctx(parser);
2228
2229     (void)block; /* not touching */
2230
2231     /* parse into the expression */
2232     if (!parser_next(parser)) {
2233         parseerror(parser, "expected 'while' condition after opening paren");
2234         return false;
2235     }
2236     /* parse the condition */
2237     cond = parse_expression_leave(parser, false, true, false);
2238     if (!cond)
2239         return false;
2240     /* closing paren */
2241     if (parser->tok != ')') {
2242         parseerror(parser, "expected closing paren after 'while' condition");
2243         ast_unref(cond);
2244         return false;
2245     }
2246     /* parse into the 'then' branch */
2247     if (!parser_next(parser)) {
2248         parseerror(parser, "expected while-loop body");
2249         ast_unref(cond);
2250         return false;
2251     }
2252     if (!parse_statement_or_block(parser, &ontrue)) {
2253         ast_unref(cond);
2254         return false;
2255     }
2256
2257     cond = process_condition(parser, cond, &ifnot);
2258     if (!cond) {
2259         ast_unref(ontrue);
2260         return false;
2261     }
2262     aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
2263     *out = (ast_expression*)aloop;
2264     return true;
2265 }
2266
2267 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out);
2268 static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
2269 {
2270     bool rv;
2271     char *label = NULL;
2272
2273     /* skip the 'do' and get the body */
2274     if (!parser_next(parser)) {
2275         if (OPTS_FLAG(LOOP_LABELS))
2276             parseerror(parser, "expected loop label or body");
2277         else
2278             parseerror(parser, "expected loop body");
2279         return false;
2280     }
2281
2282     if (parser->tok == ':') {
2283         if (!OPTS_FLAG(LOOP_LABELS))
2284             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2285         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2286             parseerror(parser, "expected loop label");
2287             return false;
2288         }
2289         label = util_strdup(parser_tokval(parser));
2290         if (!parser_next(parser)) {
2291             mem_d(label);
2292             parseerror(parser, "expected loop body");
2293             return false;
2294         }
2295     }
2296
2297     vec_push(parser->breaks, label);
2298     vec_push(parser->continues, label);
2299
2300     rv = parse_dowhile_go(parser, block, out);
2301     if (label)
2302         mem_d(label);
2303     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2304         parseerror(parser, "internal error: label stack corrupted");
2305         rv = false;
2306         /*
2307          * Test for NULL otherwise ast_delete dereferences null pointer
2308          * and boom.
2309          */
2310         if (*out)
2311             ast_delete(*out);
2312         *out = NULL;
2313     }
2314     else {
2315         vec_pop(parser->breaks);
2316         vec_pop(parser->continues);
2317     }
2318     return rv;
2319 }
2320
2321 static bool parse_dowhile_go(parser_t *parser, ast_block *block, ast_expression **out)
2322 {
2323     ast_loop *aloop;
2324     ast_expression *cond, *ontrue;
2325
2326     bool ifnot = false;
2327
2328     lex_ctx_t ctx = parser_ctx(parser);
2329
2330     (void)block; /* not touching */
2331
2332     if (!parse_statement_or_block(parser, &ontrue))
2333         return false;
2334
2335     /* expect the "while" */
2336     if (parser->tok != TOKEN_KEYWORD ||
2337         strcmp(parser_tokval(parser), "while"))
2338     {
2339         parseerror(parser, "expected 'while' and condition");
2340         ast_delete(ontrue);
2341         return false;
2342     }
2343
2344     /* skip the 'while' and check for opening paren */
2345     if (!parser_next(parser) || parser->tok != '(') {
2346         parseerror(parser, "expected 'while' condition in parenthesis");
2347         ast_delete(ontrue);
2348         return false;
2349     }
2350     /* parse into the expression */
2351     if (!parser_next(parser)) {
2352         parseerror(parser, "expected 'while' condition after opening paren");
2353         ast_delete(ontrue);
2354         return false;
2355     }
2356     /* parse the condition */
2357     cond = parse_expression_leave(parser, false, true, false);
2358     if (!cond)
2359         return false;
2360     /* closing paren */
2361     if (parser->tok != ')') {
2362         parseerror(parser, "expected closing paren after 'while' condition");
2363         ast_delete(ontrue);
2364         ast_unref(cond);
2365         return false;
2366     }
2367     /* parse on */
2368     if (!parser_next(parser) || parser->tok != ';') {
2369         parseerror(parser, "expected semicolon after condition");
2370         ast_delete(ontrue);
2371         ast_unref(cond);
2372         return false;
2373     }
2374
2375     if (!parser_next(parser)) {
2376         parseerror(parser, "parse error");
2377         ast_delete(ontrue);
2378         ast_unref(cond);
2379         return false;
2380     }
2381
2382     cond = process_condition(parser, cond, &ifnot);
2383     if (!cond) {
2384         ast_delete(ontrue);
2385         return false;
2386     }
2387     aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
2388     *out = (ast_expression*)aloop;
2389     return true;
2390 }
2391
2392 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out);
2393 static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
2394 {
2395     bool rv;
2396     char *label = NULL;
2397
2398     /* skip the 'for' and check for opening paren */
2399     if (!parser_next(parser)) {
2400         if (OPTS_FLAG(LOOP_LABELS))
2401             parseerror(parser, "expected loop label or 'for' expressions in parenthesis");
2402         else
2403             parseerror(parser, "expected 'for' expressions in parenthesis");
2404         return false;
2405     }
2406
2407     if (parser->tok == ':') {
2408         if (!OPTS_FLAG(LOOP_LABELS))
2409             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2410         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2411             parseerror(parser, "expected loop label");
2412             return false;
2413         }
2414         label = util_strdup(parser_tokval(parser));
2415         if (!parser_next(parser)) {
2416             mem_d(label);
2417             parseerror(parser, "expected 'for' expressions in parenthesis");
2418             return false;
2419         }
2420     }
2421
2422     if (parser->tok != '(') {
2423         parseerror(parser, "expected 'for' expressions in parenthesis");
2424         return false;
2425     }
2426
2427     vec_push(parser->breaks, label);
2428     vec_push(parser->continues, label);
2429
2430     rv = parse_for_go(parser, block, out);
2431     if (label)
2432         mem_d(label);
2433     if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) {
2434         parseerror(parser, "internal error: label stack corrupted");
2435         rv = false;
2436         ast_delete(*out);
2437         *out = NULL;
2438     }
2439     else {
2440         vec_pop(parser->breaks);
2441         vec_pop(parser->continues);
2442     }
2443     return rv;
2444 }
2445 static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **out)
2446 {
2447     ast_loop       *aloop;
2448     ast_expression *initexpr, *cond, *increment, *ontrue;
2449     ast_value      *typevar;
2450
2451     bool ifnot  = false;
2452
2453     lex_ctx_t ctx = parser_ctx(parser);
2454
2455     parser_enterblock(parser);
2456
2457     initexpr  = NULL;
2458     cond      = NULL;
2459     increment = NULL;
2460     ontrue    = NULL;
2461
2462     /* parse into the expression */
2463     if (!parser_next(parser)) {
2464         parseerror(parser, "expected 'for' initializer after opening paren");
2465         goto onerr;
2466     }
2467
2468     typevar = NULL;
2469     if (parser->tok == TOKEN_IDENT)
2470         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
2471
2472     if (typevar || parser->tok == TOKEN_TYPENAME) {
2473 #if 0
2474         if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_GMQCC) {
2475             if (parsewarning(parser, WARN_EXTENSIONS,
2476                              "current standard does not allow variable declarations in for-loop initializers"))
2477                 goto onerr;
2478         }
2479 #endif
2480         if (!parse_variable(parser, block, true, CV_VAR, typevar, false, false, 0, NULL))
2481             goto onerr;
2482     }
2483     else if (parser->tok != ';')
2484     {
2485         initexpr = parse_expression_leave(parser, false, false, false);
2486         if (!initexpr)
2487             goto onerr;
2488     }
2489
2490     /* move on to condition */
2491     if (parser->tok != ';') {
2492         parseerror(parser, "expected semicolon after for-loop initializer");
2493         goto onerr;
2494     }
2495     if (!parser_next(parser)) {
2496         parseerror(parser, "expected for-loop condition");
2497         goto onerr;
2498     }
2499
2500     /* parse the condition */
2501     if (parser->tok != ';') {
2502         cond = parse_expression_leave(parser, false, true, false);
2503         if (!cond)
2504             goto onerr;
2505     }
2506
2507     /* move on to incrementor */
2508     if (parser->tok != ';') {
2509         parseerror(parser, "expected semicolon after for-loop initializer");
2510         goto onerr;
2511     }
2512     if (!parser_next(parser)) {
2513         parseerror(parser, "expected for-loop condition");
2514         goto onerr;
2515     }
2516
2517     /* parse the incrementor */
2518     if (parser->tok != ')') {
2519         lex_ctx_t condctx = parser_ctx(parser);
2520         increment = parse_expression_leave(parser, false, false, false);
2521         if (!increment)
2522             goto onerr;
2523         if (!ast_side_effects(increment)) {
2524             if (compile_warning(condctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
2525                 goto onerr;
2526         }
2527     }
2528
2529     /* closing paren */
2530     if (parser->tok != ')') {
2531         parseerror(parser, "expected closing paren after 'for-loop' incrementor");
2532         goto onerr;
2533     }
2534     /* parse into the 'then' branch */
2535     if (!parser_next(parser)) {
2536         parseerror(parser, "expected for-loop body");
2537         goto onerr;
2538     }
2539     if (!parse_statement_or_block(parser, &ontrue))
2540         goto onerr;
2541
2542     if (cond) {
2543         cond = process_condition(parser, cond, &ifnot);
2544         if (!cond)
2545             goto onerr;
2546     }
2547     aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
2548     *out = (ast_expression*)aloop;
2549
2550     if (!parser_leaveblock(parser)) {
2551         ast_delete(aloop);
2552         return false;
2553     }
2554     return true;
2555 onerr:
2556     if (initexpr)  ast_unref(initexpr);
2557     if (cond)      ast_unref(cond);
2558     if (increment) ast_unref(increment);
2559     (void)!parser_leaveblock(parser);
2560     return false;
2561 }
2562
2563 static bool parse_return(parser_t *parser, ast_block *block, ast_expression **out)
2564 {
2565     ast_expression *exp      = NULL;
2566     ast_expression *var      = NULL;
2567     ast_return     *ret      = NULL;
2568     ast_value      *retval   = parser->function->return_value;
2569     ast_value      *expected = parser->function->vtype;
2570
2571     lex_ctx_t ctx = parser_ctx(parser);
2572
2573     (void)block; /* not touching */
2574
2575     if (!parser_next(parser)) {
2576         parseerror(parser, "expected return expression");
2577         return false;
2578     }
2579
2580     /* return assignments */
2581     if (parser->tok == '=') {
2582         if (!OPTS_FLAG(RETURN_ASSIGNMENTS)) {
2583             parseerror(parser, "return assignments not activated, try using -freturn-assigments");
2584             return false;
2585         }
2586
2587         if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
2588             char ty1[1024];
2589             ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
2590             parseerror(parser, "invalid return type: `%s'", ty1);
2591             return false;
2592         }
2593
2594         if (!parser_next(parser)) {
2595             parseerror(parser, "expected return assignment expression");
2596             return false;
2597         }
2598
2599         if (!(exp = parse_expression_leave(parser, false, false, false)))
2600             return false;
2601
2602         /* prepare the return value */
2603         if (!retval) {
2604             retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
2605             ast_type_adopt(retval, expected->expression.next);
2606             parser->function->return_value = retval;
2607         }
2608
2609         if (!ast_compare_type(exp, (ast_expression*)retval)) {
2610             char ty1[1024], ty2[1024];
2611             ast_type_to_string(exp, ty1, sizeof(ty1));
2612             ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
2613             parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
2614         }
2615
2616         /* store to 'return' local variable */
2617         var = (ast_expression*)ast_store_new(
2618             ctx,
2619             type_store_instr[expected->expression.next->vtype],
2620             (ast_expression*)retval, exp);
2621
2622         if (!var) {
2623             ast_unref(exp);
2624             return false;
2625         }
2626
2627         if (parser->tok != ';')
2628             parseerror(parser, "missing semicolon after return assignment");
2629         else if (!parser_next(parser))
2630             parseerror(parser, "parse error after return assignment");
2631
2632         *out = var;
2633         return true;
2634     }
2635
2636     if (parser->tok != ';') {
2637         exp = parse_expression(parser, false, false);
2638         if (!exp)
2639             return false;
2640
2641         if (exp->vtype != TYPE_NIL &&
2642             exp->vtype != ((ast_expression*)expected)->next->vtype)
2643         {
2644             parseerror(parser, "return with invalid expression");
2645         }
2646
2647         ret = ast_return_new(ctx, exp);
2648         if (!ret) {
2649             ast_unref(exp);
2650             return false;
2651         }
2652     } else {
2653         if (!parser_next(parser))
2654             parseerror(parser, "parse error");
2655
2656         if (!retval && expected->expression.next->vtype != TYPE_VOID)
2657         {
2658             (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value");
2659         }
2660         ret = ast_return_new(ctx, (ast_expression*)retval);
2661     }
2662     *out = (ast_expression*)ret;
2663     return true;
2664 }
2665
2666 static bool parse_break_continue(parser_t *parser, ast_block *block, ast_expression **out, bool is_continue)
2667 {
2668     size_t       i;
2669     unsigned int levels = 0;
2670     lex_ctx_t      ctx = parser_ctx(parser);
2671     const char **loops = (is_continue ? parser->continues : parser->breaks);
2672
2673     (void)block; /* not touching */
2674     if (!parser_next(parser)) {
2675         parseerror(parser, "expected semicolon or loop label");
2676         return false;
2677     }
2678
2679     if (!vec_size(loops)) {
2680         if (is_continue)
2681             parseerror(parser, "`continue` can only be used inside loops");
2682         else
2683             parseerror(parser, "`break` can only be used inside loops or switches");
2684     }
2685
2686     if (parser->tok == TOKEN_IDENT) {
2687         if (!OPTS_FLAG(LOOP_LABELS))
2688             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2689         i = vec_size(loops);
2690         while (i--) {
2691             if (loops[i] && !strcmp(loops[i], parser_tokval(parser)))
2692                 break;
2693             if (!i) {
2694                 parseerror(parser, "no such loop to %s: `%s`",
2695                            (is_continue ? "continue" : "break out of"),
2696                            parser_tokval(parser));
2697                 return false;
2698             }
2699             ++levels;
2700         }
2701         if (!parser_next(parser)) {
2702             parseerror(parser, "expected semicolon");
2703             return false;
2704         }
2705     }
2706
2707     if (parser->tok != ';') {
2708         parseerror(parser, "expected semicolon");
2709         return false;
2710     }
2711
2712     if (!parser_next(parser))
2713         parseerror(parser, "parse error");
2714
2715     *out = (ast_expression*)ast_breakcont_new(ctx, is_continue, levels);
2716     return true;
2717 }
2718
2719 /* returns true when it was a variable qualifier, false otherwise!
2720  * on error, cvq is set to CV_WRONG
2721  */
2722 static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *noref, bool *is_static, uint32_t *_flags, char **message)
2723 {
2724     bool had_const    = false;
2725     bool had_var      = false;
2726     bool had_noref    = false;
2727     bool had_attrib   = false;
2728     bool had_static   = false;
2729     uint32_t flags    = 0;
2730
2731     *cvq = CV_NONE;
2732     for (;;) {
2733         if (parser->tok == TOKEN_ATTRIBUTE_OPEN) {
2734             had_attrib = true;
2735             /* parse an attribute */
2736             if (!parser_next(parser)) {
2737                 parseerror(parser, "expected attribute after `[[`");
2738                 *cvq = CV_WRONG;
2739                 return false;
2740             }
2741             if (!strcmp(parser_tokval(parser), "noreturn")) {
2742                 flags |= AST_FLAG_NORETURN;
2743                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2744                     parseerror(parser, "`noreturn` attribute has no parameters, expected `]]`");
2745                     *cvq = CV_WRONG;
2746                     return false;
2747                 }
2748             }
2749             else if (!strcmp(parser_tokval(parser), "noref")) {
2750                 had_noref = true;
2751                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2752                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2753                     *cvq = CV_WRONG;
2754                     return false;
2755                 }
2756             }
2757             else if (!strcmp(parser_tokval(parser), "inline")) {
2758                 flags |= AST_FLAG_INLINE;
2759                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2760                     parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
2761                     *cvq = CV_WRONG;
2762                     return false;
2763                 }
2764             }
2765             else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
2766                 flags   |= AST_FLAG_ALIAS;
2767                 *message = NULL;
2768
2769                 if (!parser_next(parser)) {
2770                     parseerror(parser, "parse error in attribute");
2771                     goto argerr;
2772                 }
2773
2774                 if (parser->tok == '(') {
2775                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2776                         parseerror(parser, "`alias` attribute missing parameter");
2777                         goto argerr;
2778                     }
2779
2780                     *message = util_strdup(parser_tokval(parser));
2781
2782                     if (!parser_next(parser)) {
2783                         parseerror(parser, "parse error in attribute");
2784                         goto argerr;
2785                     }
2786
2787                     if (parser->tok != ')') {
2788                         parseerror(parser, "`alias` attribute expected `)` after parameter");
2789                         goto argerr;
2790                     }
2791
2792                     if (!parser_next(parser)) {
2793                         parseerror(parser, "parse error in attribute");
2794                         goto argerr;
2795                     }
2796                 }
2797
2798                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2799                     parseerror(parser, "`alias` attribute expected `]]`");
2800                     goto argerr;
2801                 }
2802             }
2803             else if (!strcmp(parser_tokval(parser), "deprecated") && !(flags & AST_FLAG_DEPRECATED)) {
2804                 flags   |= AST_FLAG_DEPRECATED;
2805                 *message = NULL;
2806
2807                 if (!parser_next(parser)) {
2808                     parseerror(parser, "parse error in attribute");
2809                     goto argerr;
2810                 }
2811
2812                 if (parser->tok == '(') {
2813                     if (!parser_next(parser) || parser->tok != TOKEN_STRINGCONST) {
2814                         parseerror(parser, "`deprecated` attribute missing parameter");
2815                         goto argerr;
2816                     }
2817
2818                     *message = util_strdup(parser_tokval(parser));
2819
2820                     if (!parser_next(parser)) {
2821                         parseerror(parser, "parse error in attribute");
2822                         goto argerr;
2823                     }
2824
2825                     if(parser->tok != ')') {
2826                         parseerror(parser, "`deprecated` attribute expected `)` after parameter");
2827                         goto argerr;
2828                     }
2829
2830                     if (!parser_next(parser)) {
2831                         parseerror(parser, "parse error in attribute");
2832                         goto argerr;
2833                     }
2834                 }
2835                 /* no message */
2836                 if (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2837                     parseerror(parser, "`deprecated` attribute expected `]]`");
2838
2839                     argerr: /* ugly */
2840                     if (*message) mem_d(*message);
2841                     *message = NULL;
2842                     *cvq     = CV_WRONG;
2843                     return false;
2844                 }
2845             }
2846             else
2847             {
2848                 /* Skip tokens until we hit a ]] */
2849                 (void)!parsewarning(parser, WARN_UNKNOWN_ATTRIBUTE, "unknown attribute starting with `%s`", parser_tokval(parser));
2850                 while (parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
2851                     if (!parser_next(parser)) {
2852                         parseerror(parser, "error inside attribute");
2853                         *cvq = CV_WRONG;
2854                         return false;
2855                     }
2856                 }
2857             }
2858         }
2859         else if (with_local && !strcmp(parser_tokval(parser), "static"))
2860             had_static = true;
2861         else if (!strcmp(parser_tokval(parser), "const"))
2862             had_const = true;
2863         else if (!strcmp(parser_tokval(parser), "var"))
2864             had_var = true;
2865         else if (with_local && !strcmp(parser_tokval(parser), "local"))
2866             had_var = true;
2867         else if (!strcmp(parser_tokval(parser), "noref"))
2868             had_noref = true;
2869         else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
2870             return false;
2871         }
2872         else
2873             break;
2874         if (!parser_next(parser))
2875             goto onerr;
2876     }
2877     if (had_const)
2878         *cvq = CV_CONST;
2879     else if (had_var)
2880         *cvq = CV_VAR;
2881     else
2882         *cvq = CV_NONE;
2883     *noref     = had_noref;
2884     *is_static = had_static;
2885     *_flags    = flags;
2886     return true;
2887 onerr:
2888     parseerror(parser, "parse error after variable qualifier");
2889     *cvq = CV_WRONG;
2890     return true;
2891 }
2892
2893 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out);
2894 static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **out)
2895 {
2896     bool rv;
2897     char *label = NULL;
2898
2899     /* skip the 'while' and get the body */
2900     if (!parser_next(parser)) {
2901         if (OPTS_FLAG(LOOP_LABELS))
2902             parseerror(parser, "expected loop label or 'switch' operand in parenthesis");
2903         else
2904             parseerror(parser, "expected 'switch' operand in parenthesis");
2905         return false;
2906     }
2907
2908     if (parser->tok == ':') {
2909         if (!OPTS_FLAG(LOOP_LABELS))
2910             parseerror(parser, "labeled loops not activated, try using -floop-labels");
2911         if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
2912             parseerror(parser, "expected loop label");
2913             return false;
2914         }
2915         label = util_strdup(parser_tokval(parser));
2916         if (!parser_next(parser)) {
2917             mem_d(label);
2918             parseerror(parser, "expected 'switch' operand in parenthesis");
2919             return false;
2920         }
2921     }
2922
2923     if (parser->tok != '(') {
2924         parseerror(parser, "expected 'switch' operand in parenthesis");
2925         return false;
2926     }
2927
2928     vec_push(parser->breaks, label);
2929
2930     rv = parse_switch_go(parser, block, out);
2931     if (label)
2932         mem_d(label);
2933     if (vec_last(parser->breaks) != label) {
2934         parseerror(parser, "internal error: label stack corrupted");
2935         rv = false;
2936         ast_delete(*out);
2937         *out = NULL;
2938     }
2939     else {
2940         vec_pop(parser->breaks);
2941     }
2942     return rv;
2943 }
2944
2945 static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression **out)
2946 {
2947     ast_expression *operand;
2948     ast_value      *opval;
2949     ast_value      *typevar;
2950     ast_switch     *switchnode;
2951     ast_switch_case swcase;
2952
2953     int  cvq;
2954     bool noref, is_static;
2955     uint32_t qflags = 0;
2956
2957     lex_ctx_t ctx = parser_ctx(parser);
2958
2959     (void)block; /* not touching */
2960     (void)opval;
2961
2962     /* parse into the expression */
2963     if (!parser_next(parser)) {
2964         parseerror(parser, "expected switch operand");
2965         return false;
2966     }
2967     /* parse the operand */
2968     operand = parse_expression_leave(parser, false, false, false);
2969     if (!operand)
2970         return false;
2971
2972     switchnode = ast_switch_new(ctx, operand);
2973
2974     /* closing paren */
2975     if (parser->tok != ')') {
2976         ast_delete(switchnode);
2977         parseerror(parser, "expected closing paren after 'switch' operand");
2978         return false;
2979     }
2980
2981     /* parse over the opening paren */
2982     if (!parser_next(parser) || parser->tok != '{') {
2983         ast_delete(switchnode);
2984         parseerror(parser, "expected list of cases");
2985         return false;
2986     }
2987
2988     if (!parser_next(parser)) {
2989         ast_delete(switchnode);
2990         parseerror(parser, "expected 'case' or 'default'");
2991         return false;
2992     }
2993
2994     /* new block; allow some variables to be declared here */
2995     parser_enterblock(parser);
2996     while (true) {
2997         typevar = NULL;
2998         if (parser->tok == TOKEN_IDENT)
2999             typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3000         if (typevar || parser->tok == TOKEN_TYPENAME) {
3001             if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL)) {
3002                 ast_delete(switchnode);
3003                 return false;
3004             }
3005             continue;
3006         }
3007         if (parse_qualifiers(parser, true, &cvq, &noref, &is_static, &qflags, NULL))
3008         {
3009             if (cvq == CV_WRONG) {
3010                 ast_delete(switchnode);
3011                 return false;
3012             }
3013             if (!parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, NULL)) {
3014                 ast_delete(switchnode);
3015                 return false;
3016             }
3017             continue;
3018         }
3019         break;
3020     }
3021
3022     /* case list! */
3023     while (parser->tok != '}') {
3024         ast_block *caseblock;
3025
3026         if (!strcmp(parser_tokval(parser), "case")) {
3027             if (!parser_next(parser)) {
3028                 ast_delete(switchnode);
3029                 parseerror(parser, "expected expression for case");
3030                 return false;
3031             }
3032             swcase.value = parse_expression_leave(parser, false, false, false);
3033             if (!swcase.value) {
3034                 ast_delete(switchnode);
3035                 parseerror(parser, "expected expression for case");
3036                 return false;
3037             }
3038             if (!OPTS_FLAG(RELAXED_SWITCH)) {
3039                 if (!ast_istype(swcase.value, ast_value)) { /* || ((ast_value*)swcase.value)->cvq != CV_CONST) { */
3040                     parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
3041                     ast_unref(operand);
3042                     return false;
3043                 }
3044             }
3045         }
3046         else if (!strcmp(parser_tokval(parser), "default")) {
3047             swcase.value = NULL;
3048             if (!parser_next(parser)) {
3049                 ast_delete(switchnode);
3050                 parseerror(parser, "expected colon");
3051                 return false;
3052             }
3053         }
3054         else {
3055             ast_delete(switchnode);
3056             parseerror(parser, "expected 'case' or 'default'");
3057             return false;
3058         }
3059
3060         /* Now the colon and body */
3061         if (parser->tok != ':') {
3062             if (swcase.value) ast_unref(swcase.value);
3063             ast_delete(switchnode);
3064             parseerror(parser, "expected colon");
3065             return false;
3066         }
3067
3068         if (!parser_next(parser)) {
3069             if (swcase.value) ast_unref(swcase.value);
3070             ast_delete(switchnode);
3071             parseerror(parser, "expected statements or case");
3072             return false;
3073         }
3074         caseblock = ast_block_new(parser_ctx(parser));
3075         if (!caseblock) {
3076             if (swcase.value) ast_unref(swcase.value);
3077             ast_delete(switchnode);
3078             return false;
3079         }
3080         swcase.code = (ast_expression*)caseblock;
3081         vec_push(switchnode->cases, swcase);
3082         while (true) {
3083             ast_expression *expr;
3084             if (parser->tok == '}')
3085                 break;
3086             if (parser->tok == TOKEN_KEYWORD) {
3087                 if (!strcmp(parser_tokval(parser), "case") ||
3088                     !strcmp(parser_tokval(parser), "default"))
3089                 {
3090                     break;
3091                 }
3092             }
3093             if (!parse_statement(parser, caseblock, &expr, true)) {
3094                 ast_delete(switchnode);
3095                 return false;
3096             }
3097             if (!expr)
3098                 continue;
3099             if (!ast_block_add_expr(caseblock, expr)) {
3100                 ast_delete(switchnode);
3101                 return false;
3102             }
3103         }
3104     }
3105
3106     parser_leaveblock(parser);
3107
3108     /* closing paren */
3109     if (parser->tok != '}') {
3110         ast_delete(switchnode);
3111         parseerror(parser, "expected closing paren of case list");
3112         return false;
3113     }
3114     if (!parser_next(parser)) {
3115         ast_delete(switchnode);
3116         parseerror(parser, "parse error after switch");
3117         return false;
3118     }
3119     *out = (ast_expression*)switchnode;
3120     return true;
3121 }
3122
3123 /* parse computed goto sides */
3124 static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) {
3125     ast_expression *on_true;
3126     ast_expression *on_false;
3127     ast_expression *cond;
3128
3129     if (!*side)
3130         return NULL;
3131
3132     if (ast_istype(*side, ast_ternary)) {
3133         ast_ternary *tern = (ast_ternary*)*side;
3134         on_true  = parse_goto_computed(parser, &tern->on_true);
3135         on_false = parse_goto_computed(parser, &tern->on_false);
3136
3137         if (!on_true || !on_false) {
3138             parseerror(parser, "expected label or expression in ternary");
3139             if (on_true) ast_unref(on_true);
3140             if (on_false) ast_unref(on_false);
3141             return NULL;
3142         }
3143
3144         cond = tern->cond;
3145         tern->cond = NULL;
3146         ast_delete(tern);
3147         *side = NULL;
3148         return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false);
3149     } else if (ast_istype(*side, ast_label)) {
3150         ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name);
3151         ast_goto_set_label(gt, ((ast_label*)*side));
3152         *side = NULL;
3153         return (ast_expression*)gt;
3154     }
3155     return NULL;
3156 }
3157
3158 static bool parse_goto(parser_t *parser, ast_expression **out)
3159 {
3160     ast_goto       *gt = NULL;
3161     ast_expression *lbl;
3162
3163     if (!parser_next(parser))
3164         return false;
3165
3166     if (parser->tok != TOKEN_IDENT) {
3167         ast_expression *expression;
3168
3169         /* could be an expression i.e computed goto :-) */
3170         if (parser->tok != '(') {
3171             parseerror(parser, "expected label name after `goto`");
3172             return false;
3173         }
3174
3175         /* failed to parse expression for goto */
3176         if (!(expression = parse_expression(parser, false, true)) ||
3177             !(*out = parse_goto_computed(parser, &expression))) {
3178             parseerror(parser, "invalid goto expression");
3179             if(expression)
3180                 ast_unref(expression);
3181             return false;
3182         }
3183
3184         return true;
3185     }
3186
3187     /* not computed goto */
3188     gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser));
3189     lbl = parser_find_label(parser, gt->name);
3190     if (lbl) {
3191         if (!ast_istype(lbl, ast_label)) {
3192             parseerror(parser, "internal error: label is not an ast_label");
3193             ast_delete(gt);
3194             return false;
3195         }
3196         ast_goto_set_label(gt, (ast_label*)lbl);
3197     }
3198     else
3199         vec_push(parser->gotos, gt);
3200
3201     if (!parser_next(parser) || parser->tok != ';') {
3202         parseerror(parser, "semicolon expected after goto label");
3203         return false;
3204     }
3205     if (!parser_next(parser)) {
3206         parseerror(parser, "parse error after goto");
3207         return false;
3208     }
3209
3210     *out = (ast_expression*)gt;
3211     return true;
3212 }
3213
3214 static bool parse_skipwhite(parser_t *parser)
3215 {
3216     do {
3217         if (!parser_next(parser))
3218             return false;
3219     } while (parser->tok == TOKEN_WHITE && parser->tok < TOKEN_ERROR);
3220     return parser->tok < TOKEN_ERROR;
3221 }
3222
3223 static bool parse_eol(parser_t *parser)
3224 {
3225     if (!parse_skipwhite(parser))
3226         return false;
3227     return parser->tok == TOKEN_EOL;
3228 }
3229
3230 static bool parse_pragma_do(parser_t *parser)
3231 {
3232     if (!parser_next(parser) ||
3233         parser->tok != TOKEN_IDENT ||
3234         strcmp(parser_tokval(parser), "pragma"))
3235     {
3236         parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
3237         return false;
3238     }
3239     if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
3240         parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
3241         return false;
3242     }
3243
3244     if (!strcmp(parser_tokval(parser), "noref")) {
3245         if (!parse_skipwhite(parser) || parser->tok != TOKEN_INTCONST) {
3246             parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
3247             return false;
3248         }
3249         parser->noref = !!parser_token(parser)->constval.i;
3250         if (!parse_eol(parser)) {
3251             parseerror(parser, "parse error after `noref` pragma");
3252             return false;
3253         }
3254     }
3255     else
3256     {
3257         (void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
3258         return false;
3259     }
3260
3261     return true;
3262 }
3263
3264 static bool parse_pragma(parser_t *parser)
3265 {
3266     bool rv;
3267     parser->lex->flags.preprocessing = true;
3268     parser->lex->flags.mergelines = true;
3269     rv = parse_pragma_do(parser);
3270     if (parser->tok != TOKEN_EOL) {
3271         parseerror(parser, "junk after pragma");
3272         rv = false;
3273     }
3274     parser->lex->flags.preprocessing = false;
3275     parser->lex->flags.mergelines = false;
3276     if (!parser_next(parser)) {
3277         parseerror(parser, "parse error after pragma");
3278         rv = false;
3279     }
3280     return rv;
3281 }
3282
3283 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases)
3284 {
3285     bool       noref, is_static;
3286     int        cvq     = CV_NONE;
3287     uint32_t   qflags  = 0;
3288     ast_value *typevar = NULL;
3289     char      *vstring = NULL;
3290
3291     *out = NULL;
3292
3293     if (parser->tok == TOKEN_IDENT)
3294         typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
3295
3296     if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
3297     {
3298         /* local variable */
3299         if (!block) {
3300             parseerror(parser, "cannot declare a variable from here");
3301             return false;
3302         }
3303         if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3304             if (parsewarning(parser, WARN_EXTENSIONS, "missing 'local' keyword when declaring a local variable"))
3305                 return false;
3306         }
3307         if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL))
3308             return false;
3309         return true;
3310     }
3311     else if (parse_qualifiers(parser, !!block, &cvq, &noref, &is_static, &qflags, &vstring))
3312     {
3313         if (cvq == CV_WRONG)
3314             return false;
3315         return parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, vstring);
3316     }
3317     else if (parser->tok == TOKEN_KEYWORD)
3318     {
3319         if (!strcmp(parser_tokval(parser), "__builtin_debug_printtype"))
3320         {
3321             char ty[1024];
3322             ast_value *tdef;
3323
3324             if (!parser_next(parser)) {
3325                 parseerror(parser, "parse error after __builtin_debug_printtype");
3326                 return false;
3327             }
3328
3329             if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0)))
3330             {
3331                 ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty));
3332                 con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->name, ty);
3333                 if (!parser_next(parser)) {
3334                     parseerror(parser, "parse error after __builtin_debug_printtype typename argument");
3335                     return false;
3336                 }
3337             }
3338             else
3339             {
3340                 if (!parse_statement(parser, block, out, allow_cases))
3341                     return false;
3342                 if (!*out)
3343                     con_out("__builtin_debug_printtype: got no output node\n");
3344                 else
3345                 {
3346                     ast_type_to_string(*out, ty, sizeof(ty));
3347                     con_out("__builtin_debug_printtype: `%s`\n", ty);
3348                 }
3349             }
3350             return true;
3351         }
3352         else if (!strcmp(parser_tokval(parser), "return"))
3353         {
3354             return parse_return(parser, block, out);
3355         }
3356         else if (!strcmp(parser_tokval(parser), "if"))
3357         {
3358             return parse_if(parser, block, out);
3359         }
3360         else if (!strcmp(parser_tokval(parser), "while"))
3361         {
3362             return parse_while(parser, block, out);
3363         }
3364         else if (!strcmp(parser_tokval(parser), "do"))
3365         {
3366             return parse_dowhile(parser, block, out);
3367         }
3368         else if (!strcmp(parser_tokval(parser), "for"))
3369         {
3370             if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
3371                 if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
3372                     return false;
3373             }
3374             return parse_for(parser, block, out);
3375         }
3376         else if (!strcmp(parser_tokval(parser), "break"))
3377         {
3378             return parse_break_continue(parser, block, out, false);
3379         }
3380         else if (!strcmp(parser_tokval(parser), "continue"))
3381         {
3382             return parse_break_continue(parser, block, out, true);
3383         }
3384         else if (!strcmp(parser_tokval(parser), "switch"))
3385         {
3386             return parse_switch(parser, block, out);
3387         }
3388         else if (!strcmp(parser_tokval(parser), "case") ||
3389                  !strcmp(parser_tokval(parser), "default"))
3390         {
3391             if (!allow_cases) {
3392                 parseerror(parser, "unexpected 'case' label");
3393                 return false;
3394             }
3395             return true;
3396         }
3397         else if (!strcmp(parser_tokval(parser), "goto"))
3398         {
3399             return parse_goto(parser, out);
3400         }
3401         else if (!strcmp(parser_tokval(parser), "typedef"))
3402         {
3403             if (!parser_next(parser)) {
3404                 parseerror(parser, "expected type definition after 'typedef'");
3405                 return false;
3406             }
3407             return parse_typedef(parser);
3408         }
3409         parseerror(parser, "Unexpected keyword: `%s'", parser_tokval(parser));
3410         return false;
3411     }
3412     else if (parser->tok == '{')
3413     {
3414         ast_block *inner;
3415         inner = parse_block(parser);
3416         if (!inner)
3417             return false;
3418         *out = (ast_expression*)inner;
3419         return true;
3420     }
3421     else if (parser->tok == ':')
3422     {
3423         size_t i;
3424         ast_label *label;
3425         if (!parser_next(parser)) {
3426             parseerror(parser, "expected label name");
3427             return false;
3428         }
3429         if (parser->tok != TOKEN_IDENT) {
3430             parseerror(parser, "label must be an identifier");
3431             return false;
3432         }
3433         label = (ast_label*)parser_find_label(parser, parser_tokval(parser));
3434         if (label) {
3435             if (!label->undefined) {
3436                 parseerror(parser, "label `%s` already defined", label->name);
3437                 return false;
3438             }
3439             label->undefined = false;
3440         }
3441         else {
3442             label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false);
3443             vec_push(parser->labels, label);
3444         }
3445         *out = (ast_expression*)label;
3446         if (!parser_next(parser)) {
3447             parseerror(parser, "parse error after label");
3448             return false;
3449         }
3450         for (i = 0; i < vec_size(parser->gotos); ++i) {
3451             if (!strcmp(parser->gotos[i]->name, label->name)) {
3452                 ast_goto_set_label(parser->gotos[i], label);
3453                 vec_remove(parser->gotos, i, 1);
3454                 --i;
3455             }
3456         }
3457         return true;
3458     }
3459     else if (parser->tok == ';')
3460     {
3461         if (!parser_next(parser)) {
3462             parseerror(parser, "parse error after empty statement");
3463             return false;
3464         }
3465         return true;
3466     }
3467     else
3468     {
3469         lex_ctx_t ctx = parser_ctx(parser);
3470         ast_expression *exp = parse_expression(parser, false, false);
3471         if (!exp)
3472             return false;
3473         *out = exp;
3474         if (!ast_side_effects(exp)) {
3475             if (compile_warning(ctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect"))
3476                 return false;
3477         }
3478         return true;
3479     }