diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index a0bf5ec93..c8c715fc6 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -11,9 +11,9 @@ X = operator ( var += expr, etc. ) X allow temp defs at higher levels X move the chained funcion support out of emit_function_expr into funciton_expr +X pre- and post- increment operators (++ and --) I gut out old parser o switch/case, for any type o break/continue keywords for switch() and for(;;) o quaternion type. Tricky: requires 4 word args/return -o pre- and post- increment operators (++ and --) o CSE optimisations diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 7dbe85a76..69e288c4d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -92,6 +92,7 @@ expr_t *unary_expr (int op, expr_t *e); expr_t *function_expr (expr_t *e1, expr_t *e2); expr_t *return_expr (function_t *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); +expr_t *incop_expr (int op, expr_t *e, int postop); def_t *emit_statement (int line, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c); void emit_expr (expr_t *e); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 92b58ce4f..201f1eef7 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -812,31 +812,7 @@ asx_expr (int op, expr_t *e1, expr_t *e2) { expr_t *e = new_expr (); *e = *e1; - switch (op) { - case ASADD: - return binary_expr ('=', e, binary_expr ('+', e1, e2)); - case ASSUB: - return binary_expr ('=', e, binary_expr ('-', e1, e2)); - case ASMUL: - return binary_expr ('=', e, binary_expr ('*', e1, e2)); - case ASDIV: - return binary_expr ('=', e, binary_expr ('/', e1, e2)); - case ASAND: - return binary_expr ('=', e, binary_expr ('&', e1, e2)); - case ASOR: - return binary_expr ('=', e, binary_expr ('|', e1, e2)); - case ASXOR: - return binary_expr ('=', e, binary_expr ('^', e1, e2)); - case ASMOD: - return binary_expr ('=', e, binary_expr ('%', e1, e2)); - case ASSHL: - return binary_expr ('=', e, binary_expr (SHL, e1, e2)); - case ASSHR: - return binary_expr ('=', e, binary_expr (SHR, e1, e2)); - default: - error (e1, "invalid operand for asx"); - } - return 0; + return binary_expr ('=', e, binary_expr (op, e1, e2)); } expr_t * @@ -1138,3 +1114,29 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2) append_expr (block, elabel); return block; } + +expr_t * +incop_expr (int op, expr_t *e, int postop) +{ + expr_t *one = new_expr (); + expr_t *incop; + + one->type = ex_integer; // integer constants get auto-cast to float + one->e.integer_val = 1; + incop = asx_expr (op, e, one); + if (postop) { + expr_t *temp; + type_t *type; + expr_t *block = new_block_expr (); + + type = e->type == ex_def + ? e->e.def->type + : e->e.expr.type; + temp = new_temp_def_expr (type); + append_expr (block, binary_expr ('=', temp, e)); + append_expr (block, incop); + block->e.block.result = temp; + return block; + } + return incop; +} diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 6a51f105c..01598ea5c 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -95,21 +95,26 @@ m ([\-+]?) s_file = ReuseString (pr_immediate_string); } +[+\-*/&|^%]= { + yylval.op = yytext[0]; + printf ("%s\n", yytext); + return ASX; + } + +"<<=" { + yylval.op = SHL; + return ASX; + } + +">>=" { + yylval.op = SHR; + return ASX; + } + [!(){}.*/&|^~+\-=\[\];,#%?:] return yytext[0]; "..." return ELIPSIS; -"+=" return ASADD; -"-=" return ASSUB; -"*=" return ASMUL; -"/=" return ASDIV; -"&=" return ASAND; -"|=" return ASOR; -"^=" return ASXOR; -"%=" return ASMOD; -"<<=" return ASSHL; -">>=" return ASSHR; - "<<" return SHL; ">>" return SHR; @@ -122,6 +127,16 @@ m ([\-+]?) "<" return LT; ">" return GT; +"++" { + yylval.op = '+'; + return INCOP; + } + +"--" { + yylval.op = '-'; + return INCOP; + } + "$"{s}*{ID} { int ret = do_grab(yytext); if (ret > 0) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index bcc7858e0..62a0b3700 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -33,6 +33,7 @@ typedef struct { %} %union { + int op; scope_t scope; def_t *def; type_t *type; @@ -45,14 +46,15 @@ typedef struct { function_t *function; } -%right '=' ASADD ASSUB ASMUL ASDIV ASAND ASOR ASXOR ASMOD ASSHL ASSHR +%right '=' ASX %right '?' ':' %left OR AND %left EQ NE LE GE LT GT %left SHL SHR %left '+' '-' %left '*' '/' '&' '|' '^' '%' -%left '!' '~' +//%left '!' '~' +%right UNARY INCOP %right '(' %left '.' @@ -442,16 +444,7 @@ opt_expr expr : expr '=' expr { $$ = binary_expr ('=', $1, $3); } - | expr ASADD expr { $$ = asx_expr (ASADD, $1, $3); } - | expr ASSUB expr { $$ = asx_expr (ASSUB, $1, $3); } - | expr ASMUL expr { $$ = asx_expr (ASMUL, $1, $3); } - | expr ASDIV expr { $$ = asx_expr (ASDIV, $1, $3); } - | expr ASAND expr { $$ = asx_expr (ASAND, $1, $3); } - | expr ASOR expr { $$ = asx_expr (ASOR, $1, $3); } - | expr ASXOR expr { $$ = asx_expr (ASXOR, $1, $3); } - | expr ASMOD expr { $$ = asx_expr (ASMOD, $1, $3); } - | expr ASSHL expr { $$ = asx_expr (ASSHL, $1, $3); } - | expr ASSHR expr { $$ = asx_expr (ASSHR, $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); } @@ -474,9 +467,12 @@ expr | expr '(' arg_list ')' { $$ = function_expr ($1, $3); } | expr '(' ')' { $$ = function_expr ($1, 0); } | expr '.' expr { $$ = binary_expr ('.', $1, $3); } - | '-' expr %prec '!' { $$ = unary_expr ('-', $2); } - | '!' expr { $$ = unary_expr ('!', $2); } - | '~' expr { $$ = unary_expr ('~', $2); } + | '+' expr %prec UNARY { $$ = $2; } + | '-' expr %prec UNARY { $$ = unary_expr ('-', $2); } + | '!' expr %prec UNARY { $$ = unary_expr ('!', $2); } + | '~' expr %prec UNARY { $$ = unary_expr ('~', $2); } + | INCOP expr { $$ = incop_expr ($1, $2, 0); } + | expr INCOP { $$ = incop_expr ($2, $1, 1); } | NAME { $$ = new_expr ();