Implement "not" logic for while and do-while.

This goes towards complementing the "if not" logic extension. I need to
check if fteqcc supports "not" with "while" (the version I have access to
at the moment does not), and also whether it would be good  to support
"not" with "for", and if so, what form the syntax should take.
This commit is contained in:
Bill Currie 2013-06-25 10:46:51 +09:00
parent 45a09e195e
commit cef2136050
4 changed files with 24 additions and 13 deletions

View file

@ -600,9 +600,9 @@ expr_t *pointer_expr (expr_t *pointer);
expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t);
expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els,
expr_t *s2); expr_t *s2);
expr_t *build_while_statement (expr_t *test, expr_t *statement, expr_t *build_while_statement (int not, expr_t *test, expr_t *statement,
expr_t *break_label, expr_t *continue_label); expr_t *break_label, expr_t *continue_label);
expr_t *build_do_while_statement (expr_t *statement, expr_t *test, expr_t *build_do_while_statement (expr_t *statement, int not, expr_t *test,
expr_t *break_label, expr_t *continue_label); expr_t *break_label, expr_t *continue_label);
expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next,
expr_t *statement, expr_t *statement,

View file

@ -2337,7 +2337,7 @@ build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2)
} }
expr_t * expr_t *
build_while_statement (expr_t *test, expr_t *statement, build_while_statement (int not, expr_t *test, expr_t *statement,
expr_t *break_label, expr_t *continue_label) expr_t *break_label, expr_t *continue_label)
{ {
int line = pr.source_line; int line = pr.source_line;
@ -2358,8 +2358,13 @@ build_while_statement (expr_t *test, expr_t *statement,
test = convert_bool (test, 1); test = convert_bool (test, 1);
if (test->type != ex_error) { if (test->type != ex_error) {
backpatch (test->e.bool.true_list, l1); if (not) {
backpatch (test->e.bool.false_list, l2); backpatch (test->e.bool.true_list, l2);
backpatch (test->e.bool.false_list, l1);
} else {
backpatch (test->e.bool.true_list, l1);
backpatch (test->e.bool.false_list, l2);
}
append_expr (test->e.bool.e, l2); append_expr (test->e.bool.e, l2);
append_expr (while_expr, test); append_expr (while_expr, test);
} }
@ -2371,7 +2376,7 @@ build_while_statement (expr_t *test, expr_t *statement,
} }
expr_t * expr_t *
build_do_while_statement (expr_t *statement, expr_t *test, build_do_while_statement (expr_t *statement, int not, expr_t *test,
expr_t *break_label, expr_t *continue_label) expr_t *break_label, expr_t *continue_label)
{ {
expr_t *l1 = new_label_expr (); expr_t *l1 = new_label_expr ();
@ -2390,8 +2395,13 @@ build_do_while_statement (expr_t *statement, expr_t *test,
test = convert_bool (test, 1); test = convert_bool (test, 1);
if (test->type != ex_error) { if (test->type != ex_error) {
backpatch (test->e.bool.true_list, l1); if (not) {
backpatch (test->e.bool.false_list, break_label); backpatch (test->e.bool.true_list, break_label);
backpatch (test->e.bool.false_list, l1);
} else {
backpatch (test->e.bool.true_list, l1);
backpatch (test->e.bool.false_list, break_label);
}
append_expr (test->e.bool.e, break_label); append_expr (test->e.bool.e, break_label);
append_expr (do_while_expr, test); append_expr (do_while_expr, test);
} }

View file

@ -1165,15 +1165,16 @@ statement
break_label = $2; break_label = $2;
continue_label = $3; continue_label = $3;
} }
| WHILE break_label continue_label '(' texpr ')' statement | WHILE break_label continue_label not '(' texpr ')' statement
{ {
$$ = build_while_statement ($5, $7, break_label, continue_label); $$ = build_while_statement ($4, $6, $8, break_label,
continue_label);
break_label = $2; break_label = $2;
continue_label = $3; continue_label = $3;
} }
| DO break_label continue_label statement WHILE '(' texpr ')' ';' | DO break_label continue_label statement WHILE not '(' texpr ')' ';'
{ {
$$ = build_do_while_statement ($4, $7, $$ = build_do_while_statement ($4, $6, $8,
break_label, continue_label); break_label, continue_label);
break_label = $2; break_label = $2;
continue_label = $3; continue_label = $3;

View file

@ -362,7 +362,7 @@ statement
} }
| WHILE expression DO statement | WHILE expression DO statement
{ {
$$ = build_while_statement ($2, $4, $$ = build_while_statement (0, $2, $4,
new_label_expr (), new_label_expr (),
new_label_expr ()); new_label_expr ());
} }