New constants and functions; some refactoring of lslfuncopt

TODO: unit tests
This commit is contained in:
Sei Lisa 2022-05-13 14:41:36 +02:00
parent be479771aa
commit c29475d072
4 changed files with 310 additions and 176 deletions

View file

@ -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

View file

@ -863,6 +863,9 @@ vector llGetVel()
#- unstable
- SEF
list llGetVisualParams(key id, list params)
- SEF
float llGetWallclock()
- SEF
- min 0

View file

@ -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.

View file

@ -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