mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 07:38:21 +00:00
Add 'listto' to fndata.txt; remove more magic names from the code
Rather than using a hardcoded table of list-to-type extraction function, add a 'ListTo' attribute to the function data. No error is raised if more than one function exists to convert to the same type. This change is of questionable usefulness, but it should soothe those allergic to magic names/numbers. I cringed a bit myself. While on it, change the syntax error that was raised when the corresponding conversion function did not exist, to a tailor-made error.
This commit is contained in:
parent
a052bf499c
commit
0855b8ad1d
3 changed files with 70 additions and 45 deletions
11
fndata.txt
11
fndata.txt
|
@ -75,6 +75,10 @@
|
|||
# max:
|
||||
# Like min, but for the maximum value.
|
||||
#
|
||||
# listto:
|
||||
# Identifies the function as a list-extracting function, for use with
|
||||
# lazy lists. It needs an LSL type as a parameter.
|
||||
#
|
||||
# return <value> [if <condition>]:
|
||||
# Self-explanatory. There can be several; they are evaluated in order.
|
||||
# <value> can be a parameter or a LSL constant. <condition> is explaned
|
||||
|
@ -927,30 +931,37 @@ string llList2CSV(list src)
|
|||
|
||||
float llList2Float(list src, integer index)
|
||||
- SEF
|
||||
- listto float
|
||||
|
||||
integer llList2Integer(list src, integer index)
|
||||
- SEF
|
||||
- listto integer
|
||||
|
||||
string llList2Json(string type, list values)
|
||||
- SEF
|
||||
|
||||
key llList2Key(list src, integer index)
|
||||
- SEF
|
||||
- listto key
|
||||
|
||||
list llList2List(list src, integer start, integer end)
|
||||
- SEF
|
||||
- listto list
|
||||
|
||||
list llList2ListStrided(list src, integer start, integer end, integer stride)
|
||||
- SEF
|
||||
|
||||
rotation llList2Rot(list src, integer index)
|
||||
- SEF
|
||||
- listto rotation
|
||||
|
||||
string llList2String(list src, integer index)
|
||||
- SEF
|
||||
- listto string
|
||||
|
||||
vector llList2Vector(list src, integer index)
|
||||
- SEF
|
||||
- listto vector
|
||||
|
||||
integer llListFindList(list src, list test)
|
||||
- SEF
|
||||
|
|
|
@ -235,7 +235,9 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
r'|\[(?:[^]"]|"(?:\\.|[^"])*")*\]))' # lists
|
||||
r'(?:\s+if\s+(.*\S))?'
|
||||
r'|(unstable|stop|strlen|detect|touch|grab)'
|
||||
r'|(min|max|delay)\s+([-0-9.]+))\s*$', re.I)
|
||||
r'|(min|max|delay)\s+([-0-9.]+)'
|
||||
r'|listto\s+(integer|float|string|key|vector|rotation|list)'
|
||||
r')\s*$', re.I)
|
||||
|
||||
# TODO: "quaternion" doesn't compare equal to "rotation" even if they are
|
||||
# equivalent. Canonicalize it before comparison, to avoid false
|
||||
|
@ -382,44 +384,50 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
functions[curr_fn]['uns'] = True
|
||||
else:
|
||||
functions[curr_fn][flag] = True
|
||||
elif match_flag.group(5).lower() in ('min', 'max'):
|
||||
minmax = match_flag.group(5).lower()
|
||||
value = match_flag.group(6)
|
||||
typ = functions[curr_fn]['Type']
|
||||
if typ == 'integer':
|
||||
good = parse_int_re.search(value)
|
||||
elif match_flag.group(5):
|
||||
if match_flag.group(5).lower() in ('min', 'max'):
|
||||
minmax = match_flag.group(5).lower()
|
||||
value = match_flag.group(6)
|
||||
typ = functions[curr_fn]['Type']
|
||||
if typ == 'integer':
|
||||
good = parse_int_re.search(value)
|
||||
if good:
|
||||
value = lslfuncs.S32(int(good.group(1), 0))
|
||||
elif typ == 'float':
|
||||
good = parse_fp_re.search(value)
|
||||
if good:
|
||||
value = lslfuncs.F32(float(good.group(1)))
|
||||
else:
|
||||
good = False
|
||||
if good:
|
||||
value = lslfuncs.S32(int(good.group(1), 0))
|
||||
elif typ == 'float':
|
||||
good = parse_fp_re.search(value)
|
||||
if good:
|
||||
value = lslfuncs.F32(float(good.group(1)))
|
||||
else:
|
||||
good = False
|
||||
if good:
|
||||
functions[curr_fn][minmax] = value
|
||||
else:
|
||||
warning(u"Type mismatch or value error in %s"
|
||||
u" line %d: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
continue
|
||||
else: # delay
|
||||
value = parse_fp_re.search(match_flag.group(6))
|
||||
if not value:
|
||||
warning(u"Invalid delay value in %s"
|
||||
u" line %d: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
continue
|
||||
functions[curr_fn][minmax] = value
|
||||
else:
|
||||
warning(u"Type mismatch or value error in %s"
|
||||
u" line %d: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
continue
|
||||
else: # delay
|
||||
value = parse_fp_re.search(match_flag.group(6))
|
||||
if not value:
|
||||
warning(u"Invalid delay value in %s"
|
||||
u" line %d: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
continue
|
||||
|
||||
value = float(value.group(1)) # no need to F32
|
||||
if value != 0 and 'SEF' in functions[curr_fn]:
|
||||
warning(u"Side-effect-free function"
|
||||
u" %s contradicts delay, in %s"
|
||||
u" line %d"
|
||||
% (ucurr_fn, ufndata, linenum))
|
||||
continue
|
||||
value = float(value.group(1)) # no need to F32
|
||||
if value != 0 and 'SEF' in functions[curr_fn]:
|
||||
warning(u"Side-effect-free function"
|
||||
u" %s contradicts delay, in %s"
|
||||
u" line %d"
|
||||
% (ucurr_fn, ufndata, linenum))
|
||||
continue
|
||||
|
||||
functions[curr_fn]['delay'] = value
|
||||
functions[curr_fn]['delay'] = value
|
||||
elif match_flag.group(7):
|
||||
functions[curr_fn]['ListTo'] = match_flag.group(7)
|
||||
continue
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
warning(u"Syntax error in %s line %d, skipping: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
|
|
|
@ -200,6 +200,11 @@ class EParseInvalidLabelOpt(EParse):
|
|||
u" child of a 'for', 'if', 'while' or 'do'. Disable optimization"
|
||||
u" or rewrite the code in some other way.")
|
||||
|
||||
class EParseNoConversion(EParse):
|
||||
def __init__(self, parser):
|
||||
super(EParseNoConversion, self).__init__(parser,
|
||||
u"There's no conversion function in the library for this type")
|
||||
|
||||
class EInternal(Exception):
|
||||
"""This exception is a construct to allow a different function to cause an
|
||||
immediate return of EOF from parser.GetToken().
|
||||
|
@ -225,9 +230,7 @@ class parser(object):
|
|||
unicode:'STRING_VALUE', Key:'KEY_VALUE', Vector:'VECTOR_VALUE',
|
||||
Quaternion:'ROTATION_VALUE', list:'LIST_VALUE'}
|
||||
|
||||
TypeToExtractionFunction = {'integer':'llList2Integer',
|
||||
'float':'llList2Float', 'string':'llList2String', 'key':'llList2Key',
|
||||
'vector':'llList2Vector', 'rotation':'llList2Rot', 'list':'llList2List'}
|
||||
TypeToExtractionFunction = {}
|
||||
|
||||
# Utility function
|
||||
def GenerateLabel(self):
|
||||
|
@ -1316,14 +1319,11 @@ list lazy_list_set(list L, integer i, list v)
|
|||
expr = self.Parse_unary_postfix_expression(AllowAssignment = False)
|
||||
basetype = expr.t
|
||||
if self.lazylists and basetype is None and expr.nt == 'SUBIDX':
|
||||
if typ not in self.TypeToExtractionFunction:
|
||||
raise EParseNoConversion(self)
|
||||
fn = self.TypeToExtractionFunction[typ]
|
||||
sym = self.FindSymbolFull(fn, 0)
|
||||
if sym is None:
|
||||
# in the unlikely event that the underlying function is not
|
||||
# defined in builtins.txt, throw a syntax error (making a
|
||||
# new exception just for this seems overkill, and throwing
|
||||
# an unknown identifier error would be confusing)
|
||||
raise EParseSyntax(self)
|
||||
assert sym is not None
|
||||
fnparamtypes = sym['ParamTypes']
|
||||
subparamtypes = [x.t for x in expr.ch]
|
||||
if fnparamtypes != subparamtypes:
|
||||
|
@ -2713,6 +2713,12 @@ list lazy_list_set(list L, integer i, list v)
|
|||
self.constants = lib[1]
|
||||
self.funclibrary = lib[2]
|
||||
|
||||
self.TypeToExtractionFunction.clear()
|
||||
for name in self.funclibrary:
|
||||
fn = self.funclibrary[name]
|
||||
if 'ListTo' in fn:
|
||||
self.TypeToExtractionFunction[fn['ListTo']] = name
|
||||
|
||||
self.filename = filename
|
||||
|
||||
if type(script) is unicode:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue