Deal with a number of issues in some expressions.

- Move TODO of <0 to !=-1 to boolean, as it's counter-productive otherwise.
- All a!=b except list!=list are equivalent to !(a==b).
- Change a>b to b<a to simplify cases to analize.
- Proper fall-through in some spots, or return in some others where it didn't apply.
- Simplify handling of a<-2147483648 as a&0, falling through, instead of coping with it ourselves.
This commit is contained in:
Sei Lisa 2015-03-28 20:23:47 +01:00
parent de33c2df01
commit c154d5eb0d

View file

@ -146,6 +146,8 @@ class foldconst(object):
# expression of the form !(a&-b) (if b is bool). # expression of the form !(a&-b) (if b is bool).
# TODO: Convert bool(x < 0) to bool(x & 0x80000000) # TODO: Convert bool(x < 0) to bool(x & 0x80000000)
# TODO: If function domain starts at -1, treat & 0x80000000 as ~
# TODO: If function domain starts at -1, treat < 0 as ~
def CopyNode(self, node): def CopyNode(self, node):
@ -609,41 +611,45 @@ class foldconst(object):
return return
return return
if nt in ('<=', '>=') or nt == '!=' \ if nt in ('<=', '>=') or nt == '!=' and child[0]['t'] != 'list':
and child[0]['t'] in ('float', 'integer') \ # Except for list != list, all these comparisons are compiled
and child[1]['t'] in ('float', 'integer'): # as !(a>b) etc. so we transform them here in order to reduce
# the number of cases to check.
# a<=b --> !(a>b); a>=b --> !(a<b); a!=b --> !(a==b)
SEF = 'SEF' in node SEF = 'SEF' in node
node['nt'] = {'<=':'>', '>=':'<', '!=':'=='}[nt] node['nt'] = {'<=':'>', '>=':'<', '!=':'=='}[nt]
node = parent[index] = {'nt':'!', 't':node['t'], 'ch':[node]} node = parent[index] = {'nt':'!', 't':node['t'], 'ch':[node]}
if SEF: if SEF:
node['SEF'] = True node['SEF'] = True
# Fold the new node # Fall through to optimize as '<' or '>' or '=='
self.FoldTree(parent, index)
return
if nt in ('<', '>'): if nt == '>':
# TODO: If function domain is -1..INT_MAX, treat <0 as !=-1 # Invert the inequalities to avoid doubling the cases to check.
# a>b --> b<a
nt = node['nt'] = '<'
child[1], child[0] = child[0], child[1]
# fall through to check for '<'
# i>2147483647 to FALSE if SEF, otherwise convert to a&0 if nt == '<':
# i<-2147483648 to FALSE if SEF, otherwise convert to a&0 # Convert 2147483647<i and i<-2147483648 to i&0
a, b = 0, 1 if child[0]['t'] == child[1]['t'] == 'integer' \
if child[a]['nt'] == 'CONST': and (child[0]['nt'] == 'CONST' and child[0]['value'] == 2147483647
a,b = 1,0 or child[1]['nt'] == 'CONST' and child[1]['value'] == -2147483648):
if child[b]['nt'] == 'CONST' and child[a]['t'] == child[b]['t'] == 'integer' \ a, b = 0, 1
and (nt == '>' and child[b]['value'] == 2147483647 # Put the constant in child[b]
or nt == '<' and child[b]['value'] == -2147483648): if child[a]['nt'] == 'CONST':
if 'SEF' in child[a]: a, b = 1, 0
parent[index] = node = child[b]
node['value'] = 0
return
nt = node['nt'] = '&' nt = node['nt'] = '&'
child[b]['value'] = 0 child[b]['value'] = 0
# fall through to check for '&' # fall through to check for '&'
else:
return
if nt in ('&', '|'): if nt in ('&', '|'):
# Deal with operands in any order # Deal with operands in any order
a, b = 0, 1 a, b = 0, 1
if child[a]['nt'] == 'CONST' and child[a]['t'] in ('float', 'integer'): # Put constant in child[b]
if child[b]['nt'] != 'CONST':
a, b = 1, 0 a, b = 1, 0
if child[b]['nt'] == 'CONST': if child[b]['nt'] == 'CONST':
@ -658,7 +664,7 @@ class foldconst(object):
# a&0 -> 0 if a is SEF # a&0 -> 0 if a is SEF
if 'SEF' in child[a]: if 'SEF' in child[a]:
parent[index] = child[b] parent[index] = child[b]
return return
if nt == '^': if nt == '^':
a, b = 0, 1 a, b = 0, 1