mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2024-11-21 06:15:56 -07:00
106 lines
3.7 KiB
Python
106 lines
3.7 KiB
Python
# (C) Copyright 2015-2024 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/>.
|
|
|
|
# Optimizer class that wraps and calls the other parts.
|
|
|
|
from lslopt import lslfuncs
|
|
|
|
from lslopt.lslcommon import nr
|
|
from lslopt.lslfoldconst import foldconst
|
|
from lslopt.lslrenamer import renamer
|
|
from lslopt.lsldeadcode import deadcode
|
|
from lslopt.lsllastpass import lastpass
|
|
|
|
class optimizer(foldconst, renamer, deadcode, lastpass):
|
|
|
|
# Default values per type when declaring variables
|
|
DefaultValues = {'integer': 0, 'float': 0.0, 'string': u'',
|
|
'key': lslfuncs.Key(u''), 'vector': lslfuncs.ZERO_VECTOR,
|
|
'rotation': lslfuncs.ZERO_ROTATION, 'list': []
|
|
}
|
|
|
|
# explicitly exclude assignments
|
|
binary_ops = frozenset({'+','-','*','/','%','<<','>>','<','<=','>','>=',
|
|
'==','!=','|','^','&','||','&&'})
|
|
assign_ops = frozenset({'=','+=','-=','*=','/=','%=','&=','|=','^=','<<=','>>='})
|
|
|
|
def Cast(self, value, newtype):
|
|
"""Return a CAST node if the types are not equal, otherwise the
|
|
value unchanged.
|
|
"""
|
|
if value.t == newtype:
|
|
return value
|
|
ret = nr(nt='CAST', t=newtype, ch=[value], SEF=value.SEF)
|
|
if value.SEF:
|
|
ret.SEF = True
|
|
if hasattr(value, 'X'):
|
|
ret.X = value.X
|
|
return ret
|
|
|
|
def optimize(self, treesymtab, options = ('optimize','constfold','dcr',
|
|
'warntabs')):
|
|
"""Optimize the symbolic table symtab in place. Requires a table of
|
|
predefined functions for folding constants.
|
|
"""
|
|
if 'optimize' not in options:
|
|
return treesymtab
|
|
|
|
# Don't perform "a"+"b" -> "ab" unless explicitly requested.
|
|
self.addstrings = 'addstrings' in options
|
|
|
|
self.foldtabs = 'foldtabs' in options
|
|
self.warntabs = 'warntabs' in options
|
|
|
|
self.shrinknames = 'shrinknames' in options
|
|
|
|
self.constfold = 'constfold' in options
|
|
self.ifelseswap = 'ifelseswap' in options
|
|
self.optlistlength = 'listlength' in options
|
|
self.optlistadd = 'listadd' in options
|
|
self.dcr = 'dcr' in options
|
|
|
|
# Math that works fine except in rare corner-cases can be optimized.
|
|
self.cornermath = 'cornermath' in options
|
|
|
|
tree, symtab = self.tree, self.symtab = treesymtab
|
|
|
|
self.globalmode = False
|
|
|
|
if self.dcr:
|
|
if self.constfold:
|
|
self.FoldScript(warningpass=False)
|
|
|
|
self.RemoveDeadCode()
|
|
|
|
# Make another fold pass, since RemoveDeadCode can embed expressions
|
|
# into other expressions and generate unoptimized code.
|
|
# Or make the first pass here if DCR is disabled.
|
|
if self.constfold:
|
|
self.FoldScript(warningpass=True)
|
|
|
|
names = self.LastPass()
|
|
|
|
if self.shrinknames:
|
|
self.ShrinkNames(UsableAsParams = names['libfuncs'])
|
|
|
|
treesymtab = (self.tree, self.symtab)
|
|
del self.tree
|
|
del self.symtab
|
|
return treesymtab
|
|
|
|
def __init__(self, lib):
|
|
self.events = lib[0]
|