Add preprocessor skip option, command line options and help, options for all functions, and enhance parentheses removal.

This commit is contained in:
Sei Lisa 2014-07-28 02:13:08 +02:00
parent ae94e80c34
commit eab0bec84b
4 changed files with 99 additions and 27 deletions

View file

@ -31,6 +31,7 @@ class optimizer(object):
"""If the statement is a constant or an identifier, remove it as it does
nothing.
"""
# Ideally this should consider side effect analysis of the whole thing.
if code[0] in (CONSTANT, 'IDENT', 'FIELD'):
code[:] = [S[';'], None]
else:
@ -86,7 +87,10 @@ class optimizer(object):
if code0 == '()':
self.FoldTree(code[2])
if code[2][0] == CONSTANT:
if code[2][0] in (CONSTANT, 'VECTOR', 'ROTATION', 'LIST',
'IDENT', 'FIELD', 'V++', 'V--', 'FUNCTION', 'PRINT'):
# Child is an unary postfix expression; parentheses can be
# removed safely.
code[:] = code[2]
return
@ -154,8 +158,11 @@ class optimizer(object):
code[:] = [S['*'], code[1], code[2], [CONSTANT, 'integer', 1<<(code[3][2] & 31)]]
else:
pass # TODO: Eliminate redundancy (x+0, x*1, x*-1, v+ZERO_VECTOR, perhaps x-1=~-x, etc.)
# Include != to ^ and || to | and maybe && to &
# Note some cases e.g. x*0 can't be optimized away without side-effect analysis.
# But some cases like %1 can be turned into *0 to save bytes.
# Turn also % (power of 2) into & mask (oops, nope, negative doesn't work)
# Maybe turn != -1 into ~ in if()'s.
return
if code0 in self.assign_ops:
@ -345,10 +352,16 @@ class optimizer(object):
raise Exception('Internal error: This should not happen, node = ' + code0) # pragma: no cover
def optimize(self, symtab, functions):
def optimize(self, symtab, functions, options = ('optimize',)):
"""Optimize the symbolic table symtab in place. Requires a table of
predefined functions for folding constants.
"""
if 'optimize' not in options:
return
# TODO: Add option to handle local jumps properly.
self.functions = functions
self.symtab = symtab

View file

@ -262,12 +262,13 @@ class outscript(object):
first = False
return ret + ')\n' + self.OutCode(code)
def output(self, symtab):
def output(self, symtab, options = ('optimizesigns',)):
# Build a sorted list of dict entries
order = []
self.symtab = symtab
self.optsigns = True
# Optimize signs
self.optsigns = 'optimizesigns' in options
for i in symtab:
item = []
@ -284,9 +285,6 @@ class outscript(object):
for name in order[0]:
sym = symtab[0][name]
#DEBUG
#print name, repr(sym)
ret += self.dent()
if sym[1] == 'State':
if name == 'default':

View file

@ -249,6 +249,19 @@ class parser(object):
self.pos += 1
# Process comments
if c == '#' and self.skippreproc:
# Preprocessor directives act like single line comments.
# Most are not supposed to reach us but cpp also generates
# as output lines like: # 123 "file.lsl"
self.ceof()
while self.script[self.pos] != '\n':
self.pos += 1
self.ceof() # A single-line comment at EOF is not unexpected EOF.
self.pos += 1
self.ceof()
continue
if c == '/':
if self.script[self.pos:self.pos+1] == '/':
self.pos += 1
@ -1666,7 +1679,7 @@ class parser(object):
self.NextToken()
def parse(self, script, options = frozenset()):
def parse(self, script, options = ()):
"""Parse the given stream with the given options.
This function also builds the temporary globals table.
@ -1693,7 +1706,8 @@ class parser(object):
# Allow C style string composition of strings: "blah" "blah" = "blahblah"
self.allowmultistrings = 'allowmultistrings' in options
# TODO: Add option to skip preprocessor directives (specifically #line).
# Skip preprocessor directives (specifically #line).
self.skippreproc = 'skippreproc' in options
# TODO: Allow pure C-style string parsing. This is low-priority.
#self.allowcescapes = 'allowcescapes' in options