mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 14:12:36 +00:00
while/for/do now all use process_condition, ast_loop got 2 new parameters for more efficient translation
This commit is contained in:
parent
d72cb42b08
commit
a985a5cab1
3 changed files with 63 additions and 9 deletions
17
ast.c
17
ast.c
|
@ -709,8 +709,8 @@ void ast_ternary_delete(ast_ternary *self)
|
||||||
|
|
||||||
ast_loop* ast_loop_new(lex_ctx ctx,
|
ast_loop* ast_loop_new(lex_ctx ctx,
|
||||||
ast_expression *initexpr,
|
ast_expression *initexpr,
|
||||||
ast_expression *precond,
|
ast_expression *precond, bool pre_not,
|
||||||
ast_expression *postcond,
|
ast_expression *postcond, bool post_not,
|
||||||
ast_expression *increment,
|
ast_expression *increment,
|
||||||
ast_expression *body)
|
ast_expression *body)
|
||||||
{
|
{
|
||||||
|
@ -723,6 +723,9 @@ ast_loop* ast_loop_new(lex_ctx ctx,
|
||||||
self->increment = increment;
|
self->increment = increment;
|
||||||
self->body = body;
|
self->body = body;
|
||||||
|
|
||||||
|
self->pre_not = pre_not;
|
||||||
|
self->post_not = post_not;
|
||||||
|
|
||||||
if (initexpr)
|
if (initexpr)
|
||||||
ast_propagate_effects(self, initexpr);
|
ast_propagate_effects(self, initexpr);
|
||||||
if (precond)
|
if (precond)
|
||||||
|
@ -2546,6 +2549,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
else if (bpostcond) ontrue = bpostcond;
|
else if (bpostcond) ontrue = bpostcond;
|
||||||
else ontrue = bprecond;
|
else ontrue = bprecond;
|
||||||
onfalse = bout;
|
onfalse = bout;
|
||||||
|
if (self->pre_not) {
|
||||||
|
tmpblock = ontrue;
|
||||||
|
ontrue = onfalse;
|
||||||
|
onfalse = tmpblock;
|
||||||
|
}
|
||||||
if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
|
if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2581,6 +2589,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
|
||||||
else if (bincrement) ontrue = bincrement;
|
else if (bincrement) ontrue = bincrement;
|
||||||
else ontrue = bpostcond;
|
else ontrue = bpostcond;
|
||||||
onfalse = bout;
|
onfalse = bout;
|
||||||
|
if (self->post_not) {
|
||||||
|
tmpblock = ontrue;
|
||||||
|
ontrue = onfalse;
|
||||||
|
onfalse = tmpblock;
|
||||||
|
}
|
||||||
if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
|
if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
12
ast.h
12
ast.h
|
@ -449,11 +449,19 @@ struct ast_loop_s
|
||||||
ast_expression *postcond;
|
ast_expression *postcond;
|
||||||
ast_expression *increment;
|
ast_expression *increment;
|
||||||
ast_expression *body;
|
ast_expression *body;
|
||||||
|
/* For now we allow a seperate flag on whether or not the condition
|
||||||
|
* is supposed to be true or false.
|
||||||
|
* That way, the parser can generate a 'while not(!x)' for `while(x)`
|
||||||
|
* if desired, which is useful for the new -f{true,false}-empty-strings
|
||||||
|
* flag.
|
||||||
|
*/
|
||||||
|
bool pre_not;
|
||||||
|
bool post_not;
|
||||||
};
|
};
|
||||||
ast_loop* ast_loop_new(lex_ctx ctx,
|
ast_loop* ast_loop_new(lex_ctx ctx,
|
||||||
ast_expression *initexpr,
|
ast_expression *initexpr,
|
||||||
ast_expression *precond,
|
ast_expression *precond, bool pre_not,
|
||||||
ast_expression *postcond,
|
ast_expression *postcond, bool post_not,
|
||||||
ast_expression *increment,
|
ast_expression *increment,
|
||||||
ast_expression *body);
|
ast_expression *body);
|
||||||
void ast_loop_delete(ast_loop*);
|
void ast_loop_delete(ast_loop*);
|
||||||
|
|
43
parser.c
43
parser.c
|
@ -1898,9 +1898,16 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
||||||
{
|
{
|
||||||
bool ifnot = false;
|
bool ifnot = false;
|
||||||
ast_unary *unary;
|
ast_unary *unary;
|
||||||
|
ast_expression *prev;
|
||||||
|
|
||||||
if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) {
|
if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) {
|
||||||
|
prev = cond;
|
||||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
|
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
|
||||||
|
if (!cond) {
|
||||||
|
ast_unref(prev);
|
||||||
|
parseerror(parser, "internal error: failed to process condition");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
ifnot = !ifnot;
|
ifnot = !ifnot;
|
||||||
}
|
}
|
||||||
else if (OPTS_FLAG(CORRECT_LOGIC)) {
|
else if (OPTS_FLAG(CORRECT_LOGIC)) {
|
||||||
|
@ -1909,13 +1916,20 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
||||||
if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
|
if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
|
||||||
{
|
{
|
||||||
/* use the right NOT_ */
|
/* use the right NOT_ */
|
||||||
|
prev = cond;
|
||||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
|
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
|
||||||
|
if (!cond) {
|
||||||
|
ast_unref(prev);
|
||||||
|
parseerror(parser, "internal error: failed to process condition");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
ifnot = !ifnot;
|
ifnot = !ifnot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unary = (ast_unary*)cond;
|
unary = (ast_unary*)cond;
|
||||||
while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F && unary->operand->expression.vtype != TYPE_STRING)
|
while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
|
||||||
|
/*&& unary->operand->expression.vtype != TYPE_STRING) */
|
||||||
{
|
{
|
||||||
cond = unary->operand;
|
cond = unary->operand;
|
||||||
unary->operand = NULL;
|
unary->operand = NULL;
|
||||||
|
@ -2018,6 +2032,8 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out
|
||||||
ast_loop *aloop;
|
ast_loop *aloop;
|
||||||
ast_expression *cond, *ontrue;
|
ast_expression *cond, *ontrue;
|
||||||
|
|
||||||
|
bool ifnot = false;
|
||||||
|
|
||||||
lex_ctx ctx = parser_ctx(parser);
|
lex_ctx ctx = parser_ctx(parser);
|
||||||
|
|
||||||
(void)block; /* not touching */
|
(void)block; /* not touching */
|
||||||
|
@ -2053,7 +2069,12 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aloop = ast_loop_new(ctx, NULL, cond, NULL, NULL, ontrue);
|
cond = process_condition(parser, cond, &ifnot);
|
||||||
|
if (!cond) {
|
||||||
|
ast_delete(ontrue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aloop = ast_loop_new(ctx, NULL, cond, ifnot, NULL, false, NULL, ontrue);
|
||||||
*out = (ast_expression*)aloop;
|
*out = (ast_expression*)aloop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2063,6 +2084,8 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o
|
||||||
ast_loop *aloop;
|
ast_loop *aloop;
|
||||||
ast_expression *cond, *ontrue;
|
ast_expression *cond, *ontrue;
|
||||||
|
|
||||||
|
bool ifnot = false;
|
||||||
|
|
||||||
lex_ctx ctx = parser_ctx(parser);
|
lex_ctx ctx = parser_ctx(parser);
|
||||||
|
|
||||||
(void)block; /* not touching */
|
(void)block; /* not touching */
|
||||||
|
@ -2122,7 +2145,12 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
aloop = ast_loop_new(ctx, NULL, NULL, cond, NULL, ontrue);
|
cond = process_condition(parser, cond, &ifnot);
|
||||||
|
if (!cond) {
|
||||||
|
ast_delete(ontrue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aloop = ast_loop_new(ctx, NULL, NULL, false, cond, ifnot, NULL, ontrue);
|
||||||
*out = (ast_expression*)aloop;
|
*out = (ast_expression*)aloop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2132,7 +2160,9 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
|
||||||
ast_loop *aloop;
|
ast_loop *aloop;
|
||||||
ast_expression *initexpr, *cond, *increment, *ontrue;
|
ast_expression *initexpr, *cond, *increment, *ontrue;
|
||||||
ast_value *typevar;
|
ast_value *typevar;
|
||||||
bool retval = true;
|
|
||||||
|
bool retval = true;
|
||||||
|
bool ifnot = false;
|
||||||
|
|
||||||
lex_ctx ctx = parser_ctx(parser);
|
lex_ctx ctx = parser_ctx(parser);
|
||||||
|
|
||||||
|
@ -2225,7 +2255,10 @@ static bool parse_for(parser_t *parser, ast_block *block, ast_expression **out)
|
||||||
if (!parse_statement_or_block(parser, &ontrue))
|
if (!parse_statement_or_block(parser, &ontrue))
|
||||||
goto onerr;
|
goto onerr;
|
||||||
|
|
||||||
aloop = ast_loop_new(ctx, initexpr, cond, NULL, increment, ontrue);
|
cond = process_condition(parser, cond, &ifnot);
|
||||||
|
if (!cond)
|
||||||
|
goto onerr;
|
||||||
|
aloop = ast_loop_new(ctx, initexpr, cond, ifnot, NULL, false, increment, ontrue);
|
||||||
*out = (ast_expression*)aloop;
|
*out = (ast_expression*)aloop;
|
||||||
|
|
||||||
if (!parser_leaveblock(parser))
|
if (!parser_leaveblock(parser))
|
||||||
|
|
Loading…
Reference in a new issue