/
spritegroup_ref.py
101 lines (81 loc) · 3.83 KB
/
spritegroup_ref.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
__license__ = """
NML is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NML is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with NML; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."""
from nml import generic
from nml.actions import action2
from nml.ast import switch
from .base_expression import Type, Expression
from itertools import chain
class SpriteGroupRef(Expression):
"""
Container for a reference to a sprite group / layout
@ivar name: Name of the referenced item
@type name: L{Identifier}
@ivar param_list: List of parameters to be passed
@type param_list: C{list} of L{Expression}
@ivar pos: Position of this reference
@type pos: L{Position}
@ivar act2: Action2 that is the target of this reference
To be used for action2s that have no direct equivalent in the AST
@type act2: L{Action2}
"""
def __init__(self, name, param_list, pos, act2 = None):
self.name = name
self.param_list = param_list
self.pos = pos
self.act2 = act2
self.is_procedure = False
def debug_print(self, indentation):
generic.print_dbg(indentation, 'Reference to:', self.name)
if len(self.param_list) != 0:
generic.print_dbg(indentation, 'Parameters:')
for p in self.param_list:
p.debug_print(indentation + 2)
def __str__(self):
if self.param_list:
return '{}({})'.format(self.name, ', '.join(str(x) for x in self.param_list))
return str(self.name)
def get_action2_id(self, feature):
"""
Get the action2 set-ID that this reference maps to
@param feature: Feature of the action2
@type feature: C{int}
@return: The set ID
@rtype: C{int}
"""
if self.act2 is not None: return self.act2.id
if self.name.value == 'CB_FAILED': return 0 # 0 serves as a failed CB result because it is never used
try:
spritegroup = action2.resolve_spritegroup(self.name)
except generic.ScriptError:
raise AssertionError("Illegal action2 reference '{}' encountered.".format(self.name.value))
return spritegroup.get_action2(feature).id
def reduce(self, id_dicts = [], unknown_id_fatal = True):
if self.name.value != 'CB_FAILED' and not self.is_procedure:
spritegroup = action2.resolve_spritegroup(self.name)
if isinstance(spritegroup, switch.Switch) and spritegroup.expr.is_read_only() and \
spritegroup.body.default is not None and spritegroup.body.default.value is not None and \
len(spritegroup.body.ranges) == 0:
generic.print_warning("Block '{}' returns a constant, optimising.".format(spritegroup.name.value), self.pos)
return spritegroup.body.default.value
return self
def supported_by_action2(self, raise_error):
return True
def collect_references(self):
return list(chain([self], *(p.collect_references() for p in self.param_list)))
def type(self):
if self.is_procedure: return Type.INTEGER
return Type.SPRITEGROUP_REF
def __eq__(self, other):
return other is not None and isinstance(other, SpriteGroupRef) and other.name == self.name and other.param_list == self.param_list
def __hash__(self):
return hash(self.name) ^ hash(tuple(self.param_list))