enhanced constant folding code for qse_awk_t

This commit is contained in:
hyung-hwan 2011-07-24 10:17:15 +00:00
parent 59afc79821
commit b67f0ccd42
2 changed files with 403 additions and 180 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: parse.c 516 2011-07-23 09:03:48Z hyunghwan.chung $ * $Id: parse.c 517 2011-07-23 16:17:15Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -3340,108 +3340,209 @@ static qse_awk_nde_t* parse_expr_dc (
#define INT_BINOP_REAL(x,op,y) \ #define INT_BINOP_REAL(x,op,y) \
(((qse_awk_nde_int_t*)x)->val op ((qse_awk_nde_real_t*)y)->val) (((qse_awk_nde_int_t*)x)->val op ((qse_awk_nde_real_t*)y)->val)
#define REAL_BINOP_INT(x,op,y) \
(((qse_awk_nde_real_t*)x)->val op ((qse_awk_nde_int_t*)y)->val)
#define REAL_BINOP_REAL(x,op,y) \ #define REAL_BINOP_REAL(x,op,y) \
(((qse_awk_nde_real_t*)x)->val op ((qse_awk_nde_real_t*)y)->val) (((qse_awk_nde_real_t*)x)->val op ((qse_awk_nde_real_t*)y)->val)
#if 0 union folded_t
static qse_awk_nde_t* fold_constants_for_binop (
qse_awk_nde_t* left, qse_awk_nde_t* right, int opcode)
{ {
int fold = 0; qse_long_t l;
qse_long_t folded_l; qse_real_t r;
qse_real_t folded_r; };
typedef union folded_t folded_t;
static int fold_constants_for_binop (
qse_awk_t* awk, qse_awk_nde_t* left, qse_awk_nde_t* right, int opcode, folded_t* folded)
{
int fold = -1;
/* TODO: can i shorten various comparisons below?
* i hate to repeat similar code just for type difference */
if (left->type == QSE_AWK_NDE_INT && if (left->type == QSE_AWK_NDE_INT &&
right->type == QSE_AWK_NDE_INT) right->type == QSE_AWK_NDE_INT)
{ {
fold = 1; fold = QSE_AWK_NDE_INT;
switch (opcode) switch (opcode)
{ {
case QSE_AWK_BINOP_PLUS: case QSE_AWK_BINOP_PLUS:
folded_l = INT_BINOP_INT(left,+,right); folded->l = INT_BINOP_INT(left,+,right);
break; break;
case QSE_AWK_BINOP_MINUS: case QSE_AWK_BINOP_MINUS:
folded_l = INT_BINOP_INT(left,-,right); folded->l = INT_BINOP_INT(left,-,right);
break; break;
case QSE_AWK_BINOP_MUL: case QSE_AWK_BINOP_MUL:
folded_l = INT_BINOP_INT(left,*,right); folded->l = INT_BINOP_INT(left,*,right);
break; break;
case QSE_AWK_BINOP_DIV: case QSE_AWK_BINOP_DIV:
if (INT_BINOP_INT(left,%,right)) if (INT_BINOP_INT(left,%,right))
{ {
folded_r = (qse_real_t)((qse_awk_nde_int_t*)left)->val / folded->r = (qse_real_t)((qse_awk_nde_int_t*)left)->val /
(qse_real_t)((qse_awk_nde_int_t*)right)->val; (qse_real_t)((qse_awk_nde_int_t*)right)->val;
fold = 2; fold = QSE_AWK_NDE_REAL;
break; break;
} }
/* fall through here */
case QSE_AWK_BINOP_IDIV: case QSE_AWK_BINOP_IDIV:
folded_l = INT_BINOP_INT(left,/,right); folded->l = INT_BINOP_INT(left,/,right);
break; break;
case QSE_AWK_BINOP_MOD: case QSE_AWK_BINOP_MOD:
folded_l = INT_BINOP_INT(left,%,right); folded->l = INT_BINOP_INT(left,%,right);
break; break;
default: default:
fold = 0; fold = -1;
break; break;
} }
} }
else if (left->type == QSE_AWK_NDE_REAL && else if (left->type == QSE_AWK_NDE_REAL &&
right->type == QSE_AWK_NDE_REAL) right->type == QSE_AWK_NDE_REAL)
{ {
fold = 1; fold = QSE_AWK_NDE_REAL;
switch (opcode) switch (opcode)
{ {
case QSE_AWK_BINOP_PLUS: case QSE_AWK_BINOP_PLUS:
folded_r = REAL_BINOP_REAL(left,+,right); folded->r = REAL_BINOP_REAL(left,+,right);
break; break;
case QSE_AWK_BINOP_MINUS: case QSE_AWK_BINOP_MINUS:
folded_r = REAL_BINOP_REAL(left,-,right); folded->r = REAL_BINOP_REAL(left,-,right);
break; break;
case QSE_AWK_BINOP_MUL: case QSE_AWK_BINOP_MUL:
folded_r = REAL_BINOP_REAL(left,*,right); folded->r = REAL_BINOP_REAL(left,*,right);
break; break;
case QSE_AWK_BINOP_DIV: case QSE_AWK_BINOP_DIV:
folded_r = (qse_real_t)((qse_awk_nde_int_t*)left)->val / folded->r = REAL_BINOP_REAL(left,/,right);
(qse_real_t)((qse_awk_nde_int_t*)right)->val;
break; break;
case QSE_AWK_BINOP_IDIV: case QSE_AWK_BINOP_IDIV:
folded_l = REAL_BINOP_REAL(left,/,right); folded->l = (qse_long_t)REAL_BINOP_REAL(left,/,right);
fold = QSE_AWK_NDE_INT;
break; break;
case QSE_AWK_BINOP_MOD: case QSE_AWK_BINOP_MOD:
folded_l = REAL_BINOP_REAL(left,%,right); folded->r = awk->prm.math.mod (
awk,
((qse_awk_nde_real_t*)left)->val,
((qse_awk_nde_real_t*)right)->val
);
break; break;
default: default:
fold = 0; fold = -1;
break; break;
} }
} }
else if (left->type == QSE_AWK_NDE_INT &&
right->type == QSE_AWK_NDE_REAL)
{
fold = QSE_AWK_NDE_REAL;
switch (opcode)
{
case QSE_AWK_BINOP_PLUS:
folded->r = INT_BINOP_REAL(left,+,right);
break;
case QSE_AWK_BINOP_MINUS:
folded->r = INT_BINOP_REAL(left,-,right);
break;
case QSE_AWK_BINOP_MUL:
folded->r = INT_BINOP_REAL(left,*,right);
break;
case QSE_AWK_BINOP_DIV:
folded->r = INT_BINOP_REAL(left,/,right);
break;
case QSE_AWK_BINOP_IDIV:
folded->l = (qse_long_t)
((qse_real_t)((qse_awk_nde_int_t*)left)->val /
((qse_awk_nde_real_t*)right)->val);
fold = QSE_AWK_NDE_INT;
break;
case QSE_AWK_BINOP_MOD:
folded->r = awk->prm.math.mod (
awk,
(qse_real_t)((qse_awk_nde_int_t*)left)->val,
((qse_awk_nde_real_t*)right)->val
);
break;
default:
fold = -1;
break;
}
}
else if (left->type == QSE_AWK_NDE_REAL &&
right->type == QSE_AWK_NDE_INT)
{
fold = QSE_AWK_NDE_REAL;
switch (opcode)
{
case QSE_AWK_BINOP_PLUS:
folded->r = REAL_BINOP_INT(left,+,right);
break;
case QSE_AWK_BINOP_MINUS:
folded->r = REAL_BINOP_INT(left,-,right);
break;
case QSE_AWK_BINOP_MUL:
folded->r = REAL_BINOP_INT(left,*,right);
break;
case QSE_AWK_BINOP_DIV:
folded->r = REAL_BINOP_INT(left,/,right);
break;
case QSE_AWK_BINOP_IDIV:
folded->l = (qse_long_t)
(((qse_awk_nde_int_t*)left)->val /
(qse_real_t)((qse_awk_nde_int_t*)right)->val);
fold = QSE_AWK_NDE_INT;
break;
case QSE_AWK_BINOP_MOD:
folded->r = awk->prm.math.mod (
awk,
((qse_awk_nde_real_t*)left)->val,
(qse_real_t)((qse_awk_nde_int_t*)right)->val
);
break;
default:
fold = -1;
break;
}
}
return fold;
} }
#endif
static qse_awk_nde_t* parse_binary ( static qse_awk_nde_t* parse_binary (
qse_awk_t* awk, const qse_awk_loc_t* xloc, qse_awk_t* awk, const qse_awk_loc_t* xloc,
int skipnl, const binmap_t* binmap, int skipnl, const binmap_t* binmap,
qse_awk_nde_t*(*next_level_func)(qse_awk_t*,const qse_awk_loc_t*)) qse_awk_nde_t*(*next_level_func)(qse_awk_t*,const qse_awk_loc_t*))
{ {
qse_awk_nde_exp_t* nde;
qse_awk_nde_t* left, * right; qse_awk_nde_t* left, * right;
int opcode; int opcode;
int fold;
folded_t folded;
left = next_level_func (awk, xloc); left = next_level_func (awk, xloc);
if (left == QSE_NULL) return QSE_NULL; if (left == QSE_NULL) return QSE_NULL;
while (1) do
{ {
qse_awk_loc_t rloc; qse_awk_loc_t rloc;
const binmap_t* p = binmap; const binmap_t* p = binmap;
@ -3477,13 +3578,13 @@ static qse_awk_nde_t* parse_binary (
return QSE_NULL; return QSE_NULL;
} }
#if 0 fold = fold_constants_for_binop (awk, left, right, opcode, &folded);
fold_constants_for_binop (left, right, opcode); if (fold == QSE_AWK_NDE_INT)
{
if (fold) if (fold == left->type)
{ {
qse_awk_clrpt (awk, right); qse_awk_clrpt (awk, right);
((qse_awk_nde_int_t*)left)->val = folded_l; ((qse_awk_nde_int_t*)left)->val = folded.l;
if (((qse_awk_nde_int_t*)left)->str) if (((qse_awk_nde_int_t*)left)->str)
{ {
QSE_AWK_FREE (awk, ((qse_awk_nde_int_t*)left)->str); QSE_AWK_FREE (awk, ((qse_awk_nde_int_t*)left)->str);
@ -3491,9 +3592,89 @@ static qse_awk_nde_t* parse_binary (
((qse_awk_nde_int_t*)left)->len = 0; ((qse_awk_nde_int_t*)left)->len = 0;
} }
} }
else if (fold == right->type)
{
qse_awk_clrpt (awk, left);
((qse_awk_nde_int_t*)right)->val = folded.l;
if (((qse_awk_nde_int_t*)right)->str)
{
QSE_AWK_FREE (awk, ((qse_awk_nde_int_t*)right)->str);
((qse_awk_nde_int_t*)right)->str = QSE_NULL;
((qse_awk_nde_int_t*)right)->len = 0;
}
left = right;
}
else else
{ {
#endif qse_awk_nde_int_t* tmp;
qse_awk_clrpt (awk, right);
qse_awk_clrpt (awk, left);
tmp = (qse_awk_nde_int_t*) QSE_AWK_ALLOC (
awk, QSE_SIZEOF(qse_awk_nde_int_t));
if (tmp == QSE_NULL)
{
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL;
}
QSE_MEMSET (tmp, 0, QSE_SIZEOF(qse_awk_nde_int_t));
tmp->type = QSE_AWK_NDE_INT;
tmp->loc = *xloc;
tmp->val = folded.l;
left = (qse_awk_nde_t*)tmp;
}
}
else if (fold == QSE_AWK_NDE_REAL)
{
if (fold == left->type)
{
qse_awk_clrpt (awk, right);
((qse_awk_nde_real_t*)left)->val = folded.r;
if (((qse_awk_nde_real_t*)left)->str)
{
QSE_AWK_FREE (awk, ((qse_awk_nde_real_t*)left)->str);
((qse_awk_nde_real_t*)left)->str = QSE_NULL;
((qse_awk_nde_real_t*)left)->len = 0;
}
}
else if (fold == right->type)
{
qse_awk_clrpt (awk, left);
((qse_awk_nde_real_t*)right)->val = folded.r;
if (((qse_awk_nde_real_t*)right)->str)
{
QSE_AWK_FREE (awk, ((qse_awk_nde_real_t*)right)->str);
((qse_awk_nde_real_t*)right)->str = QSE_NULL;
((qse_awk_nde_real_t*)right)->len = 0;
}
left = right;
}
else
{
qse_awk_nde_real_t* tmp;
qse_awk_clrpt (awk, right);
qse_awk_clrpt (awk, left);
tmp = (qse_awk_nde_real_t*) QSE_AWK_ALLOC (
awk, QSE_SIZEOF(qse_awk_nde_real_t));
if (tmp == QSE_NULL)
{
SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc);
return QSE_NULL;
}
QSE_MEMSET (tmp, 0, QSE_SIZEOF(qse_awk_nde_real_t));
tmp->type = QSE_AWK_NDE_REAL;
tmp->loc = *xloc;
tmp->val = folded.r;
left = (qse_awk_nde_t*)tmp;
}
}
else
{
qse_awk_nde_exp_t* nde;
nde = (qse_awk_nde_exp_t*) QSE_AWK_ALLOC ( nde = (qse_awk_nde_exp_t*) QSE_AWK_ALLOC (
awk, QSE_SIZEOF(qse_awk_nde_exp_t)); awk, QSE_SIZEOF(qse_awk_nde_exp_t));
if (nde == QSE_NULL) if (nde == QSE_NULL)
@ -3512,10 +3693,9 @@ static qse_awk_nde_t* parse_binary (
nde->right = right; nde->right = right;
left = (qse_awk_nde_t*)nde; left = (qse_awk_nde_t*)nde;
#if 0
} }
#endif
} }
while (1);
return left; return left;
} }
@ -3803,12 +3983,11 @@ static qse_awk_nde_t* parse_multiplicative (
static qse_awk_nde_t* parse_unary ( static qse_awk_nde_t* parse_unary (
qse_awk_t* awk, const qse_awk_loc_t* xloc) qse_awk_t* awk, const qse_awk_loc_t* xloc)
{ {
qse_awk_nde_exp_t* nde;
qse_awk_nde_t* left; qse_awk_nde_t* left;
qse_awk_loc_t uloc; qse_awk_loc_t uloc;
int opcode; int opcode;
int fold; int fold;
qse_long_t folded_l; folded_t folded;
opcode = (MATCH(awk,TOK_PLUS))? QSE_AWK_UNROP_PLUS: opcode = (MATCH(awk,TOK_PLUS))? QSE_AWK_UNROP_PLUS:
(MATCH(awk,TOK_MINUS))? QSE_AWK_UNROP_MINUS: (MATCH(awk,TOK_MINUS))? QSE_AWK_UNROP_MINUS:
@ -3834,49 +4013,90 @@ static qse_awk_nde_t* parse_unary (
awk->parse.depth.cur.expr--; awk->parse.depth.cur.expr--;
if (left == QSE_NULL) return QSE_NULL; if (left == QSE_NULL) return QSE_NULL;
fold = 0; fold = -1;
if (left->type == QSE_AWK_NDE_INT) if (left->type == QSE_AWK_NDE_INT)
{ {
fold = 1; fold = QSE_AWK_NDE_INT;
switch (opcode) switch (opcode)
{ {
case QSE_AWK_UNROP_PLUS: case QSE_AWK_UNROP_PLUS:
folded_l = ((qse_awk_nde_int_t*)left)->val; folded.l = ((qse_awk_nde_int_t*)left)->val;
break; break;
case QSE_AWK_UNROP_MINUS: case QSE_AWK_UNROP_MINUS:
folded_l = -((qse_awk_nde_int_t*)left)->val; folded.l = -((qse_awk_nde_int_t*)left)->val;
break; break;
case QSE_AWK_UNROP_LNOT: case QSE_AWK_UNROP_LNOT:
folded_l = !((qse_awk_nde_int_t*)left)->val; folded.l = !((qse_awk_nde_int_t*)left)->val;
break; break;
case QSE_AWK_UNROP_BNOT: case QSE_AWK_UNROP_BNOT:
folded_l = ~((qse_awk_nde_int_t*)left)->val; folded.l = ~((qse_awk_nde_int_t*)left)->val;
break; break;
default: default:
fold = 0; fold = -1;
break;
}
}
else if (left->type == QSE_AWK_NDE_REAL)
{
fold = QSE_AWK_NDE_REAL;
switch (opcode)
{
case QSE_AWK_UNROP_PLUS:
folded.r = ((qse_awk_nde_real_t*)left)->val;
break;
case QSE_AWK_UNROP_MINUS:
folded.r = -((qse_awk_nde_real_t*)left)->val;
break;
case QSE_AWK_UNROP_LNOT:
folded.r = !((qse_awk_nde_real_t*)left)->val;
break;
/*
case QSE_AWK_UNROP_BNOT:
folded.r = ~((qse_awk_nde_real_t*)left)->val;
break;
*/
default:
fold = -1;
break; break;
} }
} }
if (fold) switch (fold)
{ {
((qse_awk_nde_int_t*)left)->val = folded_l; case QSE_AWK_NDE_INT:
QSE_ASSERT (left->type == fold);
((qse_awk_nde_int_t*)left)->val = folded.l;
if (((qse_awk_nde_int_t*)left)->str) if (((qse_awk_nde_int_t*)left)->str)
{ {
QSE_AWK_FREE (awk, ((qse_awk_nde_int_t*)left)->str); QSE_AWK_FREE (awk, ((qse_awk_nde_int_t*)left)->str);
((qse_awk_nde_int_t*)left)->str = QSE_NULL; ((qse_awk_nde_int_t*)left)->str = QSE_NULL;
((qse_awk_nde_int_t*)left)->len = 0; ((qse_awk_nde_int_t*)left)->len = 0;
} }
return left; return left;
}
else case QSE_AWK_NDE_REAL:
QSE_ASSERT (left->type == fold);
((qse_awk_nde_real_t*)left)->val = folded.r;
if (((qse_awk_nde_real_t*)left)->str)
{ {
QSE_AWK_FREE (awk, ((qse_awk_nde_real_t*)left)->str);
((qse_awk_nde_real_t*)left)->str = QSE_NULL;
((qse_awk_nde_real_t*)left)->len = 0;
}
return left;
default:
{
qse_awk_nde_exp_t* nde;
nde = (qse_awk_nde_exp_t*) nde = (qse_awk_nde_exp_t*)
QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_exp_t)); QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_exp_t));
if (nde == QSE_NULL) if (nde == QSE_NULL)
@ -3895,7 +4115,7 @@ static qse_awk_nde_t* parse_unary (
return (qse_awk_nde_t*)nde; return (qse_awk_nde_t*)nde;
} }
}
} }
static qse_awk_nde_t* parse_exponent ( static qse_awk_nde_t* parse_exponent (

View File

@ -1,5 +1,5 @@
/* /*
* $Id: run.c 516 2011-07-23 09:03:48Z hyunghwan.chung $ * $Id: run.c 517 2011-07-23 16:17:15Z hyunghwan.chung $
* *
Copyright 2006-2011 Chung, Hyung-Hwan. Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -4697,8 +4697,9 @@ static qse_awk_val_t* eval_binop_exp (
} }
n3 = n1 + (n2 << 1); n3 = n1 + (n2 << 1);
if (n3 == 0) switch (n3)
{ {
case 0:
/* left - int, right - int */ /* left - int, right - int */
if (l2 >= 0) if (l2 >= 0)
{ {
@ -4718,9 +4719,9 @@ static qse_awk_val_t* eval_binop_exp (
while (l2-- > 0) v /= l1; while (l2-- > 0) v /= l1;
res = qse_awk_rtx_makerealval (rtx, v); res = qse_awk_rtx_makerealval (rtx, v);
} }
} break;
else if (n3 == 1)
{ case 1:
/* left - real, right - int */ /* left - real, right - int */
if (l2 >= 0) if (l2 >= 0)
{ {
@ -4740,9 +4741,9 @@ static qse_awk_val_t* eval_binop_exp (
while (l2-- > 0) v /= r1; while (l2-- > 0) v /= r1;
res = qse_awk_rtx_makerealval (rtx, v); res = qse_awk_rtx_makerealval (rtx, v);
} }
} break;
else if (n3 == 2)
{ case 2:
/* left - int, right - real */ /* left - int, right - real */
res = qse_awk_rtx_makerealval ( res = qse_awk_rtx_makerealval (
rtx, rtx,
@ -4750,17 +4751,17 @@ static qse_awk_val_t* eval_binop_exp (
rtx->awk, (qse_real_t)l1, (qse_real_t)r2 rtx->awk, (qse_real_t)l1, (qse_real_t)r2
) )
); );
} break;
else
{ case 3:
/* left - real, right - real */ /* left - real, right - real */
QSE_ASSERT (n3 == 3);
res = qse_awk_rtx_makerealval ( res = qse_awk_rtx_makerealval (
rtx, rtx,
rtx->awk->prm.math.pow ( rtx->awk->prm.math.pow (
rtx->awk, (qse_real_t)r1,(qse_real_t)r2 rtx->awk, (qse_real_t)r1,(qse_real_t)r2
) )
); );
break;
} }
return res; return res;
@ -4996,16 +4997,17 @@ static qse_awk_val_t* eval_unary (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
qse_awk_rtx_refupval (run, left); qse_awk_rtx_refupval (run, left);
if (exp->opcode == QSE_AWK_UNROP_MINUS) switch (exp->opcode)
{ {
case QSE_AWK_UNROP_MINUS:
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (run, left, &l, &r);
if (n == -1) goto exit_func; if (n == -1) goto exit_func;
res = (n == 0)? qse_awk_rtx_makeintval (run, -l): res = (n == 0)? qse_awk_rtx_makeintval (run, -l):
qse_awk_rtx_makerealval (run, -r); qse_awk_rtx_makerealval (run, -r);
} break;
else if (exp->opcode == QSE_AWK_UNROP_LNOT)
{ case QSE_AWK_UNROP_LNOT:
if (left->type == QSE_AWK_VAL_STR) if (left->type == QSE_AWK_VAL_STR)
{ {
res = qse_awk_rtx_makeintval ( res = qse_awk_rtx_makeintval (
@ -5019,22 +5021,23 @@ static qse_awk_val_t* eval_unary (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
res = (n == 0)? qse_awk_rtx_makeintval (run, !l): res = (n == 0)? qse_awk_rtx_makeintval (run, !l):
qse_awk_rtx_makerealval (run, !r); qse_awk_rtx_makerealval (run, !r);
} }
} break;
else if (exp->opcode == QSE_AWK_UNROP_BNOT)
{ case QSE_AWK_UNROP_BNOT:
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (run, left, &l, &r);
if (n == -1) goto exit_func; if (n == -1) goto exit_func;
if (n == 1) l = (qse_long_t)r; if (n == 1) l = (qse_long_t)r;
res = qse_awk_rtx_makeintval (run, ~l); res = qse_awk_rtx_makeintval (run, ~l);
} break;
else if (exp->opcode == QSE_AWK_UNROP_PLUS)
{ case QSE_AWK_UNROP_PLUS:
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (run, left, &l, &r);
if (n == -1) goto exit_func; if (n == -1) goto exit_func;
res = (n == 0)? qse_awk_rtx_makeintval (run, l): res = (n == 0)? qse_awk_rtx_makeintval (run, l):
qse_awk_rtx_makerealval (run, r); qse_awk_rtx_makerealval (run, r);
break;
} }
exit_func: exit_func: