mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Fix remaining bug in optimizer, and minor fixes.
- Get rid of Fold(). - Handle globalmode properly. It was sometimes active during function calls. - Change all warning() calls to not use Unicode, just in case the output is redirected to file. - Cosmetic fixes and TODO items.
This commit is contained in:
parent
7f6351c5e6
commit
8907a59d5f
3 changed files with 27 additions and 22 deletions
|
@ -160,6 +160,7 @@ class optimizer(object):
|
||||||
|
|
||||||
if code0 in self.assign_ops:
|
if code0 in self.assign_ops:
|
||||||
# TODO: Eliminate redundant operations, e.g. a += 0; etc.
|
# TODO: Eliminate redundant operations, e.g. a += 0; etc.
|
||||||
|
# Consider also e.g. x -= 1 or x -= a transforming it into +=.
|
||||||
self.FoldTree(code[3])
|
self.FoldTree(code[3])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -344,12 +345,6 @@ class optimizer(object):
|
||||||
|
|
||||||
raise Exception('Internal error: This should not happen, node = ' + code0) # pragma: no cover
|
raise Exception('Internal error: This should not happen, node = ' + code0) # pragma: no cover
|
||||||
|
|
||||||
def Fold(self, code, IsGlobal = True):
|
|
||||||
assert type(code) == tuple
|
|
||||||
self.globalmode = IsGlobal and len(code) == 3
|
|
||||||
self.FoldTree(code)
|
|
||||||
del self.globalmode
|
|
||||||
|
|
||||||
def optimize(self, symtab, functions):
|
def optimize(self, symtab, functions):
|
||||||
"""Optimize the symbolic table symtab in place. Requires a table of
|
"""Optimize the symbolic table symtab in place. Requires a table of
|
||||||
predefined functions for folding constants.
|
predefined functions for folding constants.
|
||||||
|
@ -357,6 +352,8 @@ class optimizer(object):
|
||||||
self.functions = functions
|
self.functions = functions
|
||||||
self.symtab = symtab
|
self.symtab = symtab
|
||||||
|
|
||||||
|
self.globalmode = False
|
||||||
|
|
||||||
# Fold constants etc.
|
# Fold constants etc.
|
||||||
for name in symtab[0]:
|
for name in symtab[0]:
|
||||||
if name == -1:
|
if name == -1:
|
||||||
|
@ -364,13 +361,15 @@ class optimizer(object):
|
||||||
entry = symtab[0][name]
|
entry = symtab[0][name]
|
||||||
if entry[1] == 'State':
|
if entry[1] == 'State':
|
||||||
for event in entry[2]:
|
for event in entry[2]:
|
||||||
self.Fold(entry[2][event][2], False)
|
self.FoldTree(entry[2][event][2])
|
||||||
elif type(entry[2]) == tuple:
|
elif type(entry[2]) == tuple:
|
||||||
self.Fold(entry[2]) # global
|
self.globalmode = len(entry) == 3
|
||||||
if len(entry) == 3:
|
self.FoldTree(entry[2]) # global
|
||||||
|
if self.globalmode:
|
||||||
val = entry[2]
|
val = entry[2]
|
||||||
# Unfold constant
|
# Unfold constant
|
||||||
if val[0] == 'EXPR' and val[2][0] == CONSTANT:
|
if val[0] == 'EXPR' and val[2][0] == CONSTANT:
|
||||||
symtab[0][name] = entry[:2] + (val[2][2],) + entry[3:]
|
symtab[0][name] = entry[:2] + (val[2][2],) + entry[3:]
|
||||||
else:
|
else:
|
||||||
warning(u'WARNING: Expression does not collapse to a single constant.')
|
warning('WARNING: Expression does not collapse to a single constant.')
|
||||||
|
self.globalmode = False
|
||||||
|
|
|
@ -23,7 +23,7 @@ class outscript(object):
|
||||||
# is lost. So we emit a warning instead, letting the compiler
|
# is lost. So we emit a warning instead, letting the compiler
|
||||||
# report the error in the generated source.
|
# report the error in the generated source.
|
||||||
if self.globalmode and self.listmode:
|
if self.globalmode and self.listmode:
|
||||||
warning(u'Illegal combo: Key type inside a global list')
|
warning('WARNING: Illegal combo: Key type inside a global list')
|
||||||
if self.listmode or not self.globalmode:
|
if self.listmode or not self.globalmode:
|
||||||
if self.globalmode:
|
if self.globalmode:
|
||||||
pfx = '(key)'
|
pfx = '(key)'
|
||||||
|
@ -52,6 +52,7 @@ class outscript(object):
|
||||||
if '.' not in s:
|
if '.' not in s:
|
||||||
# I couldn't produce one but it's assumed that if it happens,
|
# I couldn't produce one but it's assumed that if it happens,
|
||||||
# this code deals with it correctly
|
# this code deals with it correctly
|
||||||
|
# FIXME: Not true, it should handle (float) conversion.
|
||||||
return s + exp # pragma: no cover
|
return s + exp # pragma: no cover
|
||||||
else:
|
else:
|
||||||
if '.' not in s:
|
if '.' not in s:
|
||||||
|
@ -60,6 +61,7 @@ class outscript(object):
|
||||||
exp = ''
|
exp = ''
|
||||||
while s[-1] != '.' and lslfuncs.F32(float(s[:-1]+exp)) == value:
|
while s[-1] != '.' and lslfuncs.F32(float(s[:-1]+exp)) == value:
|
||||||
s = s[:-1]
|
s = s[:-1]
|
||||||
|
# TODO: Refine.
|
||||||
if value >= 0 or self.globalmode or not self.optsigns:
|
if value >= 0 or self.globalmode or not self.optsigns:
|
||||||
return s + exp
|
return s + exp
|
||||||
return '((float)' + s + exp + ')'
|
return '((float)' + s + exp + ')'
|
||||||
|
@ -282,6 +284,9 @@ class outscript(object):
|
||||||
for name in order[0]:
|
for name in order[0]:
|
||||||
sym = symtab[0][name]
|
sym = symtab[0][name]
|
||||||
|
|
||||||
|
#DEBUG
|
||||||
|
#print name, repr(sym)
|
||||||
|
|
||||||
ret += self.dent()
|
ret += self.dent()
|
||||||
if sym[1] == 'State':
|
if sym[1] == 'State':
|
||||||
if name == 'default':
|
if name == 'default':
|
||||||
|
@ -299,10 +304,11 @@ class outscript(object):
|
||||||
self.indentlevel -= 1
|
self.indentlevel -= 1
|
||||||
ret += self.dent() + '}\n'
|
ret += self.dent() + '}\n'
|
||||||
|
|
||||||
elif len(sym) > 3: # function call
|
elif len(sym) > 3: # function definition
|
||||||
ret += self.OutFunc(sym[1], name, sym[3], symtab[sym[4]], sym[2])
|
ret += self.OutFunc(sym[1], name, sym[3], symtab[sym[4]], sym[2])
|
||||||
|
|
||||||
else: # global var
|
else: # global var
|
||||||
|
|
||||||
self.globalmode = True
|
self.globalmode = True
|
||||||
ret += sym[1] + ' ' + name
|
ret += sym[1] + ' ' + name
|
||||||
if sym[2] is not None:
|
if sym[2] is not None:
|
||||||
|
|
|
@ -6,8 +6,8 @@ import sys, re
|
||||||
# reading it.
|
# reading it.
|
||||||
|
|
||||||
def warning(txt):
|
def warning(txt):
|
||||||
assert type(txt) == unicode
|
assert type(txt) == str
|
||||||
sys.stderr.write(txt + u'\n')
|
sys.stderr.write(txt + '\n')
|
||||||
|
|
||||||
def isdigit(c):
|
def isdigit(c):
|
||||||
return '0' <= c <= '9'
|
return '0' <= c <= '9'
|
||||||
|
@ -1818,7 +1818,7 @@ class parser(object):
|
||||||
if not line: break
|
if not line: break
|
||||||
match = parse_lin_re.match(line)
|
match = parse_lin_re.match(line)
|
||||||
if not match:
|
if not match:
|
||||||
warning(u'Syntax error in builtins.txt: ' + line.decode('utf8'))
|
warning('Syntax error in builtins.txt: ' + line)
|
||||||
continue
|
continue
|
||||||
if match.group(1):
|
if match.group(1):
|
||||||
# event or function
|
# event or function
|
||||||
|
@ -1836,20 +1836,20 @@ class parser(object):
|
||||||
name = match.group(2)
|
name = match.group(2)
|
||||||
if typ == 'event':
|
if typ == 'event':
|
||||||
if name in self.events:
|
if name in self.events:
|
||||||
warning(u'Event already defined in bultins.txt, overwriting: ' + name.decode('utf8'))
|
warning('Event already defined in bultins.txt, overwriting: ' + name)
|
||||||
self.events[name] = tuple(args)
|
self.events[name] = tuple(args)
|
||||||
else:
|
else:
|
||||||
# Library functions go to the functions table. If
|
# Library functions go to the functions table. If
|
||||||
# they are implemented in lslfuncs.*, they get a
|
# they are implemented in lslfuncs.*, they get a
|
||||||
# reference to the implementation; otherwise None.
|
# reference to the implementation; otherwise None.
|
||||||
if name in self.functions:
|
if name in self.functions:
|
||||||
warning(u'Function already defined in bultins.txt, overwriting: ' + name.decode('utf8'))
|
warning('Function already defined in bultins.txt, overwriting: ' + name)
|
||||||
self.functions[name] = (typ, tuple(args), getattr(lslfuncs, name, None))
|
self.functions[name] = (typ, tuple(args), getattr(lslfuncs, name, None))
|
||||||
elif match.group(4):
|
elif match.group(4):
|
||||||
# constant
|
# constant
|
||||||
name = match.group(5)
|
name = match.group(5)
|
||||||
if name in self.constants:
|
if name in self.constants:
|
||||||
warning(u'Global already defined in bultins.txt, overwriting: ' + name.decode('utf8'))
|
warning('Global already defined in bultins.txt, overwriting: ' + name)
|
||||||
try:
|
try:
|
||||||
typ = match.group(4)
|
typ = match.group(4)
|
||||||
if typ == 'quaternion':
|
if typ == 'quaternion':
|
||||||
|
@ -1881,7 +1881,7 @@ class parser(object):
|
||||||
#if typ == 'key':
|
#if typ == 'key':
|
||||||
# val = Key(val)
|
# val = Key(val)
|
||||||
elif typ == 'key':
|
elif typ == 'key':
|
||||||
warning(u'Key constants not supported in builtins.txt: ' + line.decode('utf8'))
|
warning('Key constants not supported in builtins.txt: ' + line)
|
||||||
val = None
|
val = None
|
||||||
elif typ in ('vector', 'rotation'):
|
elif typ in ('vector', 'rotation'):
|
||||||
if val[0:1] != '<' or val[-1:] != '>':
|
if val[0:1] != '<' or val[-1:] != '>':
|
||||||
|
@ -1911,14 +1911,14 @@ class parser(object):
|
||||||
val = Vector(val)
|
val = Vector(val)
|
||||||
else:
|
else:
|
||||||
assert typ == 'list'
|
assert typ == 'list'
|
||||||
warning(u'List constants not supported in builtins.txt: ' + line.decode('utf8'))
|
warning('List constants not supported in builtins.txt: ' + line)
|
||||||
val = None
|
val = None
|
||||||
if val is not None:
|
if val is not None:
|
||||||
self.constants[name] = val
|
self.constants[name] = val
|
||||||
|
|
||||||
except EInternal:
|
except EInternal:
|
||||||
warning(u'Invalid string in builtins.txt: ' + line.decode('utf8'))
|
warning('Invalid string in builtins.txt: ' + line)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warning(u'Invalid vector syntax in builtins.txt: ' + line.decode('utf8'))
|
warning('Invalid vector syntax in builtins.txt: ' + line)
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue