/* basic simplifying procedure */
int t
; /* take on the values LVAL, RVAL, and SUBVAL */
register ptr e
; /* points to an expression */
ptr
exio(), exioop(), dblop(), setfield(), gentemp();
TEST
fprintf(diagfile
, "simple(%d; tag %d,%d)\n", t
,tag
,subtype
);
case TNOTOP
: /* not not = yes */
case TLOGOP
: /* de Morgan's Law */
lp
->subtype
= (OPOR
+OPAND
) - lp
->subtype
;
lp
->leftp
= mknode(TNOTOP
,OPNOT
,lp
->leftp
, PNULL
);
lp
->rightp
=mknode(TNOTOP
,OPNOT
,lp
->rightp
, PNULL
);
case TRELOP
: /* reverse the condition */
lp
->subtype
= (OPEQ
+OPNE
) - lp
->subtype
;
e
->leftp
= simple(RVAL
,lp
);
mknode(TASGNOP
,0, gentemp(e
->leftp
), e
));
if(equals(lp
->leftp
, ".false."))
e
->leftp
= copys(".true.");
else if(equals(lp
->leftp
, ".true."))
e
->leftp
= copys(".false.");
case TLOGOP
: switch(subtype
) {
lp
= e
->leftp
= simple(RVAL
, lp
);
mknode(TASGNOP
,0, gent(TYLOG
,0),lp
));
return( simple(LVAL
, mknode(TASGNOP
,subtype
,lp
,rp
)) );
fatal("impossible logical operator");
lp
= e
->leftp
= simple(RVAL
,lp
);
e
->leftp
= simple(RVAL
,lp
);
e
->rightp
= simple(RVAL
,rp
);
if(tag
==TAROP
&& isicon(rp
,&b
) )
{ /* simplify a*1, a/1 , a+0, a-0 */
if( ((subtype
==OPSTAR
||subtype
==OPSLASH
) && b
==1) ||
((subtype
==OPPLUS
||subtype
==OPMINUS
) && b
==0) )
if(isicon(lp
, &a
)) /* try folding const op const */
if(e1
!=e
|| e1
->tag
!=TAROP
)
if(ltag
==TAROP
&& lp
->needpar
==0 && isicon(lp
->rightp
,&a
) )
{ /* look for cases of (e op const ) op' const */
if( (subtype
==OPPLUS
||subtype
==OPMINUS
) &&
(lsubt
==OPPLUS
||lsubt
==OPMINUS
) )
{ /* (e +- const) +- const */
c
= (subtype
==OPPLUS
? 1 : -1) * b
+
(lsubt
==OPPLUS
? 1 : -1) * a
;
(subtype
==OPSLASH
&& a
%b
==0)) )
{ /* (e * const ) (* or /) const */
c
= (subtype
==OPSTAR
? a
*b
: a
/b
);
if(ltag
==TAROP
&& (lsubt
==OPPLUS
|| lsubt
==OPMINUS
) &&
subtype
==OPSLASH
&& divides(lp
,conval(rp
)) )
e
->leftp
= mknode(TAROP
,OPSLASH
,lp
->leftp
, cpexpr(rp
));
e
->rightp
= mknode(TAROP
,OPSLASH
,lp
->rightp
, rp
);
else if( tag
==TRELOP
&& isicon(lp
,&a
) && isicon(rp
,&b
) )
if(e1
!=e
|| e1
->tag
!=TRELOP
)
e
= simple(LVAL
, mknode(TASGNOP
,0, gentemp(e
),e
));
{ /* test for legal Fortran c*v +-c form */
if(tag
==TAROP
&& (subtype
==OPPLUS
|| subtype
==OPMINUS
))
if(rp
->tag
==TCONST
&& rp
->vtype
==TYINT
)
e
->leftp
= simple(SUBVAL
, lp
);
else if( !cvform(e
) ) goto makesub
;
if( lp
->tag
!=TFTNBLOCK
&& ioop(lp
->sthead
->namep
) )
e
->rightp
= simple(RVAL
, rp
);
e
= simple(RVAL
, mknode(TASGNOP
,0, gentemp(e
),e
));
e
->vsubs
= simple(SUBVAL
, e
->vsubs
);
if(t
==SUBVAL
&& !vform(e
))
if(t
==SUBVAL
&& e
->vtype
!=TYINT
)
lp
= e
->leftp
= simple(LVAL
,lp
);
if(subtype
==OP2OR
|| subtype
==OP2AND
)
rp
= e
->rightp
= simple(RVAL
,rp
);
excall(mkcall(mkftnblock(TYSUBR
,"ef1asc"), arg4(cpexpr(lp
),rp
)));
else if(e
->vtype
== TYSTRUCT
)
if(lp
->vtypep
->strsize
!= rp
->vtypep
->strsize
)
fatal("simple: attempt to assign incompatible structures");
e1
= mkchain(cpexpr(lp
),mkchain(rp
,
mkchain(mkint(lp
->vtypep
->strsize
),CHNULL
)));
excall(mkcall(mkftnblock(TYSUBR
,"ef1ass"),
mknode(TLIST
, 0, e1
, PNULL
) ));
else if(lp
->vtype
== TYFIELD
)
if(subtype
!= OPASGN
) /* but is one of += etc */
rp
= e
->rightp
= simple(RVAL
, mknode(
(subtype
<=OPPOWER
?TAROP
:TLOGOP
),subtype
,
cpexpr(e
->leftp
),e
->rightp
));
if(t
== SUBVAL
) goto top
;
for(p
=lp
; p
; p
= p
->nextp
)
p
->datap
= simple(t
, p
->datap
);
exprerr("type match error", CNULL
);
if(t
==SUBVAL
&& e
->vtype
!=TYINT
)
warn1("Line %d. Non-integer subscript", yylineno
);
return( simple(RVAL
, mknode(TASGNOP
,0,gent(TYINT
,PNULL
),e
)) );
if(lp
->tag
!=TCONST
&& lp
->tag
!=TNEGOP
)
if(rp
->tag
!=TCONST
&& rp
->tag
!=TNEGOP
)
if( !isicon(lp
,&a
) || !isicon(rp
,&b
) )
if(a
%b
!=0 && (a
<0 || b
<0) )
fatal("fold: illegal binary operator");
else return(mknode(TNEGOP
,OPMINUS
, mkint(-c
), PNULL
) );
if( !isicon(lp
,&a
) || !isicon(rp
,&b
) )
fatal("fold: invalid relational operator");
return( mkconst(TYLOG
, (c
? ".true." : ".false.")) );
if(lp
->vtype
!=TYLOG
|| rp
->vtype
!=TYLOG
)
a
= equals(lp
->leftp
, ".true.");
b
= equals(rp
->leftp
, ".true.");
fatal("fold: invalid logical operator");
return( mkconst(TYLOG
, (c
? ".true." : ".false")) );
ptr
coerce(t
,e
) /* coerce expression e to type t */
e
->leftp
= coerce(t
, e
->leftp
);
econst
= (e
->tag
== TCONST
);
TEST
fprintf(diagfile
, "coerce type %d to type %d\n", et
, t
);
e
= mkcall(builtin(TYINT
,"ifix"), arg1(e
));
e
->leftp
= conrep(e
->leftp
, ".");
e
= mkcall(builtin(TYREAL
,"float"), arg1(e
));
for(s
=e
->leftp
; *s
&& *s
!='d';++s
)
e
= mkcall(builtin(TYREAL
,"sngl"), arg1(e
));
case TYCOMPLEX TO TYREAL
:
s1
= (char *)(e
->leftp
) + 1;
while(*s1
!=',' && *s1
!='\0')
e
= mkcall(mkftnblock(TYREAL
,"real"), arg1(e
));
e
->leftp
= conrep(e
->leftp
,"d0");
case TYCOMPLEX TO TYLREAL
:
for(s
=e
->leftp
; *s
&& *s
!='e'; ++s
)
else e
->leftp
= conrep(e
->leftp
,"d0");
e
= mkcall(builtin(TYLREAL
,"dble"), arg1(e
));
case TYLREAL TO TYCOMPLEX
:
case TYREAL TO TYCOMPLEX
:
sprintf(buff
, "(%s,0.)", e
->leftp
);
e
= mkcall(builtin(TYCOMPLEX
,"cmplx"),
arg2(e
, mkconst(TYREAL
,"0.")));
exprerr("impossible conversion", "");
/* check whether expression is in form c, v, or v*c */
return(p
->vtype
== TYINT
);
if(p
->subtype
==OPSTAR
&& p
->rightp
->tag
==TCONST
&& p
->rightp
->vtype
==TYINT
&& vform(p
->leftp
))
/* is p a simple integer variable */
return( p
->tag
==TNAME
&& p
->vtype
==TYINT
&& p
->vdim
==0
&& p
->voffset
==0 && p
->vsubs
==0) ;
q
= mknode(TNOTOP
,OPNOT
, cpexpr(p
->leftp
), PNULL
);
else q
= cpexpr(p
->leftp
);
exasgn(cpexpr(p
->leftp
), OPASGN
, p
->rightp
);
return( divides(a
->leftp
,b
) );
return( conval(a
) % b
== 0);
return(divides(a
->leftp
,b
)&&
return(divides(a
->rightp
,b
));
/* truncate floating point constant to integer */
char digit
[MAXD
+1]; /* buffer into which digits are placed */
char *first
; /* points to first nonzero digit */
register char *end
; /* points at position past last digit */
register char *dot
; /* decimal point is immediately to left of this digit */
for(s
= e
->leftp
; *s
; ++s
)
else if(*s
=='d' || *s
=='e')
else fatal1("impossible character %d in floating constant", *s
);
for(first
= digit
; first
<end
&& *first
=='0' ; ++first
)