Implement 'add image' screen language statement.
This commit is contained in:
@@ -1377,6 +1377,106 @@ class SLDisplayable(SLBlock):
|
|||||||
i.dump_const(prefix + " ")
|
i.dump_const(prefix + " ")
|
||||||
|
|
||||||
|
|
||||||
|
class SLAddImage(SLDisplayable):
|
||||||
|
def __init__(self, loc, name):
|
||||||
|
super().__init__(loc, None, name=name, unique=False)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
debug = context.debug
|
||||||
|
|
||||||
|
cache = context.old_cache.get(self.serial, None) or context.miss_cache.get(self.serial, None)
|
||||||
|
|
||||||
|
# We use and check 'displayable', 'constant' and 'old_showif'
|
||||||
|
# fields, and rest are left unchanged.
|
||||||
|
if not isinstance(cache, SLCache):
|
||||||
|
cache = SLCache()
|
||||||
|
|
||||||
|
context.new_cache[self.serial] = cache
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
self.debug_line()
|
||||||
|
|
||||||
|
# Add image does not use style or scope.
|
||||||
|
if cache.constant is not None:
|
||||||
|
d = cache.constant
|
||||||
|
|
||||||
|
if context.showif is not None:
|
||||||
|
d = self.wrap_in_showif(d, context, cache)
|
||||||
|
|
||||||
|
context.children.append(d)
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
profile_log.write(" reused constant displayable")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create the context.
|
||||||
|
ctx = SLContext(context)
|
||||||
|
|
||||||
|
# True if we encountered an exception that we're recovering from
|
||||||
|
# due to being in prediction mode.
|
||||||
|
fail = False
|
||||||
|
|
||||||
|
# Result transform to display.
|
||||||
|
d = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
ctx.keywords = {}
|
||||||
|
|
||||||
|
SLBlock.keywords(self, ctx)
|
||||||
|
|
||||||
|
d = ctx.keywords.pop("at")
|
||||||
|
assert not ctx.keywords, ctx.keywords
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
self.report_arguments(cache, (), {}, None)
|
||||||
|
|
||||||
|
d._location = self.location
|
||||||
|
|
||||||
|
cache.copy_on_change = False # We no longer need to copy on change.
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
if self.constant:
|
||||||
|
profile_log.write(" created constant displayable")
|
||||||
|
else:
|
||||||
|
profile_log.write(" created displayable")
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
if not context.predicting:
|
||||||
|
raise
|
||||||
|
fail = True
|
||||||
|
|
||||||
|
if self.variable is not None:
|
||||||
|
context.scope[self.variable] = d
|
||||||
|
|
||||||
|
old_d = cache.displayable
|
||||||
|
|
||||||
|
if old_d is not None:
|
||||||
|
d.take_state(old_d)
|
||||||
|
d.take_execution_state(old_d)
|
||||||
|
|
||||||
|
# If a failure occurred during prediction, predict main (if known),
|
||||||
|
# and return.
|
||||||
|
if fail:
|
||||||
|
predict_displayable(d)
|
||||||
|
context.fail = True
|
||||||
|
return
|
||||||
|
|
||||||
|
cache.displayable = d
|
||||||
|
|
||||||
|
if ctx.fail:
|
||||||
|
context.fail = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self.constant:
|
||||||
|
cache.constant = d
|
||||||
|
|
||||||
|
if context.showif is not None:
|
||||||
|
d = self.wrap_in_showif(d, context, cache)
|
||||||
|
|
||||||
|
context.children.append(d)
|
||||||
|
|
||||||
|
|
||||||
class SLIf(SLNode):
|
class SLIf(SLNode):
|
||||||
"""
|
"""
|
||||||
A screen language AST node that corresponds to an If/Elif/Else statement.
|
A screen language AST node that corresponds to an If/Elif/Else statement.
|
||||||
|
|||||||
+71
-13
@@ -194,21 +194,42 @@ class Parser(object):
|
|||||||
self.keyword[i.prefix + j + i.name] = i
|
self.keyword[i.prefix + j + i.name] = i
|
||||||
|
|
||||||
elif isinstance(i, Parser):
|
elif isinstance(i, Parser):
|
||||||
self.children[i.name] = i
|
self.children[tuple(i.name.split())] = i
|
||||||
|
|
||||||
def parse_statement(self, loc, l, layout_mode=False, keyword=True):
|
def parse_statement(self, loc, l, layout_mode=False, keyword=True):
|
||||||
word = l.word() or l.match(r'\$')
|
# Look for one-line python only once.
|
||||||
|
if l.match(r'\$'):
|
||||||
if word and word in self.children:
|
if ("$", ) in self.children:
|
||||||
if layout_mode:
|
assert not layout_mode, "One-line python can not be in layout mode."
|
||||||
c = self.children[word].parse_layout(loc, l, self, keyword)
|
return self.children["$", ].parse(loc, l, self, keyword)
|
||||||
else:
|
else:
|
||||||
c = self.children[word].parse(loc, l, self, keyword)
|
return None
|
||||||
|
|
||||||
return c
|
name = ()
|
||||||
else:
|
while True:
|
||||||
|
cp = l.checkpoint()
|
||||||
|
word = l.word()
|
||||||
|
if not word:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Look for more specialized child parser.
|
||||||
|
new_name = (*name, word)
|
||||||
|
if new_name not in self.children:
|
||||||
|
l.revert(cp)
|
||||||
|
break
|
||||||
|
|
||||||
|
name = new_name
|
||||||
|
|
||||||
|
if not name:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if layout_mode:
|
||||||
|
c = self.children[name].parse_layout(loc, l, self, keyword)
|
||||||
|
else:
|
||||||
|
c = self.children[name].parse(loc, l, self, keyword)
|
||||||
|
|
||||||
|
return c
|
||||||
|
|
||||||
def parse_layout(self, loc, l, parent, keyword):
|
def parse_layout(self, loc, l, parent, keyword):
|
||||||
l.error("The %s statement cannot be used as a container for the has statement." % self.name)
|
l.error("The %s statement cannot be used as a container for the has statement." % self.name)
|
||||||
|
|
||||||
@@ -229,7 +250,16 @@ class Parser(object):
|
|||||||
|
|
||||||
raise Exception("Not Implemented")
|
raise Exception("Not Implemented")
|
||||||
|
|
||||||
def parse_contents(self, l, target, layout_mode=False, can_has=False, can_tag=False, block_only=False, keyword=True):
|
def parse_contents(
|
||||||
|
self,
|
||||||
|
l, target,
|
||||||
|
layout_mode=False,
|
||||||
|
can_has=False,
|
||||||
|
can_tag=False,
|
||||||
|
block_only=False,
|
||||||
|
keyword=True,
|
||||||
|
line_only=False,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Parses the remainder of the current line of `l`, and all of its subblock,
|
Parses the remainder of the current line of `l`, and all of its subblock,
|
||||||
looking for keywords and children.
|
looking for keywords and children.
|
||||||
@@ -247,6 +277,10 @@ class Parser(object):
|
|||||||
|
|
||||||
`block_only`
|
`block_only`
|
||||||
If true, only parse the block and not the initial properties.
|
If true, only parse the block and not the initial properties.
|
||||||
|
|
||||||
|
`line_only`
|
||||||
|
If true, only parse initial properties and not the block.
|
||||||
|
Lexer ends before the colon (if any).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
seen_keywords = set()
|
seen_keywords = set()
|
||||||
@@ -330,10 +364,16 @@ class Parser(object):
|
|||||||
# If not block_only, we allow keyword arguments on the starting
|
# If not block_only, we allow keyword arguments on the starting
|
||||||
# line.
|
# line.
|
||||||
while True:
|
while True:
|
||||||
|
cp = l.checkpoint()
|
||||||
if l.match(':'):
|
if l.match(':'):
|
||||||
l.expect_eol()
|
# If line_only, we stop before the colon.
|
||||||
l.expect_block(self.name)
|
if line_only:
|
||||||
block = True
|
l.revert(cp)
|
||||||
|
block = False
|
||||||
|
else:
|
||||||
|
l.expect_eol()
|
||||||
|
l.expect_block(self.name)
|
||||||
|
block = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if l.eol():
|
if l.eol():
|
||||||
@@ -700,6 +740,24 @@ class DisplayableParser(Parser):
|
|||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
|
||||||
|
class AddImageParser(Parser):
|
||||||
|
def __init__(self, name):
|
||||||
|
super().__init__(name)
|
||||||
|
self.variable = True
|
||||||
|
|
||||||
|
def parse(self, loc, l, parent, keyword):
|
||||||
|
rv = slast.SLAddImage(loc, self.name)
|
||||||
|
|
||||||
|
self.parse_contents(l, rv, line_only=True)
|
||||||
|
l.require(':')
|
||||||
|
l.expect_eol()
|
||||||
|
l.expect_block("ATL block")
|
||||||
|
rv.atl_transform = renpy.atl.parse_atl(l.subblock_lexer()) # type: ignore
|
||||||
|
return rv
|
||||||
|
|
||||||
|
AddImageParser("add image")
|
||||||
|
|
||||||
|
|
||||||
class IfParser(Parser):
|
class IfParser(Parser):
|
||||||
|
|
||||||
def __init__(self, name, node_type, parent_contents):
|
def __init__(self, name, node_type, parent_contents):
|
||||||
|
|||||||
Reference in New Issue
Block a user