mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 07:38:21 +00:00
New constants and functions; some refactoring of lslfuncopt
TODO: unit tests
This commit is contained in:
parent
be479771aa
commit
c29475d072
4 changed files with 310 additions and 176 deletions
21
builtins.txt
21
builtins.txt
|
@ -1,4 +1,4 @@
|
|||
// Generated by LSL2 Derived Files Generator. Database version: 0.0.20220306000; output module version: 0.0.20140731000
|
||||
// Generated by LSL2 Derived Files Generator. Database version: 0.0.20220513000; output module version: 0.0.20140731000
|
||||
integer llAbs( integer val )
|
||||
float llAcos( float val )
|
||||
void llAddToLandBanList( key avatar, float hours )
|
||||
|
@ -204,6 +204,7 @@ integer llGetUnixTime( )
|
|||
integer llGetUsedMemory( )
|
||||
string llGetUsername( key id )
|
||||
vector llGetVel( )
|
||||
list llGetVisualParams( key id, list params )
|
||||
float llGetWallclock( )
|
||||
void llGiveInventory( key destination, string inventory )
|
||||
void llGiveInventoryList( key target, string folder, list inventory )
|
||||
|
@ -762,6 +763,9 @@ const integer OBJECT_GROUP = 7
|
|||
const integer OBJECT_GROUP_TAG = 33
|
||||
const integer OBJECT_HOVER_HEIGHT = 25
|
||||
const integer OBJECT_LAST_OWNER_ID = 27
|
||||
const integer OBJECT_LINK_NUMBER = 46
|
||||
const integer OBJECT_MASS = 43
|
||||
const integer OBJECT_MATERIAL = 42
|
||||
const integer OBJECT_NAME = 1
|
||||
const integer OBJECT_OMEGA = 29
|
||||
const integer OBJECT_OWNER = 6
|
||||
|
@ -777,9 +781,11 @@ const integer OBJECT_RETURN_PARCEL = 0x1
|
|||
const integer OBJECT_RETURN_PARCEL_OWNER = 0x2
|
||||
const integer OBJECT_RETURN_REGION = 0x4
|
||||
const integer OBJECT_REZZER_KEY = 32
|
||||
const integer OBJECT_REZ_TIME = 45
|
||||
const integer OBJECT_ROOT = 18
|
||||
const integer OBJECT_ROT = 4
|
||||
const integer OBJECT_RUNNING_SCRIPT_COUNT = 9
|
||||
const integer OBJECT_SCALE = 47
|
||||
const integer OBJECT_SCRIPT_MEMORY = 11
|
||||
const integer OBJECT_SCRIPT_TIME = 12
|
||||
const integer OBJECT_SELECT_COUNT = 37
|
||||
|
@ -788,6 +794,9 @@ const integer OBJECT_SIT_COUNT = 38
|
|||
const integer OBJECT_STREAMING_COST = 15
|
||||
const integer OBJECT_TEMP_ATTACHED = 34
|
||||
const integer OBJECT_TEMP_ON_REZ = 23
|
||||
const integer OBJECT_TEXT = 44
|
||||
const integer OBJECT_TEXT_ALPHA = 49
|
||||
const integer OBJECT_TEXT_COLOR = 48
|
||||
const integer OBJECT_TOTAL_INVENTORY_COUNT = 31
|
||||
const integer OBJECT_TOTAL_SCRIPT_COUNT = 10
|
||||
const integer OBJECT_UNKNOWN_DETAIL = -1
|
||||
|
@ -808,11 +817,18 @@ const integer PARCEL_COUNT_TEMP = 5
|
|||
const integer PARCEL_COUNT_TOTAL = 0
|
||||
const integer PARCEL_DETAILS_AREA = 4
|
||||
const integer PARCEL_DETAILS_DESC = 1
|
||||
const integer PARCEL_DETAILS_FLAGS = 12
|
||||
const integer PARCEL_DETAILS_GROUP = 3
|
||||
const integer PARCEL_DETAILS_ID = 5
|
||||
const integer PARCEL_DETAILS_LANDING_LOOKAT = 10
|
||||
const integer PARCEL_DETAILS_LANDING_POINT = 9
|
||||
const integer PARCEL_DETAILS_NAME = 0
|
||||
const integer PARCEL_DETAILS_OWNER = 2
|
||||
const integer PARCEL_DETAILS_PRIM_CAPACITY = 7
|
||||
const integer PARCEL_DETAILS_PRIM_USED = 8
|
||||
const integer PARCEL_DETAILS_SCRIPT_DANGER = 13
|
||||
const integer PARCEL_DETAILS_SEE_AVATARS = 6
|
||||
const integer PARCEL_DETAILS_TP_ROUTING = 11
|
||||
const integer PARCEL_FLAG_ALLOW_ALL_OBJECT_ENTRY = 0x08000000
|
||||
const integer PARCEL_FLAG_ALLOW_CREATE_GROUP_OBJECTS = 0x04000000
|
||||
const integer PARCEL_FLAG_ALLOW_CREATE_OBJECTS = 0x00000040
|
||||
|
@ -1162,6 +1178,9 @@ const string TEXTURE_TRANSPARENT = "8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"
|
|||
const integer TOUCH_INVALID_FACE = -1
|
||||
const vector TOUCH_INVALID_TEXCOORD = <-1.0, -1.0, 0.0>
|
||||
const vector TOUCH_INVALID_VECTOR = <0.0, 0.0, 0.0>
|
||||
const integer TP_ROUTING_BLOCKED = 0
|
||||
const integer TP_ROUTING_FREE = 2
|
||||
const integer TP_ROUTING_LANDINGP = 1
|
||||
const integer TRAVERSAL_TYPE = 7
|
||||
const integer TRAVERSAL_TYPE_FAST = 1
|
||||
const integer TRAVERSAL_TYPE_NONE = 2
|
||||
|
|
|
@ -863,6 +863,9 @@ vector llGetVel()
|
|||
#- unstable
|
||||
- SEF
|
||||
|
||||
list llGetVisualParams(key id, list params)
|
||||
- SEF
|
||||
|
||||
float llGetWallclock()
|
||||
- SEF
|
||||
- min 0
|
||||
|
|
|
@ -21,17 +21,35 @@ from lslopt.lslcommon import Key, Vector #, Quaternion
|
|||
from lslopt.lslbasefuncs import ELSLCantCompute, fi,ff,fs,fk,v2f,q2f,fl, \
|
||||
NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, \
|
||||
TOUCH_INVALID_TEXCOORD, cond
|
||||
#from strutil import unicode
|
||||
ff, q2f # keep pyflakes happy as these are not used
|
||||
|
||||
GetEnvSettings = frozenset({'agent_limit', 'dynamic_pathfinding', 'estate_id'
|
||||
, 'estate_name', 'frame_number', 'region_cpu_ratio', 'region_idle'
|
||||
, 'region_product_name', 'region_product_sku', 'region_start_time'
|
||||
, 'sim_channel', 'sim_version', 'simulator_hostname'
|
||||
, 'region_max_prims' # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.11.02.321369>
|
||||
, 'region_object_bonus' # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.12.03.322072>
|
||||
, 'whisper_range', 'chat_range', 'shout_range'
|
||||
, 'region_max_prims' # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.11.02.321369>
|
||||
, 'region_object_bonus' # <http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_Magnum/16#16.12.03.322072>
|
||||
, 'whisper_range', 'chat_range', 'shout_range' #? (jun 2020)
|
||||
, 'agent_limit_max', 'agent_reserved', 'agent_underserved' # <https://releasenotes.secondlife.com/simulator/2022-04-21.571166.html>
|
||||
})
|
||||
|
||||
# Values valid for llGetVisualDetails parameters
|
||||
GVD_ValidValues = \
|
||||
{ 33, "height"
|
||||
, 38, "torso_length"
|
||||
, 80, "male"
|
||||
, 198, "heel_height"
|
||||
, 503, "platform_height"
|
||||
, 616, "shoe_height"
|
||||
, 692, "leg_length"
|
||||
, 693, "arm_length"
|
||||
, 756, "neck_length"
|
||||
, 814, "waist_height"
|
||||
, 842, "hip_length"
|
||||
, 11001, "hover"
|
||||
}
|
||||
|
||||
xp_error_messages = {
|
||||
-1:u'unknown error id',
|
||||
0:u'no error', 1:u'exceeded throttle', 2:u'experiences are disabled',
|
||||
|
@ -319,4 +337,18 @@ def llGetStatus(mask):
|
|||
return 0
|
||||
raise ELSLCantCompute
|
||||
|
||||
def llGetVisualParams(id, params):
|
||||
id = fk(id)
|
||||
params = fl(params)
|
||||
if not cond(id) or params.nt == 'CONST' and not params.ch:
|
||||
return []
|
||||
# TODO: This needs to check whether the list is a literal, and whether the
|
||||
# elements are constant.
|
||||
# if params.nt == 'LIST':
|
||||
# for i in params:
|
||||
# if (i.lower() if type(i) == unicode else i) in GVD_ValidValues:
|
||||
# raise ELSLCantCompute
|
||||
# return [u""] * len(params)
|
||||
raise ELSLCantCompute
|
||||
|
||||
# TODO: Add more predictable functions.
|
||||
|
|
|
@ -56,50 +56,64 @@ def OptimizeArgs(node, sym):
|
|||
params[i].type = 'string'
|
||||
|
||||
|
||||
# Type of each entry in llGetObjectDetails.
|
||||
# Last: 41 (OBJECT_ACCOUNT_LEVEL).
|
||||
objDetailsTypes = 'issvrvkkkiiififfffkiiiiiiffkiviiksiisiiiii'
|
||||
# llGetObjectDetails return types
|
||||
# Last: 49 (OBJECT_TEXT_ALPHA).
|
||||
objDetailsTypes = 'issvrvkkkiiififfffkiiiiiiffkiviiksiisiiiiiifssivvf'
|
||||
|
||||
# llGetParcelDetails return types
|
||||
# Last: 13 (PARCEL_DETAILS_SCRIPT_DANGER)
|
||||
parcelDetailsTypes = 'sskkikiiivviii'
|
||||
parcelMediaQTypes = \
|
||||
{ 4: 'k' # PARCEL_MEDIA_COMMAND_TEXTURE
|
||||
, 5: 's' # PARCEL_MEDIA_COMMAND_URL
|
||||
, 10: 's' # PARCEL_MEDIA_COMMAND_TYPE
|
||||
, 11: 'ii' # PARCEL_MEDIA_COMMAND_SIZE
|
||||
, 12: 's' # PARCEL_MEDIA_COMMAND_DESC
|
||||
, 13: 'f' # PARCEL_MEDIA_COMMAND_LOOP
|
||||
}
|
||||
|
||||
# llGetPrimitiveParams and llGetLinkPrimitiveParams return types
|
||||
primParamsTypes = \
|
||||
( False # 0 (unassigned)
|
||||
, 'i*' # 1=PRIM_TYPE_LEGACY
|
||||
, 'i' # 2=PRIM_MATERIAL
|
||||
, 'i' # 3=PRIM_PHYSICS
|
||||
, 'i' # 4=PRIM_TEMP_ON_REZ
|
||||
, 'i' # 5=PRIM_PHANTOM
|
||||
, 'v' # 6=PRIM_POSITION
|
||||
, 'v' # 7=PRIM_SIZE
|
||||
, 'r' # 8=PRIM_ROTATION
|
||||
, 'i*' # 9=PRIM_TYPE
|
||||
, False, False, False, False # 10, 11, 12, 13 (unassigned)
|
||||
, False, False, False # 14, 15, 16 (unassigned)
|
||||
, 'svvf' # 17=PRIM_TEXTURE
|
||||
, 'vf' # 18=PRIM_COLOR
|
||||
, 'ii' # 19=PRIM_BUMP_SHINY
|
||||
, 'i' # 20=PRIM_FULLBRIGHT
|
||||
, 'iiffffv' # 21=PRIM_FLEXIBLE
|
||||
, 'i' # 22=PRIM_TEXGEN
|
||||
, 'ivfff' # 23=PRIM_POINT_LIGHT
|
||||
, False # 24 (unassigned)
|
||||
, 'f' # 25=PRIM_GLOW
|
||||
, 'svf' # 26=PRIM_TEXT
|
||||
, 's' # 27=PRIM_NAME
|
||||
, 's' # 28=PRIM_DESC
|
||||
, 'r' # 29=PRIM_ROT_LOCAL
|
||||
, 'i' # 30=PRIM_PHYSICS_SHAPE_TYPE
|
||||
, False # 31 (unassigned)
|
||||
, 'vff' # 32=PRIM_OMEGA
|
||||
, 'v' # 33=PRIM_POS_LOCAL
|
||||
, '' # 34=PRIM_LINK_TARGET
|
||||
, 'v' # 35=PRIM_SLICE
|
||||
, 'svvfvii' # 36=PRIM_SPECULAR
|
||||
, 'svvf' # 37=PRIM_NORMAL
|
||||
, 'ii' # 38=PRIM_ALPHA_MODE
|
||||
, 'i' # 39=PRIM_ALLOW_UNSIT
|
||||
, 'i' # 40=PRIM_SCRIPTED_SIT_ONLY
|
||||
, 'ivv' # 41=PRIM_SIT_TARGET
|
||||
, 'sfff' # 42=PRIM_PROJECTOR
|
||||
)
|
||||
# GetPrimitiveParams parameters with arguments. F=face, L=link.
|
||||
{ # 0 (unassigned)
|
||||
1: 'i*' # 1=PRIM_TYPE_LEGACY
|
||||
, 2: 'i' # 2=PRIM_MATERIAL
|
||||
, 3: 'i' # 3=PRIM_PHYSICS
|
||||
, 4: 'i' # 4=PRIM_TEMP_ON_REZ
|
||||
, 5: 'i' # 5=PRIM_PHANTOM
|
||||
, 6: 'v' # 6=PRIM_POSITION
|
||||
, 7: 'v' # 7=PRIM_SIZE
|
||||
, 8: 'r' # 8=PRIM_ROTATION
|
||||
, 9: 'i*' # 9=PRIM_TYPE
|
||||
# 10 to 16: unassigned
|
||||
, 17: 'svvf' # 17=PRIM_TEXTURE
|
||||
, 18: 'vf' # 18=PRIM_COLOR
|
||||
, 19: 'ii' # 19=PRIM_BUMP_SHINY
|
||||
, 20: 'i' # 20=PRIM_FULLBRIGHT
|
||||
, 21: 'iiffffv' # 21=PRIM_FLEXIBLE
|
||||
, 22: 'i' # 22=PRIM_TEXGEN
|
||||
, 23: 'ivfff' # 23=PRIM_POINT_LIGHT
|
||||
# 24 :unassigned
|
||||
, 25: 'f' # 25=PRIM_GLOW
|
||||
, 26: 'svf' # 26=PRIM_TEXT
|
||||
, 27: 's' # 27=PRIM_NAME
|
||||
, 28: 's' # 28=PRIM_DESC
|
||||
, 29: 'r' # 29=PRIM_ROT_LOCAL
|
||||
, 30: 'i' # 30=PRIM_PHYSICS_SHAPE_TYPE
|
||||
# 31: unassigned
|
||||
, 32: 'vff' # 32=PRIM_OMEGA
|
||||
, 33: 'v' # 33=PRIM_POS_LOCAL
|
||||
, 34: '' # 34=PRIM_LINK_TARGET
|
||||
, 35: 'v' # 35=PRIM_SLICE
|
||||
, 36: 'svvfvii' # 36=PRIM_SPECULAR
|
||||
, 37: 'svvf' # 37=PRIM_NORMAL
|
||||
, 38: 'ii' # 38=PRIM_ALPHA_MODE
|
||||
, 39: 'i' # 39=PRIM_ALLOW_UNSIT
|
||||
, 40: 'i' # 40=PRIM_SCRIPTED_SIT_ONLY
|
||||
, 41: 'ivv' # 41=PRIM_SIT_TARGET
|
||||
, 42: 'sfff' # 42=PRIM_PROJECTOR
|
||||
}
|
||||
|
||||
# llGetPrimitiveParams parameters with arguments. F=face, L=link.
|
||||
primParamsArgs = \
|
||||
{ 17: 'F' # 17=PRIM_TEXTURE
|
||||
, 18: 'F' # 18=PRIM_COLOR
|
||||
|
@ -113,10 +127,56 @@ primParamsArgs = \
|
|||
, 38: 'F' # PRIM_ALPHA_MODE
|
||||
}
|
||||
|
||||
# Compatibility: list extraction function / input type (by type's first
|
||||
# letter), e.g. 'si' means llList2String can extract an integer.
|
||||
listCompat = frozenset({'ss', 'sk', 'si', 'sf', 'sv', 'sr', 'ks', 'kk',
|
||||
'is', 'ii', 'if', 'fs', 'fi', 'ff', 'vv', 'rr'})
|
||||
# llGetPrimMediaParams and llGetLinkMedia return types
|
||||
# Last: 14 (PRIM_MEDIA_PERMS_CONTROL)
|
||||
primMediaTypes = 'iissiiiiiiiisii'
|
||||
|
||||
# llGetEnvironment return types (not to be confused with llGetEnv)
|
||||
getEnvTypes = \
|
||||
{ 15: 'fff'
|
||||
, 0: 'v'
|
||||
, 1: 'iii'
|
||||
, 2: 'vfffvvvi'
|
||||
, 4: 'fff'
|
||||
, 5: 'f'
|
||||
, 6: 'ff'
|
||||
, 9: 'rffivvv'
|
||||
, 13: 'f'
|
||||
, 14: 'rfvivvv'
|
||||
, 10: 'fff'
|
||||
, 11: 'fff'
|
||||
, 8: 'vvv'
|
||||
, 100: 'f'
|
||||
, 101: 'vff'
|
||||
, 102: 'ff'
|
||||
, 103: 'ii'
|
||||
, 104: 'v'
|
||||
, 105: 'ff'
|
||||
, 106: 'vv'
|
||||
, 200: 'iif'
|
||||
}
|
||||
|
||||
# Types for llGetVisualDetails parameters (anything not in this list is
|
||||
# returned as an empty string)
|
||||
visualDetailsTypes = \
|
||||
{ 33: 'f', 'height': 'f'
|
||||
, 38: 'f', 'torso_length': 'f'
|
||||
, 80: 'f', 'male': 'f'
|
||||
, 198: 'f', 'heel_height': 'f'
|
||||
, 503: 'f', 'platform_height': 'f'
|
||||
, 616: 'f', 'shoe_height': 'f'
|
||||
, 692: 'f', 'leg_length': 'f'
|
||||
, 693: 'f', 'arm_length': 'f'
|
||||
, 756: 'f', 'neck_length': 'f'
|
||||
, 814: 'f', 'waist_height': 'f'
|
||||
, 842: 'f', 'hip_length': 'f'
|
||||
, 11001: 'f', 'hover': 'f'
|
||||
}
|
||||
|
||||
# Compatibility: list extraction function / input type (by type's initial),
|
||||
# e.g. 'si' means llList2String can extract an integer.
|
||||
listCompat = {'ss', 'sk', 'si', 'sf', 'sv', 'sr', 'ks', 'kk',
|
||||
'is', 'ii', 'if', 'fs', 'fi', 'ff', 'vv', 'rr'}
|
||||
|
||||
defaultListVals = {'llList2Integer':0, 'llList2Float':0.0,
|
||||
'llList2String':u'',
|
||||
|
@ -135,7 +195,7 @@ def CastDL2S(self, node, index):
|
|||
if type(elem) != nr:
|
||||
elem = nr(nt='CONST', t=lslcommon.PythonType2LSL[type(elem)], SEF=True,
|
||||
value=elem)
|
||||
if elem.t in ('vector', 'rotation'):
|
||||
if elem.t in {'vector', 'rotation'}:
|
||||
return self.Cast(self.Cast(elem, 'list'), 'string')
|
||||
return self.Cast(elem, 'string')
|
||||
|
||||
|
@ -143,7 +203,7 @@ def CastDL2S(self, node, index):
|
|||
def FnFree(self, node):
|
||||
if node.nt == 'FNCALL':
|
||||
return False
|
||||
if node.nt in ('CONST', 'IDENT', 'FLD'):
|
||||
if node.nt in {'CONST', 'IDENT', 'FLD'}:
|
||||
return True
|
||||
return all(FnFree(self, node.ch[i]) for i in range(len(node.ch)))
|
||||
|
||||
|
@ -165,7 +225,7 @@ def OptimizeFunc(self, parent, index):
|
|||
if name == 'llDumpList2String':
|
||||
assert child[0].t == 'list'
|
||||
if (child[1].nt == 'CONST'
|
||||
and child[1].t in ('string', 'key')
|
||||
and child[1].t in {'string', 'key'}
|
||||
and child[1].value == u""
|
||||
):
|
||||
# Convert llDumpList2String(expr, "") to (string)(expr)
|
||||
|
@ -197,7 +257,7 @@ def OptimizeFunc(self, parent, index):
|
|||
|
||||
# Only optimize if the second param is a very simple expression,
|
||||
# otherwise the sums can get large.
|
||||
if child[1].nt in ('CONST', 'IDENT'):
|
||||
if child[1].nt in {'CONST', 'IDENT'}:
|
||||
threshold = 10
|
||||
else:
|
||||
return
|
||||
|
@ -253,8 +313,8 @@ def OptimizeFunc(self, parent, index):
|
|||
self.FoldTree(parent, index)
|
||||
return
|
||||
|
||||
if (name in ('llList2String', 'llList2Key', 'llList2Integer',
|
||||
'llList2Float', 'llList2Vector', 'llList2Rot')
|
||||
if (name in {'llList2String', 'llList2Key', 'llList2Integer',
|
||||
'llList2Float', 'llList2Vector', 'llList2Rot'}
|
||||
and child[1].nt == 'CONST'
|
||||
):
|
||||
# 2nd arg to llList2XXXX must be integer
|
||||
|
@ -278,131 +338,151 @@ def OptimizeFunc(self, parent, index):
|
|||
parent[index] = nr(nt='CONST', t=node.t, value=const, SEF=True)
|
||||
return
|
||||
|
||||
if listarg.nt == 'FNCALL' \
|
||||
and listarg.name == 'llGetObjectDetails':
|
||||
if listarg.nt == 'FNCALL':
|
||||
if listarg.name == 'llGetObjectDetails':
|
||||
|
||||
# make it the list argument of llGetObjectDetails
|
||||
listarg = listarg.ch[1]
|
||||
value = self.GetListNodeElement(listarg, idx)
|
||||
tvalue = self.TypeFromNodeOrConst(value)
|
||||
const = self.ConstFromNodeOrConst(value)
|
||||
if type(const) == int and self.GetListNodeLength(listarg) == 1:
|
||||
# Some of these can be handled with a typecast to string.
|
||||
if name == 'llList2String':
|
||||
# turn the node into a cast of arg 0 to string
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
return
|
||||
# The other ones that support cast to string then to
|
||||
# the final type in some cases (depending on the
|
||||
# list type, which we know) are key/int/float.
|
||||
finaltype = objDetailsTypes[const:const+1]
|
||||
if (name == 'llList2Key' # checked via listCompat
|
||||
or (name == 'llList2Integer'
|
||||
and finaltype in ('s', 'i')) # won't work for floats
|
||||
or (name == 'llList2Float'
|
||||
and finaltype in ('s', 'i')) # won't work for floats
|
||||
) and (node.t[0] + finaltype) in listCompat:
|
||||
# -> (key)((string)llGetObjectDetails...)
|
||||
# or (integer)((string)llGetObjectDetails...)
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
child[0] = self.Cast(child[0], 'string')
|
||||
return
|
||||
# make it the list argument of llGetObjectDetails
|
||||
listarg = listarg.ch[1]
|
||||
value = self.GetListNodeElement(listarg, idx)
|
||||
tvalue = self.TypeFromNodeOrConst(value)
|
||||
const = self.ConstFromNodeOrConst(value)
|
||||
if type(const) == int and self.GetListNodeLength(listarg) == 1:
|
||||
# Some of these can be handled with a typecast to string.
|
||||
if name == 'llList2String':
|
||||
# turn the node into a cast of arg 0 to string
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
return
|
||||
# The other ones that support cast to string then to
|
||||
# the final type in some cases (depending on the
|
||||
# list type, which we know) are key/int/float.
|
||||
finaltype = objDetailsTypes[const:const+1]
|
||||
if (name == 'llList2Key' # checked via listCompat
|
||||
or (name == 'llList2Integer'
|
||||
and finaltype in {'s', 'i'}) # won't work for floats
|
||||
or (name == 'llList2Float'
|
||||
and finaltype in {'s', 'i'}) # won't work for floats
|
||||
) and (node.t[0] + finaltype) in listCompat:
|
||||
# -> (key)((string)llGetObjectDetails...)
|
||||
# or (integer)((string)llGetObjectDetails...)
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
child[0] = self.Cast(child[0], 'string')
|
||||
return
|
||||
|
||||
# Check for type incompatibility or index out of range
|
||||
# and replace node with a constant if that's the case
|
||||
if (value is False
|
||||
or type(const) == int
|
||||
and (node.t[0] + objDetailsTypes[const])
|
||||
not in listCompat
|
||||
) and node.SEF:
|
||||
parent[index] = nr(nt='CONST', t=node.t,
|
||||
value=defaultListVals[name], SEF=True)
|
||||
# Check for type incompatibility or index out of range
|
||||
# and replace node with a constant if that's the case
|
||||
if (value is False
|
||||
or type(const) == int
|
||||
and (node.t[0] + objDetailsTypes[const])
|
||||
not in listCompat
|
||||
) and node.SEF:
|
||||
parent[index] = nr(nt='CONST', t=node.t,
|
||||
value=defaultListVals[name], SEF=True)
|
||||
|
||||
elif listarg.nt == 'FNCALL' and listarg.name in (
|
||||
'llGetPrimitiveParams', 'llGetLinkPrimitiveParams'):
|
||||
# We're going to work with the primitive params list.
|
||||
listarg = listarg.ch[
|
||||
0 if listarg.name == 'llGetPrimitiveParams'
|
||||
else 1]
|
||||
length = self.GetListNodeLength(listarg)
|
||||
if length is not False:
|
||||
# Construct a list (string) of return types.
|
||||
# A '*' in the list means the type can't be
|
||||
# determined past this point (used with PRIM_TYPE).
|
||||
i = 0
|
||||
returntypes = ''
|
||||
while i < length:
|
||||
param = self.GetListNodeElement(listarg, i)
|
||||
param = self.ConstFromNodeOrConst(param)
|
||||
if (param is False
|
||||
or type(param) != int
|
||||
# Parameters with arguments have
|
||||
# side effects (errors).
|
||||
# We could check whether there's a face
|
||||
# argument and the face is 0, which is
|
||||
# guaranteed to exist, but it's not worth
|
||||
# the effort.
|
||||
or param in primParamsArgs
|
||||
or param < 0
|
||||
or param >= len(primParamsTypes)
|
||||
or primParamsTypes[param] is False
|
||||
):
|
||||
# Can't process this list.
|
||||
returntypes = '!'
|
||||
break
|
||||
returntypes += primParamsTypes[param]
|
||||
i += 1
|
||||
if returntypes != '!':
|
||||
if (len(returntypes) == 1
|
||||
and returntypes != '*'
|
||||
and idx in (0, -1)
|
||||
):
|
||||
if name == 'llList2String':
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
return
|
||||
if ((name == 'llList2Key'
|
||||
or name == 'llList2Integer'
|
||||
and returntypes in ('s', 'i')
|
||||
or name == 'llList2Float'
|
||||
and returntypes in ('s', 'i')
|
||||
)
|
||||
and (node.t[0] + returntypes)
|
||||
in listCompat
|
||||
elif listarg.name in {'llGetPrimitiveParams',
|
||||
'llGetLinkPrimitiveParams'}:
|
||||
# We're going to work with the primitive params list.
|
||||
listarg = listarg.ch[
|
||||
0 if listarg.name == 'llGetPrimitiveParams'
|
||||
else 1]
|
||||
length = self.GetListNodeLength(listarg)
|
||||
if length is not False:
|
||||
# Construct a list (string) of return types.
|
||||
# A '*' in the list means the type can't be
|
||||
# determined past this point (used with PRIM_TYPE).
|
||||
i = 0
|
||||
returntypes = ''
|
||||
while i < length:
|
||||
param = self.GetListNodeElement(listarg, i)
|
||||
param = self.ConstFromNodeOrConst(param)
|
||||
if (param is False
|
||||
or type(param) != int
|
||||
# Parameters with arguments have
|
||||
# side effects (errors).
|
||||
# We could check whether there's a face
|
||||
# argument and the face is 0, which is
|
||||
# guaranteed to exist, but it's not worth
|
||||
# the effort.
|
||||
or param in primParamsArgs
|
||||
or param not in primParamsTypes
|
||||
):
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
child[0] = nr(nt='CAST', t='string',
|
||||
ch=[child[0]], SEF=child[0].SEF)
|
||||
return
|
||||
# Can't process this list.
|
||||
returntypes = '!'
|
||||
break
|
||||
returntypes += primParamsTypes[param]
|
||||
i += 1
|
||||
if returntypes != '!':
|
||||
if (len(returntypes) == 1
|
||||
and returntypes != '*'
|
||||
and idx in {0, -1}
|
||||
):
|
||||
if name == 'llList2String':
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
return
|
||||
if ((name == 'llList2Key'
|
||||
or name == 'llList2Integer'
|
||||
and returntypes in {'s', 'i'}
|
||||
or name == 'llList2Float'
|
||||
and returntypes in {'s', 'i'}
|
||||
)
|
||||
and (node.t[0] + returntypes)
|
||||
in listCompat
|
||||
):
|
||||
node.nt = 'CAST'
|
||||
del child[1]
|
||||
del node.name
|
||||
child[0] = nr(nt='CAST', t='string',
|
||||
ch=[child[0]], SEF=child[0].SEF)
|
||||
return
|
||||
|
||||
# The position of parameters past the first asterisk can't
|
||||
# be determined, so we only consider parameters before it.
|
||||
asteriskPos = returntypes.find('*')
|
||||
if (asteriskPos == -1
|
||||
or 0 <= idx < asteriskPos
|
||||
or asteriskPos - len(returntypes) < idx < 0
|
||||
):
|
||||
# Check for type incompatibility or index
|
||||
# out of range.
|
||||
if idx < 0:
|
||||
# s[-1:0] doesn't return the last char
|
||||
# so we make it positive to ensure correctness
|
||||
idx += len(returntypes)
|
||||
if ((node.t[0] + returntypes[idx:idx+1])
|
||||
not in listCompat
|
||||
and node.SEF):
|
||||
parent[index] = nr(nt='CONST', t=node.t,
|
||||
value=defaultListVals[name], SEF=True)
|
||||
return
|
||||
# The position of parameters past the first asterisk can't
|
||||
# be determined, so we only consider parameters before it.
|
||||
asteriskPos = returntypes.find('*')
|
||||
if (asteriskPos == -1
|
||||
or 0 <= idx < asteriskPos
|
||||
or asteriskPos - len(returntypes) < idx < 0
|
||||
):
|
||||
# Check for type incompatibility or index
|
||||
# out of range.
|
||||
if idx < 0:
|
||||
# s[-1:0] doesn't return the last char
|
||||
# so we make it positive to ensure correctness
|
||||
idx += len(returntypes)
|
||||
if ((node.t[0] + returntypes[idx:idx+1])
|
||||
not in listCompat
|
||||
and node.SEF):
|
||||
parent[index] = nr(nt='CONST', t=node.t,
|
||||
value=defaultListVals[name], SEF=True)
|
||||
return
|
||||
|
||||
del returntypes
|
||||
del returntypes
|
||||
|
||||
elif listarg.name == 'llGetParcelDetails':
|
||||
listarg = listarg.ch[1] # 0 is vector pos
|
||||
# TODO: llList2XXX(llGetParcelDetails)
|
||||
|
||||
elif listarg.name == 'llParcelMediaQuery':
|
||||
listarg = listarg.ch[0]
|
||||
# TODO: llList2XXX(llParcelMediaQuery)
|
||||
|
||||
elif listarg.name in {'llGetPrimMediaParams', 'llGetLinkMedia'}:
|
||||
listarg = listarg.ch[
|
||||
1 if listarg.name == 'llGetPrimMediaParams'
|
||||
else 2]
|
||||
# TODO: llList2XXX(llGetPrimMediaXXX)
|
||||
|
||||
elif listarg.name == 'llGetEnvironment':
|
||||
listarg = listarg.ch[1] # 0 is vector pos
|
||||
# TODO: llList2XXX(llGetEnvironment)
|
||||
|
||||
elif listarg.name == 'llGetVisualParams':
|
||||
listarg = listarg.ch[1] # 0 is id
|
||||
# TODO: llList2XXX(llGetVisualParams)
|
||||
|
||||
del listarg, idx, value, tvalue, const
|
||||
return
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue