Handle type cast optimization in the output module (easiest).

This commit is contained in:
Sei Lisa 2014-07-27 04:24:14 +02:00
parent d98e145090
commit 6e1357f4f3

View file

@ -1,6 +1,11 @@
# Convert a symbol table (with parse tree) back to a script. # Convert a symbol table (with parse tree) back to a script.
import lslfuncs import lslfuncs
from lslcommon import Key, Vector, Quaternion from lslcommon import Key, Vector, Quaternion
import sys
def warning(txt):
assert type(txt) == unicode
sys.stderr.write(txt + u'\n')
class outscript(object): class outscript(object):
@ -11,16 +16,33 @@ class outscript(object):
unary_operands = frozenset(('NEG', '!', '~')) unary_operands = frozenset(('NEG', '!', '~'))
def Value2LSL(self, value): def Value2LSL(self, value):
if type(value) in (Key, unicode): tvalue = type(value)
if tvalue in (Key, unicode):
pfx = sfx = ''
if type(value) == Key: if type(value) == Key:
# Constants of type key can not be represented # Constants of type key can not be represented
raise lslfuncs.ELSLTypeMismatch #raise lslfuncs.ELSLTypeMismatch
return '"' + value.encode('utf8').replace('\\','\\\\').replace('"','\\"').replace('\n','\\n') + '"' # Actually they can be the result of folding.
if type(value) == int: # On second thought, if we report the error, the location info is lost.
if value < 0: # So we will let the compiler deal with the error.
return '0x%X' % (value + 4294967296) if self.globalmode and self.listmode:
warning(u'Illegal combo: Key type inside a global list')
if self.listmode or not self.globalmode:
pfx = '((key)'
sfx = ')'
return pfx + '"' + value.encode('utf8').replace('\\','\\\\') \
.replace('"','\\"').replace('\n','\\n') + '"' + sfx
if tvalue == int:
if value < 0 and not self.globalmode and not self.optsigns:
#return '0x%X' % (value + 4294967296)
return '((integer)' + str(value) + ')'
return str(value) return str(value)
if type(value) == float: if tvalue == float:
if value.is_integer() and -2147483648.0 <= value < 2147483648.0:
if self.globalmode or not self.optsigns:# or value >= 0:
return str(int(value))
else:
return '((float)' + str(int(value)) + ')'
s = str(value) s = str(value)
# Try to remove as many decimals as possible but keeping the F32 value intact # Try to remove as many decimals as possible but keeping the F32 value intact
exp = s.find('e') exp = s.find('e')
@ -37,14 +59,16 @@ class outscript(object):
exp = '' exp = ''
while s[-1] != '.' and lslfuncs.F32(float(s[:-1]+exp)) == value: while s[-1] != '.' and lslfuncs.F32(float(s[:-1]+exp)) == value:
s = s[:-1] s = s[:-1]
return s + exp if value >= 0 or self.globalmode or not self.optsigns:
if type(value) == Vector: return s + exp
return '((float)' + s + exp + ')'
if tvalue == Vector:
return '<' + self.Value2LSL(value[0]) + ', ' + self.Value2LSL(value[1]) \ return '<' + self.Value2LSL(value[0]) + ', ' + self.Value2LSL(value[1]) \
+ ', ' + self.Value2LSL(value[2]) + '>' + ', ' + self.Value2LSL(value[2]) + '>'
if type(value) == Quaternion: if tvalue == Quaternion:
return '<' + self.Value2LSL(value[0]) + ', ' + self.Value2LSL(value[1]) \ return '<' + self.Value2LSL(value[0]) + ', ' + self.Value2LSL(value[1]) \
+ ', ' + self.Value2LSL(value[2]) + ', ' + self.Value2LSL(value[3]) + '>' + ', ' + self.Value2LSL(value[2]) + ', ' + self.Value2LSL(value[3]) + '>'
if type(value) == list: if tvalue == list:
if value == []: if value == []:
return '[]' return '[]'
if len(value) < 5: if len(value) < 5:
@ -57,11 +81,13 @@ class outscript(object):
ret += self.dent() + ', ' ret += self.dent() + ', '
else: else:
ret += self.dent() + '[ ' ret += self.dent() + '[ '
self.listmode = True
ret += self.Value2LSL(entry) + '\n' ret += self.Value2LSL(entry) + '\n'
self.listmode = False
first = False first = False
self.indentlevel -= 1 self.indentlevel -= 1
return ret + self.dent() + self.indent + ']' return ret + self.dent() + self.indent + ']'
raise lslfuncs.ELSLTypeMismatch assert False, u'Unknown value type in Value2LSL: ' + repr(type(value))
def dent(self): def dent(self):
return self.indent * self.indentlevel return self.indent * self.indentlevel
@ -232,6 +258,8 @@ class outscript(object):
order = [] order = []
self.symtab = symtab self.symtab = symtab
self.optsigns = False
for i in symtab: for i in symtab:
item = [] item = []
for j in sorted(i.items(), key=lambda k: -1 if k[0]==-1 else k[1][0]): for j in sorted(i.items(), key=lambda k: -1 if k[0]==-1 else k[1][0]):
@ -242,6 +270,8 @@ class outscript(object):
ret = '' ret = ''
self.indent = ' ' self.indent = ' '
self.indentlevel = 0 self.indentlevel = 0
self.globalmode = False
self.listmode = False
for name in order[0]: for name in order[0]:
sym = symtab[0][name] sym = symtab[0][name]
@ -262,10 +292,11 @@ class outscript(object):
self.indentlevel -= 1 self.indentlevel -= 1
ret += self.dent() + '}\n' ret += self.dent() + '}\n'
elif len(sym) > 3: elif len(sym) > 3: # function call
ret += self.OutFunc(sym[1], name, sym[3], symtab[sym[4]], sym[2]) ret += self.OutFunc(sym[1], name, sym[3], symtab[sym[4]], sym[2])
else: else: # global var
self.globalmode = True
ret += sym[1] + ' ' + name ret += sym[1] + ' ' + name
if sym[2] is not None: if sym[2] is not None:
ret += ' = ' ret += ' = '
@ -275,5 +306,6 @@ class outscript(object):
ret += self.Value2LSL(sym[2]) ret += self.Value2LSL(sym[2])
ret += ';\n' ret += ';\n'
self.globalmode = False
return ret return ret