mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Deal with the state change in globals error.
This commit is contained in:
parent
400809671e
commit
dce6419b4f
2 changed files with 40 additions and 10 deletions
|
@ -3,8 +3,9 @@ import lslfuncs
|
|||
from lslparse import warning
|
||||
|
||||
from lslrenamer import renamer
|
||||
from lsldeadcode import deadcode
|
||||
|
||||
class optimizer(renamer):
|
||||
class optimizer(renamer, deadcode):
|
||||
|
||||
# Default values per type when declaring variables
|
||||
DefaultValues = {'integer': 0, 'float': 0.0, 'string': u'',
|
||||
|
@ -450,20 +451,30 @@ class optimizer(renamer):
|
|||
for idx in xrange(len(child)):
|
||||
self.FoldTree(child, idx)
|
||||
self.FoldStmt(child, idx)
|
||||
if 'StSw' in child[idx]:
|
||||
node['StSw'] = True
|
||||
return
|
||||
|
||||
if nt == 'IF':
|
||||
self.FoldTree(child, 0)
|
||||
if child[0]['nt'] == 'CONST':
|
||||
# We can remove one of the branches safely.
|
||||
# We might be able to remove one of the branches.
|
||||
if lslfuncs.cond(child[0]['value']):
|
||||
self.FoldTree(child, 1)
|
||||
parent[index] = child[1]
|
||||
# If it has a state switch, the if() must be preserved
|
||||
# (but the else branch may be removed).
|
||||
if 'StSw' in child[1]:
|
||||
if len(child) > 2:
|
||||
del child[2] # Delete ELSE if present
|
||||
child[0]['t'] = 'integer'
|
||||
child[0]['value'] = 1
|
||||
else:
|
||||
self.FoldStmt(child, 1)
|
||||
parent[index] = child[1]
|
||||
elif len(child) > 2:
|
||||
self.FoldTree(child, 2)
|
||||
parent[index] = child[2]
|
||||
self.FoldStmt(child, 2)
|
||||
parent[index] = child[2]
|
||||
else:
|
||||
# No ELSE branch, replace the statement with an empty one.
|
||||
parent[index] = {'nt':';', 't':None}
|
||||
|
@ -568,6 +579,10 @@ class optimizer(renamer):
|
|||
lslfuncs.ZERO_ROTATION}]
|
||||
return
|
||||
|
||||
if nt == 'STSW':
|
||||
node['StSw'] = True
|
||||
return
|
||||
|
||||
if nt in self.ignored_stmts:
|
||||
return
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# TODO: Check "Not All Code Paths return a Value"
|
||||
|
||||
from lslcommon import Key, Vector, Quaternion
|
||||
import lslfuncs
|
||||
|
@ -92,6 +93,11 @@ class EParseDeclarationScope(EParse):
|
|||
super(EParseDeclarationScope, self).__init__(parser,
|
||||
u"Declaration requires a new scope -- use { and }")
|
||||
|
||||
class EParseCantChangeState(EParse):
|
||||
def __init__(self, parser):
|
||||
super(EParseCantChangeState, self).__init__(parser,
|
||||
u"Global functions can't change state")
|
||||
|
||||
class EParseDuplicateLabel(EParse):
|
||||
def __init__(self, parser):
|
||||
super(EParseDuplicateLabel, self).__init__(parser,
|
||||
|
@ -1127,7 +1133,7 @@ class parser(object):
|
|||
raise EParseFunctionMismatch(self)
|
||||
return ret
|
||||
|
||||
def Parse_statement(self, ReturnType, AllowDecl = False):
|
||||
def Parse_statement(self, ReturnType, AllowDecl = False, AllowStSw = False):
|
||||
"""Grammar parsed here:
|
||||
|
||||
statement: ';' | single_statement | code_block
|
||||
|
@ -1219,6 +1225,8 @@ class parser(object):
|
|||
self.NextToken()
|
||||
self.expect(';')
|
||||
self.NextToken()
|
||||
if self.localevents is None and not AllowStSw:
|
||||
raise EParseCantChangeState(self)
|
||||
return {'nt':'STSW', 't':None, 'name':name, 'scope':0}
|
||||
if tok0 == 'RETURN':
|
||||
self.NextToken()
|
||||
|
@ -1245,7 +1253,12 @@ class parser(object):
|
|||
cur['ch'].append(self.Parse_expression())
|
||||
self.expect(')')
|
||||
self.NextToken()
|
||||
cur['ch'].append(self.Parse_statement(ReturnType))
|
||||
# INCOMPATIBILITY NOTE: This is more permissive than LSL.
|
||||
# In LSL, an if...then...else does NOT allow a state change
|
||||
# in either branch. Only an if...then without else does.
|
||||
# BUT we're not going to check the branch after the fact, just
|
||||
# to report that error. The compiler will report it.
|
||||
cur['ch'].append(self.Parse_statement(ReturnType, AllowStSw = True))
|
||||
if self.tok[0] == 'ELSE':
|
||||
self.NextToken()
|
||||
if self.tok[0] == 'IF':
|
||||
|
@ -1262,10 +1275,11 @@ class parser(object):
|
|||
condition = self.Parse_expression()
|
||||
self.expect(')')
|
||||
self.NextToken()
|
||||
return {'nt':'WHILE', 't':None, 'ch':[condition, self.Parse_statement(ReturnType)]}
|
||||
return {'nt':'WHILE', 't':None, 'ch':[condition,
|
||||
self.Parse_statement(ReturnType, AllowStSw = True)]}
|
||||
if tok0 == 'DO':
|
||||
self.NextToken()
|
||||
stmt = self.Parse_statement(ReturnType)
|
||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True)
|
||||
self.expect('WHILE')
|
||||
self.NextToken()
|
||||
self.expect('(')
|
||||
|
@ -1289,7 +1303,7 @@ class parser(object):
|
|||
iterator = self.Parse_optional_expression_list()
|
||||
self.expect(')')
|
||||
self.NextToken()
|
||||
stmt = self.Parse_statement(ReturnType)
|
||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True)
|
||||
return {'nt':'FOR', 't':None,
|
||||
'ch':[{'nt':'EXPRLIST','t':None, 'ch':initializer},
|
||||
condition,
|
||||
|
@ -1561,6 +1575,7 @@ class parser(object):
|
|||
params = self.Parse_optional_param_list()
|
||||
self.expect(')')
|
||||
self.NextToken()
|
||||
self.localevents = None
|
||||
self.locallabels = set()
|
||||
body = self.Parse_code_block(typ)
|
||||
del self.locallabels
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue