Implement transformation of lists into additions.

If the list in brackets is SEF:
  [a, b, ...]  ->  (list)a + b + ...
  ListExpr + [a, b, ...]  ->  ListExpr + a + b + ...
This commit is contained in:
Sei Lisa 2017-09-15 22:30:22 +02:00
parent de29a9aa07
commit a6a08fe3f3
3 changed files with 110 additions and 3 deletions

102
lslopt/lsllastpass.py Normal file
View file

@ -0,0 +1,102 @@
# (C) Copyright 2015-2017 Sei Lisa. All rights reserved.
#
# This file is part of LSL PyOptimizer.
#
# LSL PyOptimizer is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# LSL PyOptimizer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LSL PyOptimizer. If not, see <http://www.gnu.org/licenses/>.
# Optimizations that have a negative effect on other stages.
import lslcommon
#from lslcommon import Vector, Quaternion
#import lslfuncs
#from lslfuncs import ZERO_VECTOR, ZERO_ROTATION
#import math
#from lslparse import warning
#from lslfuncopt import OptimizeFunc, OptimizeArgs, FuncOptSetup
class lastpass(object):
def LastPassPreOrder(self, parent, index):
node = parent[index]
nt = node['nt']
child = node['ch'] if 'ch' in node else None
if (self.optlistadd and not self.globalmode
and (nt == 'CONST' and node['t'] == 'list' or nt == 'LIST'
or nt == '+' and child[0]['t'] == 'list' and
(child[1]['nt'] == 'CONST' and child[1]['t'] == 'list'
or child[1]['nt'] == 'LIST')
)
):
# Perform these transformations if the list is SEF:
# [a, b, ...] -> (list)a + b...
# ListExpr + [a, b, ..] -> ListExpr + a + b...
# (ListExpr doesn't need to be SEF for this to work)
# This transformation makes it difficult to handle lists during
# optimization, that's why it's done in a separate pass.
top = child[0] if nt == '+' else None
elemnode = child[1] if nt == '+' else node
if 'SEF' in elemnode:
elements = (elemnode['value'] if elemnode['nt'] == 'CONST'
else elemnode['ch'])
for v in elements:
elem = v if elemnode['nt'] != 'CONST' else {
'nt':'CONST',
't':lslcommon.PythonType2LSL[type(v)],
'SEF':True,
'value':v}
top = {'nt':'CAST', 't':'list', 'SEF':True,
'ch':[elem]
} if top is None else {
'nt':'+', 't':'list', 'SEF':True,
'ch':[top, elem]
}
del elem
if top is not None:
parent[index] = top
nt = top['nt']
# Do another pass on the result
self.RecursiveLastPass(parent, index)
del top
return
def LastPassPostOrder(self, parent, index):
pass
def RecursiveLastPass(self, parent, index):
self.LastPassPreOrder(parent, index)
if 'ch' in parent[index]:
child = parent[index]['ch']
idx = 0
while idx < len(child):
self.RecursiveLastPass(child, idx)
idx += 1
self.LastPassPostOrder(parent, index)
def LastPass(self):
self.globalmode = False
tree = self.tree
# Last optimizations pass
for idx in xrange(len(tree)):
if tree[idx]['nt'] == 'DECL':
self.globalmode = True
self.RecursiveLastPass(tree, idx)
self.globalmode = False
else:
self.RecursiveLastPass(tree, idx)
pass

View file

@ -22,8 +22,9 @@ import lslfuncs
from lslfoldconst import foldconst from lslfoldconst import foldconst
from lslrenamer import renamer from lslrenamer import renamer
from lsldeadcode import deadcode from lsldeadcode import deadcode
from lsllastpass import lastpass
class optimizer(foldconst, renamer, deadcode): class optimizer(foldconst, renamer, deadcode, lastpass):
# Default values per type when declaring variables # Default values per type when declaring variables
DefaultValues = {'integer': 0, 'float': 0.0, 'string': u'', DefaultValues = {'integer': 0, 'float': 0.0, 'string': u'',
@ -67,6 +68,7 @@ class optimizer(foldconst, renamer, deadcode):
self.constfold = 'constfold' in options self.constfold = 'constfold' in options
self.optlistlength = 'listlength' in options self.optlistlength = 'listlength' in options
self.optlistadd = 'listadd' in options
self.dcr = 'dcr' in options self.dcr = 'dcr' in options
# Math that works fine except in rare corner-cases can be optimized. # Math that works fine except in rare corner-cases can be optimized.
@ -88,6 +90,8 @@ class optimizer(foldconst, renamer, deadcode):
if self.constfold: if self.constfold:
self.FoldScript(warningpass=True) self.FoldScript(warningpass=True)
self.LastPass()
if self.shrinknames: if self.shrinknames:
self.ShrinkNames() self.ShrinkNames()

View file

@ -290,6 +290,7 @@ Case insensitive.
take memory. take memory.
ListLength + Optimize llGetListLength(arg) to arg!=[]. Needs constant ListLength + Optimize llGetListLength(arg) to arg!=[]. Needs constant
folding active to work. folding active to work.
ListAdd + Convert [a,b,c...] to (list)a + b + c... if possible.
Miscellaneous options Miscellaneous options
@ -326,7 +327,7 @@ validoptions = frozenset(('extendedglobalexpr','breakcont','extendedtypecast',
'extendedassignment','allowkeyconcat','allowmultistrings','duplabels', 'extendedassignment','allowkeyconcat','allowmultistrings','duplabels',
'lazylists','enableswitch','errmissingdefault','funcoverride','optimize', 'lazylists','enableswitch','errmissingdefault','funcoverride','optimize',
'optsigns','optfloats','constfold','dcr','shrinknames','addstrings', 'optsigns','optfloats','constfold','dcr','shrinknames','addstrings',
'foldtabs','warntabs','processpre','explicitcast','listlength', 'foldtabs','warntabs','processpre','explicitcast','listlength','listadd',
'help', 'help',
# undocumented # undocumented
'lso','expr','rsrclimit', 'lso','expr','rsrclimit',
@ -344,7 +345,7 @@ def main(argv):
options = set(('extendedglobalexpr','extendedtypecast','extendedassignment', options = set(('extendedglobalexpr','extendedtypecast','extendedassignment',
'allowkeyconcat','allowmultistrings','processpre','warntabs','optimize', 'allowkeyconcat','allowmultistrings','processpre','warntabs','optimize',
'optsigns','optfloats','constfold','dcr','errmissingdefault', 'optsigns','optfloats','constfold','dcr','errmissingdefault',
'listlength', 'listlength','listadd',
)) ))
assert not (options - validoptions), (u"Default options not present in" assert not (options - validoptions), (u"Default options not present in"