mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Optimize llDumpList2String for some non-constant cases
In particular, variables and fields. When we implement an analysis of functions contained in subexpressions, we can optimize more expressions, so add that as a TODO.
This commit is contained in:
parent
59df033fe0
commit
64c9c1db8b
1 changed files with 74 additions and 0 deletions
|
@ -113,6 +113,20 @@ defaultListVals = {'llList2Integer':0, 'llList2Float':0.0,
|
||||||
'llList2Vector':Vector((0.,0.,0.)),
|
'llList2Vector':Vector((0.,0.,0.)),
|
||||||
'llList2Rot':Quaternion((0.,0.,0.,1.))}
|
'llList2Rot':Quaternion((0.,0.,0.,1.))}
|
||||||
|
|
||||||
|
# Auxiliary function for llDumpList2String optimization
|
||||||
|
def CastDL2S(self, node, index):
|
||||||
|
"""Cast a list element to string, wrapping it in a list if it's a vector or
|
||||||
|
rotation.
|
||||||
|
"""
|
||||||
|
elem = self.GetListNodeElement(node, index)
|
||||||
|
assert elem is not False
|
||||||
|
if type(elem) != nr:
|
||||||
|
elem = nr(nt='CONST', t=lslcommon.PythonType2LSL[type(elem)], SEF=True,
|
||||||
|
value=elem)
|
||||||
|
if elem.t in ('vector', 'rotation'):
|
||||||
|
return self.Cast(self.Cast(elem, 'list'), 'string')
|
||||||
|
return self.Cast(elem, 'string')
|
||||||
|
|
||||||
# The 'self' parameter here is the constant folding object.
|
# The 'self' parameter here is the constant folding object.
|
||||||
def OptimizeFunc(self, parent, index):
|
def OptimizeFunc(self, parent, index):
|
||||||
"""Look for possible optimizations taking advantage of the specific LSL
|
"""Look for possible optimizations taking advantage of the specific LSL
|
||||||
|
@ -127,7 +141,9 @@ def OptimizeFunc(self, parent, index):
|
||||||
node = nr(nt='CONST', t='list', value=[], SEF=True)
|
node = nr(nt='CONST', t='list', value=[], SEF=True)
|
||||||
parent[index] = node = nr(nt='!=', t='integer',
|
parent[index] = node = nr(nt='!=', t='integer',
|
||||||
ch=[child[0], node], SEF=child[0].SEF)
|
ch=[child[0], node], SEF=child[0].SEF)
|
||||||
|
|
||||||
if name == 'llDumpList2String':
|
if name == 'llDumpList2String':
|
||||||
|
assert child[0].t == 'list'
|
||||||
if (child[1].nt == 'CONST'
|
if (child[1].nt == 'CONST'
|
||||||
and child[1].t in ('string', 'key')
|
and child[1].t in ('string', 'key')
|
||||||
and child[1].value == u""
|
and child[1].value == u""
|
||||||
|
@ -138,6 +154,64 @@ def OptimizeFunc(self, parent, index):
|
||||||
del node.name
|
del node.name
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if node.SEF:
|
||||||
|
# Attempt to convert the function call into a sum of strings when
|
||||||
|
# possible and productive.
|
||||||
|
|
||||||
|
list_len = self.GetListNodeLength(child[0])
|
||||||
|
if list_len is False:
|
||||||
|
# Can't identify the length, which means we can't optimize.
|
||||||
|
return
|
||||||
|
|
||||||
|
if list_len == 0:
|
||||||
|
# Empty list -> empty string, no matter the separator
|
||||||
|
# (remember we're SEF).
|
||||||
|
parent[index] = nr(nt='CONST', t='string', value=u'', SEF=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Only optimize if the second param is a very simple expression,
|
||||||
|
# otherwise the sums can get large.
|
||||||
|
if child[1].nt in ('CONST', 'IDENT'):
|
||||||
|
threshold = 10
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Apply a threshold for optimizing as a sum.
|
||||||
|
if list_len > threshold:
|
||||||
|
return
|
||||||
|
|
||||||
|
for i in range(list_len):
|
||||||
|
# TODO: If there's a function call, don't optimize.
|
||||||
|
# Since we don't yet have a flag, for now, optimize variables
|
||||||
|
# and constants only (kinda like simple_expression_no_list).
|
||||||
|
# Also, if an element is a list, we can't optimize it, as that
|
||||||
|
# will produce a side effect (error). Neither can we if the
|
||||||
|
# single elements can't be extracted.
|
||||||
|
val = self.GetListNodeElement(child[0], i)
|
||||||
|
if (val is False or type(val) == nr and (val.t == 'list'
|
||||||
|
or val.nt not in ('CONST', 'IDENT', 'FLD'))
|
||||||
|
):
|
||||||
|
# With our simple analysis, we can't guarantee that
|
||||||
|
# whatever the content is, there are no functions.
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Optimize to a sum of strings, right-to-left
|
||||||
|
i = list_len - 1
|
||||||
|
newnode = CastDL2S(self,child[0], i)
|
||||||
|
while i > 0:
|
||||||
|
i -= 1
|
||||||
|
newnode = nr(nt='+', t='string', SEF=True,
|
||||||
|
ch=[CastDL2S(self, child[0], i),
|
||||||
|
nr(nt='+', t='string', SEF=True,
|
||||||
|
ch=[child[1], newnode]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
parent[index] = newnode
|
||||||
|
# Re-fold
|
||||||
|
self.FoldTree(parent, index)
|
||||||
|
return
|
||||||
|
|
||||||
if (name in ('llList2String', 'llList2Key', 'llList2Integer',
|
if (name in ('llList2String', 'llList2Key', 'llList2Integer',
|
||||||
'llList2Float', 'llList2Vector', 'llList2Rot')
|
'llList2Float', 'llList2Vector', 'llList2Rot')
|
||||||
and child[1].nt == 'CONST'
|
and child[1].nt == 'CONST'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue