mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 07:38:21 +00:00
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:
parent
de29a9aa07
commit
a6a08fe3f3
3 changed files with 110 additions and 3 deletions
102
lslopt/lsllastpass.py
Normal file
102
lslopt/lsllastpass.py
Normal 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
|
|
@ -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()
|
||||||
|
|
||||||
|
|
5
main.py
5
main.py
|
@ -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"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue