#include "gmqcc.h"
#include "lexer.h"
-#define PARSER_HT_FIELDS 0
-#define PARSER_HT_GLOBALS 1
/* beginning of locals */
#define PARSER_HT_LOCALS 2
parseerror(parser, "invalid types for logical operation with -fperl-logic: %s and %s", ty1, ty2);
return false;
}
- if (OPTS_FLAG(CORRECT_LOGIC)) {
- /* non-floats need to be NOTed */
- for (i = 0; i < 2; ++i) {
- if (exprs[i]->expression.vtype != TYPE_FLOAT) {
- if (type_not_instr[exprs[i]->expression.vtype] == AINSTR_END) {
- ast_type_to_string(exprs[0], ty1, sizeof(ty1));
- ast_type_to_string(exprs[1], ty2, sizeof(ty2));
- parseerror(parser, "invalid types for logical operation with -fcorrect-logic: %s and %s", ty1, ty2);
- return false;
- }
- out = (ast_expression*)ast_unary_new(ctx, type_not_instr[exprs[i]->expression.vtype], exprs[i]);
- if (!out)
- break;
- exprs[i] = out; out = NULL;
+ for (i = 0; i < 2; ++i) {
+ if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->expression.vtype == TYPE_VECTOR) {
+ out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
+ if (!out) break;
+ out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
+ if (!out) break;
+ exprs[i] = out; out = NULL;
+ if (OPTS_FLAG(PERL_LOGIC)) {
+ /* here we want to keep the right expressions' type */
+ break;
}
- if (OPTS_FLAG(PERL_LOGIC))
+ }
+ else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->expression.vtype == TYPE_STRING) {
+ out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]);
+ if (!out) break;
+ out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
+ if (!out) break;
+ exprs[i] = out; out = NULL;
+ if (OPTS_FLAG(PERL_LOGIC)) {
+ /* here we want to keep the right expressions' type */
break;
+ }
}
}
out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
{
bool ifnot = false;
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);
+ if (!cond) {
+ ast_unref(prev);
+ parseerror(parser, "internal error: failed to process condition");
+ return NULL;
+ }
ifnot = !ifnot;
}
- else if (OPTS_FLAG(CORRECT_LOGIC)) {
- /* everything must use a NOT_ */
- unary = (ast_unary*)cond;
- if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
+ else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
+ {
+ /* vector types need to be cast to true booleans */
+ ast_binary *bin = (ast_binary*)cond;
+ if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
{
- /* use the right NOT_ */
- cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
+ /* in perl-logic, AND and OR take care of the -fcorrect-logic */
+ prev = cond;
+ cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
+ if (!cond) {
+ ast_unref(prev);
+ parseerror(parser, "internal error: failed to process condition");
+ return NULL;
+ }
ifnot = !ifnot;
}
}
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)
{
cond = unary->operand;
unary->operand = NULL;
ast_loop *aloop;
ast_expression *cond, *ontrue;
+ bool ifnot = false;
+
lex_ctx ctx = parser_ctx(parser);
(void)block; /* not touching */
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;
return true;
}
ast_loop *aloop;
ast_expression *cond, *ontrue;
+ bool ifnot = false;
+
lex_ctx ctx = parser_ctx(parser);
(void)block; /* not touching */
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;
return true;
}
ast_loop *aloop;
ast_expression *initexpr, *cond, *increment, *ontrue;
ast_value *typevar;
- bool retval = true;
+
+ bool retval = true;
+ bool ifnot = false;
lex_ctx ctx = parser_ctx(parser);
if (!parse_statement_or_block(parser, &ontrue))
goto onerr;
- aloop = ast_loop_new(ctx, initexpr, cond, NULL, increment, ontrue);
+ if (cond) {
+ 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;
if (!parser_leaveblock(parser))
}
else if (parser->tok == '{' || parser->tok == '[')
{
- size_t i;
if (localblock) {
parseerror(parser, "cannot declare functions within functions");
break;