mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 12:40:42 +00:00
short circuit logic for && and || (as per C). forces standard precedence
(ie, breaks --traditional) when enabled (no choice at the moment, next fix)
This commit is contained in:
parent
5686ff51e5
commit
945006494f
4 changed files with 394 additions and 66 deletions
|
@ -34,6 +34,7 @@
|
|||
|
||||
typedef enum {
|
||||
ex_error,
|
||||
ex_bool,
|
||||
ex_label,
|
||||
ex_block,
|
||||
ex_expr, // binary expression
|
||||
|
@ -83,6 +84,17 @@ typedef struct {
|
|||
struct def_s *def;
|
||||
} ex_pointer_t;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
struct expr_s *e[1];
|
||||
} ex_list_t;
|
||||
|
||||
typedef struct {
|
||||
ex_list_t *true_list;
|
||||
ex_list_t *false_list;
|
||||
struct expr_s *e;
|
||||
} ex_bool_t;
|
||||
|
||||
#define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val)
|
||||
|
||||
typedef struct expr_s {
|
||||
|
@ -94,6 +106,7 @@ typedef struct expr_s {
|
|||
unsigned rvalue:1;
|
||||
union {
|
||||
ex_label_t label;
|
||||
ex_bool_t bool;
|
||||
ex_block_t block;
|
||||
struct {
|
||||
int op;
|
||||
|
@ -132,6 +145,7 @@ expr_t *new_expr (void);
|
|||
const char *new_label_name (void);
|
||||
|
||||
expr_t *new_label_expr (void);
|
||||
expr_t *new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e);
|
||||
expr_t *new_block_expr (void);
|
||||
expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2);
|
||||
expr_t *new_unary_expr (int op, expr_t *e1);
|
||||
|
@ -176,6 +190,9 @@ void convert_short_int (expr_t *e);
|
|||
void convert_short_uint (expr_t *e);
|
||||
|
||||
expr_t *test_expr (expr_t *e, int test);
|
||||
void backpatch (ex_list_t *list, expr_t *label);
|
||||
expr_t *convert_bool (expr_t *e, int block);
|
||||
expr_t *bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2);
|
||||
expr_t *binary_expr (int op, expr_t *e1, expr_t *e2);
|
||||
expr_t *asx_expr (int op, expr_t *e1, expr_t *e2);
|
||||
expr_t *unary_expr (int op, expr_t *e);
|
||||
|
|
|
@ -434,6 +434,125 @@ emit_deref_expr (expr_t *e, def_t *dest)
|
|||
return d;
|
||||
}
|
||||
|
||||
static void
|
||||
build_bool_block (expr_t *block, expr_t *e)
|
||||
{
|
||||
switch (e->type) {
|
||||
case ex_bool:
|
||||
build_bool_block (block, e->e.bool.e);
|
||||
return;
|
||||
case ex_label:
|
||||
e->next = 0;
|
||||
append_expr (block, e);
|
||||
return;
|
||||
case ex_expr:
|
||||
if (e->e.expr.op == OR || e->e.expr.op == AND) {
|
||||
build_bool_block (block, e->e.expr.e1);
|
||||
build_bool_block (block, e->e.expr.e2);
|
||||
} else if (e->e.expr.op == 'i') {
|
||||
e->next = 0;
|
||||
append_expr (block, e);
|
||||
} else if (e->e.expr.op == 'n') {
|
||||
e->next = 0;
|
||||
append_expr (block, e);
|
||||
}
|
||||
return;
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == 'g') {
|
||||
e->next = 0;
|
||||
append_expr (block, e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ex_block:
|
||||
if (!e->e.block.result) {
|
||||
expr_t *t;
|
||||
for (e = e->e.block.head; e; e = t) {
|
||||
t = e->next;
|
||||
build_bool_block (block, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
}
|
||||
|
||||
static int
|
||||
is_goto (expr_t *e)
|
||||
{
|
||||
return e && e->type == ex_uexpr && e->e.expr.op == 'g';
|
||||
}
|
||||
|
||||
static int
|
||||
is_if (expr_t *e)
|
||||
{
|
||||
return e && e->type == ex_expr && e->e.expr.op == 'i';
|
||||
}
|
||||
|
||||
static int
|
||||
is_ifnot (expr_t *e)
|
||||
{
|
||||
return e && e->type == ex_expr && e->e.expr.op == 'n';
|
||||
}
|
||||
|
||||
static void
|
||||
emit_bool_expr (expr_t *e)
|
||||
{
|
||||
expr_t *block = new_block_expr ();
|
||||
expr_t **s;
|
||||
expr_t *l;
|
||||
|
||||
build_bool_block (block, e);
|
||||
|
||||
s = &block->e.block.head;
|
||||
while (*s) {
|
||||
if (is_if (*s) && is_goto ((*s)->next)) {
|
||||
l = (*s)->e.expr.e2;
|
||||
for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
e = *s;
|
||||
e->e.expr.op = 'n';
|
||||
e->e.expr.e2 = e->next->e.expr.e1;
|
||||
e->next = e->next->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s = &(*s)->next;
|
||||
} else if (is_ifnot (*s) && is_goto ((*s)->next)) {
|
||||
l = (*s)->e.expr.e2;
|
||||
for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
e = *s;
|
||||
e->e.expr.op = 'i';
|
||||
e->e.expr.e2 = e->next->e.expr.e1;
|
||||
e->next = e->next->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s = &(*s)->next;
|
||||
} else if (is_goto (*s)) {
|
||||
l = (*s)->e.expr.e1;
|
||||
for (e = (*s)->next; e && e->type == ex_label; e = e->next) {
|
||||
if (e == l) {
|
||||
*s = (*s)->next;
|
||||
l = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l)
|
||||
s = &(*s)->next;
|
||||
} else {
|
||||
s = &(*s)->next;
|
||||
}
|
||||
}
|
||||
|
||||
emit_expr (block);
|
||||
}
|
||||
|
||||
def_t *
|
||||
emit_sub_expr (expr_t *e, def_t *dest)
|
||||
{
|
||||
|
@ -449,8 +568,9 @@ emit_sub_expr (expr_t *e, def_t *dest)
|
|||
for (e = e->e.block.head; e; e = e->next)
|
||||
emit_expr (e);
|
||||
d = emit_sub_expr (res, dest);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ex_bool:
|
||||
case ex_name:
|
||||
case ex_nil:
|
||||
case ex_label:
|
||||
|
@ -637,6 +757,9 @@ emit_expr (expr_t *e)
|
|||
label->ofs = pr.code->size;
|
||||
relocate_refs (label->refs, label->ofs);
|
||||
break;
|
||||
case ex_bool:
|
||||
emit_bool_expr (e);
|
||||
break;
|
||||
case ex_block:
|
||||
for (e = e->e.block.head; e; e = e->next)
|
||||
emit_expr (e);
|
||||
|
|
|
@ -69,6 +69,7 @@ int lineno_base;
|
|||
etype_t qc_types[] = {
|
||||
ev_void, // ex_error
|
||||
ev_void, // ex_label
|
||||
ev_void, // ex_bool
|
||||
ev_void, // ex_block
|
||||
ev_void, // ex_expr
|
||||
ev_void, // ex_uexpr
|
||||
|
@ -179,6 +180,10 @@ get_type (expr_t *e)
|
|||
case ex_name:
|
||||
case ex_error:
|
||||
return 0; // something went very wrong
|
||||
case ex_bool:
|
||||
if (options.code.progsversion == PROG_ID_VERSION)
|
||||
return &type_float;
|
||||
return &type_integer;
|
||||
case ex_nil:
|
||||
return &type_void;
|
||||
case ex_block:
|
||||
|
@ -352,6 +357,18 @@ new_label_expr (void)
|
|||
return l;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e)
|
||||
{
|
||||
expr_t *b = new_expr ();
|
||||
|
||||
b->type = ex_bool;
|
||||
b->e.bool.true_list = true_list;
|
||||
b->e.bool.false_list = false_list;
|
||||
b->e.bool.e = e;
|
||||
return b;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_block_expr (void)
|
||||
{
|
||||
|
@ -654,6 +671,9 @@ print_expr (expr_t *e)
|
|||
case ex_error:
|
||||
printf ("(error)");
|
||||
break;
|
||||
case ex_bool:
|
||||
printf ("bool"); //FIXME
|
||||
break;
|
||||
case ex_label:
|
||||
printf ("%s", e->e.label.name);
|
||||
break;
|
||||
|
@ -1441,6 +1461,113 @@ test_expr (expr_t *e, int test)
|
|||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
backpatch (ex_list_t *list, expr_t *label)
|
||||
{
|
||||
int i;
|
||||
expr_t *e;
|
||||
|
||||
for (i = 0; i < list->size; i++) {
|
||||
e = list->e[i];
|
||||
if (e->type == ex_uexpr && e->e.expr.op == 'g')
|
||||
e->e.expr.e1 = label;
|
||||
else if (e->type == ex_expr && (e->e.expr.op == 'i'
|
||||
|| e->e.expr.op == 'n'))
|
||||
e->e.expr.e2 = label;
|
||||
else {
|
||||
error (e, "internal compiler error");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ex_list_t *
|
||||
merge (ex_list_t *l1, ex_list_t *l2)
|
||||
{
|
||||
ex_list_t *m;
|
||||
|
||||
m = malloc ((size_t)&((ex_list_t *)0)->e[l1->size + l2->size]);
|
||||
m->size = l1->size + l2->size;
|
||||
memcpy (m->e, l1->e, l1->size * sizeof (expr_t *));
|
||||
memcpy (m->e + l1->size, l2->e, l2->size * sizeof (expr_t *));
|
||||
return m;
|
||||
}
|
||||
|
||||
static ex_list_t *
|
||||
make_list (expr_t *e)
|
||||
{
|
||||
ex_list_t *m;
|
||||
|
||||
m = malloc ((size_t)&((ex_list_t *) 0)->e[1]);
|
||||
m->size = 1;
|
||||
m->e[0] = e;
|
||||
return m;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
convert_bool (expr_t *e, int block)
|
||||
{
|
||||
expr_t *b;
|
||||
|
||||
if (e->type == ex_uexpr && e->e.expr.op == '!') {
|
||||
e = convert_bool (e->e.expr.e1, 0);
|
||||
e = unary_expr ('!', e);
|
||||
}
|
||||
if (e->type != ex_bool) {
|
||||
e = test_expr (e, 1);
|
||||
if (e->type == ex_integer) {
|
||||
e = new_unary_expr ('g', 0);
|
||||
if (e->e.integer_val)
|
||||
e = new_bool_expr (make_list (e), 0, e);
|
||||
else
|
||||
e = new_bool_expr (0, make_list (e), e);
|
||||
} else {
|
||||
b = new_block_expr ();
|
||||
append_expr (b, new_binary_expr ('i', e, 0));
|
||||
append_expr (b, new_unary_expr ('g', 0));
|
||||
e = new_bool_expr (make_list (b->e.block.head),
|
||||
make_list (b->e.block.head->next), b);
|
||||
}
|
||||
}
|
||||
if (block && e->e.bool.e->type != ex_block) {
|
||||
expr_t *block = new_block_expr ();
|
||||
append_expr (block, e->e.bool.e);
|
||||
e->e.bool.e = block;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
expr_t *block;
|
||||
|
||||
e1 = convert_bool (e1, 0);
|
||||
e2 = convert_bool (e2, 0);
|
||||
|
||||
block = new_block_expr ();
|
||||
append_expr (block, e1);
|
||||
append_expr (block, label);
|
||||
append_expr (block, e2);
|
||||
|
||||
switch (op) {
|
||||
case OR:
|
||||
backpatch (e1->e.bool.false_list, label);
|
||||
return new_bool_expr (merge (e1->e.bool.true_list,
|
||||
e2->e.bool.true_list),
|
||||
e2->e.bool.false_list, block);
|
||||
break;
|
||||
case AND:
|
||||
backpatch (e1->e.bool.true_list, label);
|
||||
return new_bool_expr (e2->e.bool.true_list,
|
||||
merge (e1->e.bool.false_list,
|
||||
e2->e.bool.false_list), block);
|
||||
break;
|
||||
}
|
||||
error (e1, "internal error");
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
convert_int (expr_t *e)
|
||||
{
|
||||
|
@ -1607,6 +1734,12 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
}
|
||||
}
|
||||
|
||||
if (e1->type == ex_bool)
|
||||
e1 = conditional_expr (e1, new_integer_expr (1), new_integer_expr (0));
|
||||
|
||||
if (e2->type == ex_bool)
|
||||
e2 = conditional_expr (e2, new_integer_expr (1), new_integer_expr (0));
|
||||
|
||||
if (e1->type == ex_short) {
|
||||
if (t2 == &type_integer) {
|
||||
convert_short_int (e1);
|
||||
|
@ -1798,6 +1931,7 @@ unary_expr (int op, expr_t *e)
|
|||
if (!e->e.block.result)
|
||||
return error (e, "invalid type for unary -");
|
||||
case ex_expr:
|
||||
case ex_bool:
|
||||
case ex_def:
|
||||
case ex_temp:
|
||||
{
|
||||
|
@ -1844,6 +1978,9 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_name:
|
||||
error (e, "internal error");
|
||||
abort ();
|
||||
case ex_bool:
|
||||
return new_bool_expr (e->e.bool.false_list,
|
||||
e->e.bool.true_list, e);
|
||||
case ex_block:
|
||||
if (!e->e.block.result)
|
||||
return error (e, "invalid type for unary !");
|
||||
|
@ -1914,6 +2051,7 @@ unary_expr (int op, expr_t *e)
|
|||
return error (e, "invalid type for unary ~");
|
||||
goto bitnot_expr;
|
||||
case ex_expr:
|
||||
case ex_bool:
|
||||
case ex_def:
|
||||
case ex_temp:
|
||||
bitnot_expr:
|
||||
|
@ -2131,6 +2269,8 @@ function_expr (expr_t *e1, expr_t *e2)
|
|||
expr_t *
|
||||
return_expr (function_t *f, expr_t *e)
|
||||
{
|
||||
type_t *t = get_type (e);
|
||||
|
||||
if (!e) {
|
||||
if (f->def->type->aux_type != &type_void) {
|
||||
if (options.traditional) {
|
||||
|
@ -2141,33 +2281,41 @@ return_expr (function_t *f, expr_t *e)
|
|||
return e;
|
||||
}
|
||||
}
|
||||
return new_unary_expr ('r', 0);
|
||||
}
|
||||
if (e) {
|
||||
type_t *t = get_type (e);
|
||||
|
||||
if (e->type == ex_error)
|
||||
return e;
|
||||
if (f->def->type->aux_type == &type_void) {
|
||||
if (!options.traditional)
|
||||
return error (e, "returning a value for a void function");
|
||||
warning (e, "returning a value for a void function");
|
||||
}
|
||||
if (f->def->type->aux_type == &type_float && e->type == ex_integer) {
|
||||
e->type = ex_float;
|
||||
e->e.float_val = e->e.integer_val;
|
||||
t = &type_float;
|
||||
}
|
||||
if (t == &type_void) {
|
||||
t = f->def->type->aux_type;
|
||||
e->type = expr_types[t->type];
|
||||
}
|
||||
if (!type_assignable (f->def->type->aux_type, t)) {
|
||||
if (!options.traditional)
|
||||
return error (e, "type mismatch for return value of %s",
|
||||
f->def->name);
|
||||
warning (e, "type mismatch for return value of %s",
|
||||
f->def->name);
|
||||
}
|
||||
if (e->type == ex_error)
|
||||
return e;
|
||||
if (f->def->type->aux_type == &type_void) {
|
||||
if (!options.traditional)
|
||||
return error (e, "returning a value for a void function");
|
||||
warning (e, "returning a value for a void function");
|
||||
}
|
||||
if (e->type == ex_bool) {
|
||||
if (f->def->type->aux_type == &type_float)
|
||||
e = conditional_expr (e, new_float_expr (1), new_float_expr (0));
|
||||
else if (f->def->type->aux_type == &type_integer)
|
||||
e = conditional_expr (e, new_integer_expr (1),
|
||||
new_integer_expr (0));
|
||||
else if (f->def->type->aux_type == &type_uinteger)
|
||||
e = conditional_expr (e, new_uinteger_expr (1),
|
||||
new_uinteger_expr (0));
|
||||
}
|
||||
if (f->def->type->aux_type == &type_float && e->type == ex_integer) {
|
||||
e->type = ex_float;
|
||||
e->e.float_val = e->e.integer_val;
|
||||
t = &type_float;
|
||||
}
|
||||
if (t == &type_void) {
|
||||
t = f->def->type->aux_type;
|
||||
e->type = expr_types[t->type];
|
||||
}
|
||||
if (!type_assignable (f->def->type->aux_type, t)) {
|
||||
if (!options.traditional)
|
||||
return error (e, "type mismatch for return value of %s",
|
||||
f->def->name);
|
||||
warning (e, "type mismatch for return value of %s",
|
||||
f->def->name);
|
||||
}
|
||||
return new_unary_expr ('r', e);
|
||||
}
|
||||
|
@ -2179,6 +2327,7 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2)
|
|||
type_t *type1 = get_type (e1);
|
||||
type_t *type2 = get_type (e2);
|
||||
expr_t *tlabel = new_label_expr ();
|
||||
expr_t *flabel = new_label_expr ();
|
||||
expr_t *elabel = new_label_expr ();
|
||||
|
||||
if (cond->type == ex_error)
|
||||
|
@ -2188,8 +2337,14 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2)
|
|||
if (e2->type == ex_error)
|
||||
return e2;
|
||||
|
||||
cond = convert_bool (cond, 1);
|
||||
|
||||
backpatch (cond->e.bool.true_list, tlabel);
|
||||
backpatch (cond->e.bool.false_list, flabel);
|
||||
|
||||
block->e.block.result = (type1 == type2) ? new_temp_def_expr (type1) : 0;
|
||||
append_expr (block, new_binary_expr ('i', test_expr (cond, 1), tlabel));
|
||||
append_expr (block, cond);
|
||||
append_expr (cond->e.bool.e, flabel);
|
||||
if (block->e.block.result)
|
||||
append_expr (block, assign_expr (block->e.block.result, e2));
|
||||
else
|
||||
|
|
|
@ -161,7 +161,7 @@ expr_t *argv_expr (void);
|
|||
%type <expr> const opt_expr expr element_list element_list1 element
|
||||
%type <expr> string_val opt_state_expr array_decl
|
||||
%type <expr> statement statements statement_block
|
||||
%type <expr> break_label continue_label enum_list enum
|
||||
%type <expr> label break_label continue_label enum_list enum
|
||||
%type <expr> unary_expr primary cast_expr opt_arg_list arg_list
|
||||
%type <function> begin_function
|
||||
%type <def_list> save_inits
|
||||
|
@ -654,25 +654,23 @@ statement
|
|||
{
|
||||
expr_t *l1 = new_label_expr ();
|
||||
expr_t *l2 = break_label;
|
||||
expr_t *e;
|
||||
|
||||
restore_local_inits ($7);
|
||||
free_local_inits ($7);
|
||||
|
||||
$$ = new_block_expr ();
|
||||
|
||||
e = new_binary_expr ('n', test_expr ($5, 1), l2);
|
||||
e->line = $5->line;
|
||||
e->file = $5->file;
|
||||
append_expr ($$, e);
|
||||
append_expr ($$, new_unary_expr ('g', continue_label));
|
||||
append_expr ($$, l1);
|
||||
append_expr ($$, $8);
|
||||
append_expr ($$, continue_label);
|
||||
e = new_binary_expr ('i', test_expr ($5, 1), l1);
|
||||
e->line = $5->line;
|
||||
e->file = $5->file;
|
||||
append_expr ($$, e);
|
||||
append_expr ($$, l2);
|
||||
|
||||
$5 = convert_bool ($5, 1);
|
||||
backpatch ($5->e.bool.true_list, l1);
|
||||
backpatch ($5->e.bool.false_list, l2);
|
||||
append_expr ($5->e.bool.e, l2);
|
||||
append_expr ($$, $5);
|
||||
|
||||
break_label = $2;
|
||||
continue_label = $3;
|
||||
}
|
||||
|
@ -685,8 +683,13 @@ statement
|
|||
append_expr ($$, l1);
|
||||
append_expr ($$, $4);
|
||||
append_expr ($$, continue_label);
|
||||
append_expr ($$, new_binary_expr ('i', test_expr ($7, 1), l1));
|
||||
append_expr ($$, break_label);
|
||||
|
||||
$7 = convert_bool ($7, 1);
|
||||
backpatch ($7->e.bool.true_list, l1);
|
||||
backpatch ($7->e.bool.false_list, break_label);
|
||||
append_expr ($7->e.bool.e, break_label);
|
||||
append_expr ($$, $7);
|
||||
|
||||
break_label = $2;
|
||||
continue_label = $3;
|
||||
}
|
||||
|
@ -703,20 +706,22 @@ statement
|
|||
}
|
||||
| IF '(' expr ')' save_inits statement
|
||||
{
|
||||
expr_t *l1 = new_label_expr ();
|
||||
expr_t *e;
|
||||
expr_t *tl = new_label_expr ();
|
||||
expr_t *fl = new_label_expr ();
|
||||
|
||||
$$ = new_block_expr ();
|
||||
|
||||
restore_local_inits ($5);
|
||||
free_local_inits ($5);
|
||||
|
||||
e = new_binary_expr ('n', test_expr ($3, 1), l1);
|
||||
e->line = $3->line;
|
||||
e->file = $3->file;
|
||||
append_expr ($$, e);
|
||||
$3 = convert_bool ($3, 1);
|
||||
backpatch ($3->e.bool.true_list, tl);
|
||||
backpatch ($3->e.bool.false_list, fl);
|
||||
append_expr ($3->e.bool.e, tl);
|
||||
append_expr ($$, $3);
|
||||
|
||||
append_expr ($$, $6);
|
||||
append_expr ($$, l1);
|
||||
append_expr ($$, fl);
|
||||
}
|
||||
| IF '(' expr ')' save_inits statement ELSE
|
||||
{
|
||||
|
@ -725,8 +730,9 @@ statement
|
|||
}
|
||||
statement
|
||||
{
|
||||
expr_t *l1 = new_label_expr ();
|
||||
expr_t *l2 = new_label_expr ();
|
||||
expr_t *tl = new_label_expr ();
|
||||
expr_t *fl = new_label_expr ();
|
||||
expr_t *nl = new_label_expr ();
|
||||
expr_t *e;
|
||||
hashtab_t *merged;
|
||||
hashtab_t *else_ini;
|
||||
|
@ -738,19 +744,21 @@ statement
|
|||
restore_local_inits ($5);
|
||||
free_local_inits ($5);
|
||||
|
||||
e = new_binary_expr ('n', test_expr ($3, 1), l1);
|
||||
e->line = $3->line;
|
||||
e->file = $3->file;
|
||||
append_expr ($$, e);
|
||||
$3 = convert_bool ($3, 1);
|
||||
backpatch ($3->e.bool.true_list, tl);
|
||||
backpatch ($3->e.bool.false_list, fl);
|
||||
append_expr ($3->e.bool.e, tl);
|
||||
append_expr ($$, $3);
|
||||
|
||||
append_expr ($$, $6);
|
||||
|
||||
e = new_unary_expr ('g', l2);
|
||||
e = new_unary_expr ('g', nl);
|
||||
append_expr ($$, e);
|
||||
|
||||
append_expr ($$, l1);
|
||||
append_expr ($$, fl);
|
||||
append_expr ($$, $9);
|
||||
append_expr ($$, l2);
|
||||
append_expr ($$, nl);
|
||||
|
||||
merged = merge_local_inits ($<def_list>8, else_ini);
|
||||
restore_local_inits (merged);
|
||||
free_local_inits (merged);
|
||||
|
@ -760,8 +768,14 @@ statement
|
|||
| FOR break_label continue_label
|
||||
'(' opt_expr ';' opt_expr ';' opt_expr ')' save_inits statement
|
||||
{
|
||||
expr_t *l1 = new_label_expr ();
|
||||
expr_t *l2 = break_label;
|
||||
expr_t *tl = new_label_expr ();
|
||||
expr_t *fl = break_label;
|
||||
expr_t *l1 = 0;
|
||||
int line = pr.source_line;
|
||||
string_t file = pr.source_file;
|
||||
|
||||
pr.source_line = $7->line;
|
||||
pr.source_file = $7->file;
|
||||
|
||||
restore_local_inits ($11);
|
||||
free_local_inits ($11);
|
||||
|
@ -769,17 +783,29 @@ statement
|
|||
$$ = new_block_expr ();
|
||||
|
||||
append_expr ($$, $5);
|
||||
if ($7)
|
||||
append_expr ($$, new_binary_expr ('n', test_expr ($7, 1), l2));
|
||||
append_expr ($$, l1);
|
||||
if ($7) {
|
||||
l1 = new_label_expr ();
|
||||
append_expr ($$, new_unary_expr ('g', l1));
|
||||
}
|
||||
append_expr ($$, tl);
|
||||
append_expr ($$, $12);
|
||||
append_expr ($$, continue_label);
|
||||
append_expr ($$, $9);
|
||||
if ($5)
|
||||
append_expr ($$, new_binary_expr ('i', test_expr ($7, 1), l1));
|
||||
append_expr ($$, l2);
|
||||
if ($7) {
|
||||
append_expr ($$, l1);
|
||||
$7 = convert_bool ($7, 1);
|
||||
backpatch ($7->e.bool.true_list, tl);
|
||||
backpatch ($7->e.bool.false_list, fl);
|
||||
append_expr ($7->e.bool.e, fl);
|
||||
append_expr ($$, $7);
|
||||
} else {
|
||||
append_expr ($$, fl);
|
||||
}
|
||||
break_label = $2;
|
||||
continue_label = $3;
|
||||
|
||||
pr.source_line = line;
|
||||
pr.source_file = file;
|
||||
}
|
||||
| expr ';'
|
||||
{
|
||||
|
@ -787,6 +813,13 @@ statement
|
|||
}
|
||||
;
|
||||
|
||||
label
|
||||
: /* empty */
|
||||
{
|
||||
$$ = new_label_expr ();
|
||||
}
|
||||
;
|
||||
|
||||
break_label
|
||||
: /* empty */
|
||||
{
|
||||
|
@ -864,8 +897,8 @@ expr
|
|||
| expr '=' expr { $$ = assign_expr ($1, $3); }
|
||||
| expr ASX expr { $$ = asx_expr ($2, $1, $3); }
|
||||
| expr '?' expr ':' expr { $$ = conditional_expr ($1, $3, $5); }
|
||||
| expr AND expr { $$ = binary_expr (AND, $1, $3); }
|
||||
| expr OR expr { $$ = binary_expr (OR, $1, $3); }
|
||||
| expr AND label expr { $$ = bool_expr (AND, $3, $1, $4); }
|
||||
| expr OR label expr { $$ = bool_expr (OR, $3, $1, $4); }
|
||||
| expr EQ expr { $$ = binary_expr (EQ, $1, $3); }
|
||||
| expr NE expr { $$ = binary_expr (NE, $1, $3); }
|
||||
| expr LE expr { $$ = binary_expr (LE, $1, $3); }
|
||||
|
|
Loading…
Reference in a new issue