From ec89149b2902e328da28b96beb1e6ad9c5875b10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 13:54:03 +0900 Subject: [PATCH] Build for loop decl inits correctly The multiple expressions are chained together and evaluate in left to right order. --- tools/qfcc/include/expr.h | 11 +++++++++++ tools/qfcc/source/expr.c | 14 ++++++++++++++ tools/qfcc/source/qc-parse.y | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f1987bb8a..d8831b766 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -314,6 +314,17 @@ expr_t *new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e); */ expr_t *new_block_expr (void); +/** Create a new statement block expression node from an expression list + + The returned block holds the expression list in reverse order. This makes + it easy to build the list in a parser. + + \param expr_list The expression list to convert to an expression block. + Note that the evaluation order will be reversed. + \return The new block expression (::ex_block_t) node. +*/ +expr_t *build_block_expr (expr_t *expr_list); + /** Create a new binary expression node node. If either \a e1 or \a e2 are error expressions, then that expression will diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 104963189..c6bed8e39 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -539,6 +539,20 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2) return e; } +expr_t * +build_block_expr (expr_t *expr_list) +{ + expr_t *b = new_block_expr (); + + while (expr_list) { + expr_t *e = expr_list; + expr_list = e->next; + e->next = 0; + append_expr (b, e); + } + return b; +} + expr_t * new_unary_expr (int op, expr_t *e1) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 945e3b5fb..8e9c38af8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1153,6 +1153,9 @@ statement | FOR push_scope break_label continue_label '(' opt_init ';' opt_expr ';' opt_expr ')' statement pop_scope { + if ($6) { + $6 = build_block_expr ($6); + } $$ = build_for_statement ($6, $8, $10, $12, break_label, continue_label); break_label = $3; @@ -1234,12 +1237,22 @@ opt_init init_var_decl_list : init_var_decl - | init_var_decl_list ',' init_var_decl + { + printf ("a\n"); + $$ = $1; + } + | init_var_decl_list ',' { $$ = $0; } init_var_decl + { + printf ("b\n"); + $4->next = $1; + $$ = $4; + } ; init_var_decl : var_decl opt_initializer { + printf ("c\n"); specifier_t spec = $0; $1->type = append_type ($1->type, spec.type); $1->type = find_type ($1->type);