diff options
Diffstat (limited to 'unrpyc/renpy/ast.py')
-rw-r--r-- | unrpyc/renpy/ast.py | 1757 |
1 files changed, 0 insertions, 1757 deletions
diff --git a/unrpyc/renpy/ast.py b/unrpyc/renpy/ast.py deleted file mode 100644 index 2f714ce..0000000 --- a/unrpyc/renpy/ast.py +++ /dev/null @@ -1,1757 +0,0 @@ -# Copyright 2004-2013 Tom Rothamel <pytom@bishoujo.us> -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# This file contains the AST for the Ren'Py script language. Each class -# here corresponds to a statement in the script language. - -# NOTE: -# When updating this file, consider if lint.py or warp.py also need -# updating. - -import renpy.display - -import re -import time -import hashlib -import collections - -def next_node(n): - """ - Indicates the next node that should be executed. When a statement - can crash, this should be set as early as possible, so that ignore - can bring us there. - """ - - renpy.game.context().next_node = n - -class ParameterInfo(object): - """ - This class is used to store information about parameters to a - label. - """ - def __init__(self, parameters, positional, extrapos, extrakw): - - # A list of parameter name, default value pairs. - self.parameters = parameters - - # A list, giving the positional parameters to this function, - # in order. - self.positional = positional - - # A variable that takes the extra positional arguments, if - # any. None if no such variable exists. - self.extrapos = extrapos - - # A variable that takes the extra keyword arguments, if - # any. None if no such variable exists. - self.extrakw = extrakw - -class ArgumentInfo(object): - - def __init__(self, arguments, extrapos, extrakw): - - # A list of (keyword, expression) pairs. If an argument doesn't - # have a keyword, it's thought of as positional. - self.arguments = arguments - - # An expression giving extra positional arguments being - # supplied to this function. - self.extrapos = extrapos - - # An expression giving extra keyword arguments that need - # to be supplied to this function. - self.extrakw = extrakw - - -def __newobj__(cls, *args): - return cls.__new__(cls, *args) - -# This represents a string containing python code. -class PyExpr(str): - - __slots__ = [ - 'filename', - 'linenumber', - ] - - def __new__(cls, s, filename, linenumber): - self = str.__new__(cls, s) - self.filename = filename - self.linenumber = linenumber - return self - - def __getnewargs__(self): - return (str(self), self.filename, self.linenumber) # E1101 - -class PyCode(object): - - __slots__ = [ - 'source', - 'location', - 'mode', - 'bytecode', - 'hash', - ] - - def __getstate__(self): - return (1, self.source, self.location, self.mode) - - def __setstate__(self, state): - (_, self.source, self.location, self.mode) = state - self.bytecode = None - - if renpy.game.script.record_pycode: - renpy.game.script.all_pycode.append(self) - - def __init__(self, source, loc=('<none>', 1), mode='exec'): - - if isinstance(source, PyExpr): - loc = (source.filename, source.linenumber, source) - - # The source code. - self.source = source - - # The time is necessary so we can disambiguate between Python - # blocks on the same line in different script versions. - self.location = loc + ( int(time.time()), ) - self.mode = mode - - # This will be initialized later on, after we are serialized. - self.bytecode = None - - if renpy.game.script.record_pycode: - renpy.game.script.all_pycode.append(self) - - self.hash = None - - def get_hash(self): - try: - if self.hash is not None: - return self.hash - except: - pass - - code = self.source - if isinstance(code, renpy.python.ast.AST): #@UndefinedVariable - code = renpy.python.ast.dump(code) #@UndefinedVariable - - self.hash = chr(renpy.bytecode_version) + hashlib.md5(repr(self.location) + code.encode("utf-8")).digest() - return self.hash - - -def chain_block(block, next): #@ReservedAssignment - """ - This is called to chain together all of the nodes in a block. Node - n is chained with node n+1, while the last node is chained with - next. - """ - - if not block: - return - - for a, b in zip(block, block[1:]): - a.chain(b) - - block[-1].chain(next) - - -class Scry(object): - """ - This is used to store information about the future, if we know it. Unlike - predict, this tries to only get things we _know_ will happen. - """ - - # By default, all attributes are None. - def __getattr__(self, name): - return None - - def __next__(self): #@ReservedAssignment - if self._next is None: - return None - else: - return self._next.scry() - - -class Node(object): - """ - A node in the abstract syntax tree of the program. - - @ivar name: The name of this node. - - @ivar filename: The filename where this node comes from. - @ivar linenumber: The line number of the line on which this node is defined. - """ - - __slots__ = [ - 'name', - 'filename', - 'linenumber', - 'next', - ] - - # True if this node is translatable, false otherwise. (This can be set on - # the class or the instance.) - translatable = False - - # Called to set the state of a Node, when necessary. - def __setstate__(self, state): - for k, v in state[1].items(): - try: - setattr(self, k, v) - except AttributeError: - pass - - - def __init__(self, loc): - """ - Initializes this Node object. - - @param loc: A (filename, physical line number) tuple giving the - logical line on which this Node node starts. - """ - - self.filename, self.linenumber = loc - self.name = None - self.next = None - - def diff_info(self): - """ - Returns a tuple of diff info about ourself. This is used to - compare Nodes to see if they should be considered the same node. The - tuple returned must be hashable. - """ - - return ( id(self), ) - - def get_children(self): - """ - Returns a list of all of the nodes that are children of this - node. (That is, all of the nodes in any block associated with - this node.) - """ - - return [ ] - - def get_init(self): - """ - Returns a node that should be run at init time (that is, before - the normal start of the script.), or None if this node doesn't - care to suggest one. - - (The only class that needs to override this is Init.) - """ - - return None - - def chain(self, next): #@ReservedAssignment - """ - This is called with the Node node that should be followed after - executing this node, and all nodes that this node - executes. (For example, if this node is a block label, the - next is the node that should be executed after all nodes in - the block.) - """ - - self.next = next - - def execute(self): - """ - Causes this node to execute, and any action it entails to be - performed. The node should call next_node with the node to - be executed after this one. - """ - - assert False, "Node subclass forgot to define execute." - - def early_execute(self): - """ - Called when the module is loaded. - """ - - def predict(self): - """ - This is called to predictively load images from this node. It - should cause renpy.display.predict.image and - renpy.display.predict.screen to be called as necessary. - """ - - if self.__next__: - return [ self.__next__ ] - else: - return [ ] - - def scry(self): - """ - Called to return an object with some general, user-definable information - about the future. - """ - - rv = Scry() - rv._next = self.__next__ # W0201 - return rv - - def restructure(self, callback): - """ - Called to restructure the AST. - - When this method is called, callback is called once for each child - block of the node. The block, a list, can be updated by the callback - using slice assignment to the list. - """ - - # Does nothing for nodes that do not contain child blocks. - return - - def get_code(self, dialogue_filter=None): - """ - Returns the canonical form of the code corresponding to this statement. - This only needs to be defined if the statement is translatable. - - `filter` - If present, a filter that should be applied to human-readable - text in the statement. - """ - - raise Exception("Not Implemented") - -def say_menu_with(expression, callback): - """ - This handles the with clause of a say or menu statement. - """ - - if expression is not None: - what = renpy.python.py_eval(expression) - elif renpy.store.default_transition and renpy.game.preferences.transitions == 2: - what = renpy.store.default_transition - else: - return - - if not what: - return - - if renpy.game.preferences.transitions: - # renpy.game.interface.set_transition(what) - callback(what) - -class Say(Node): - - __slots__ = [ - 'who', - 'who_fast', - 'what', - 'with_', - 'interact', - 'attributes', - ] - - def diff_info(self): - return (Say, self.who, self.what) - - def __setstate__(self, state): - self.attributes = None - self.interact = True - Node.__setstate__(self, state) - - def __init__(self, loc, who, what, with_, interact=True, attributes=None): - - super(Say, self).__init__(loc) - - if who is not None: - self.who = who.strip() - - if re.match(r'[a-zA-Z_]\w*$', self.who): - self.who_fast = True - else: - self.who_fast = False - else: - self.who = None - self.who_fast = False - - self.what = what - self.with_ = with_ - self.interact = interact - - # A tuple of attributes that are applied to the character that's - # speaking, or None to disable this behavior. - self.attributes = attributes - - def get_code(self, dialogue_filter=None): - rv = [ ] - - if self.who: - rv.append(self.who) - - if self.attributes is not None: - rv.extend(self.attributes) - - what = self.what - if dialogue_filter is not None: - what = dialogue_filter(what) - - rv.append(renpy.translation.encode_say_string(what)) - - if not self.interact: - rv.append("nointeract") - - if self.with_: - rv.append("with") - rv.append(self.with_) - - return " ".join(rv) - - def execute(self): - - next_node(self.__next__) - - try: - - renpy.exports.say_attributes = self.attributes - - if self.who is not None: - if self.who_fast: - who = getattr(renpy.store, self.who, None) - if who is None: - raise Exception("Sayer '%s' is not defined." % self.who.encode("utf-8")) - else: - who = renpy.python.py_eval(self.who) - else: - who = None - - if not ( - (who is None) or - isinstance(who, collections.Callable) or - isinstance(who, str) ): - - raise Exception("Sayer %s is not a function or string." % self.who.encode("utf-8")) - - what = self.what - if renpy.config.say_menu_text_filter: - what = renpy.config.say_menu_text_filter(what) # E1102 - - if getattr(who, "record_say", True): - renpy.store._last_say_who = self.who - renpy.store._last_say_what = what - - say_menu_with(self.with_, renpy.game.interface.set_transition) - renpy.exports.say(who, what, interact=self.interact) - - finally: - renpy.exports.say_attributes = None - - - def predict(self): - - old_attributes = renpy.exports.say_attributes - - try: - - renpy.exports.say_attributes = self.attributes - - if self.who is not None: - if self.who_fast: - who = getattr(renpy.store, self.who) - else: - who = renpy.python.py_eval(self.who) - else: - who = None - - def predict_with(trans): - renpy.display.predict.displayable(trans(old_widget=None, new_widget=None)) - - say_menu_with(self.with_, predict_with) - - what = self.what - if renpy.config.say_menu_text_filter: - what = renpy.config.say_menu_text_filter(what) - - renpy.exports.predict_say(who, what) - - finally: - renpy.exports.say_attributes = old_attributes - - return [ self.__next__ ] - - def scry(self): - rv = Node.scry(self) - - if self.who is not None: - if self.who_fast: - who = getattr(renpy.store, self.who) - else: - who = renpy.python.py_eval(self.who) - else: - who = None - - if self.interact: - renpy.exports.scry_say(who, rv) - else: - rv.interacts = False - - return rv - -# Copy the descriptor. -setattr(Say, "with", Say.with_) # E1101 - -class Init(Node): - - __slots__ = [ - 'block', - 'priority', - ] - - def __init__(self, loc, block, priority): - super(Init, self).__init__(loc) - - self.block = block - self.priority = priority - - - def get_children(self): - return self.block - - def get_init(self): - return self.priority, self.block[0] - - # We handle chaining specially. We want to chain together the nodes in - # the block, but we want that chain to end in None, and we also want - # this node to just continue on to the next node in normal execution. - def chain(self, next): #@ReservedAssignment - self.next = next - - chain_block(self.block, None) - - def execute(self): - next_node(self.__next__) - - def restructure(self, callback): - callback(self.block) - -def apply_arguments(params, args, kwargs): - """ - Applies arguments to parameters to update scope. - - `scope` - A dict. - - `params` - The parameters object. - - `args`, `kwargs` - Positional and keyword arguments. - """ - - values = { } - rv = { } - - if args is None: - args = () - - if kwargs is None: - kwargs = { } - - if params is None: - if args or kwargs: - raise Exception("Arguments supplied, but parameter list not present") - else: - return rv - - for name, value in zip(params.positional, args): - if name in values: - raise Exception("Parameter %s has two values." % name) - - values[name] = value - - extrapos = tuple(args[len(params.positional):]) - - for name, value in kwargs.items(): - if name in values: - raise Exception("Parameter %s has two values." % name) - - values[name] = value - - for name, default in params.parameters: - - if name not in values: - if default is None: - raise Exception("Required parameter %s has no value." % name) - else: - rv[name] = renpy.python.py_eval(default) - - else: - rv[name] = values[name] - del values[name] - - # Now, values has the left-over keyword arguments, and extrapos - # has the left-over positional arguments. - - if params.extrapos: - rv[params.extrapos] = extrapos - elif extrapos: - raise Exception("Too many arguments in call (expected %d, got %d)." % (len(params.positional), len(args))) - - if params.extrakw: - rv[params.extrakw] = values - else: - if values: - raise Exception("Unknown keyword arguments: %s" % ( ", ".join(list(values.keys())))) - - return rv - -class Label(Node): - - __slots__ = [ - 'name', - 'parameters', - 'block', - 'hide', - ] - - def __setstate__(self, state): - self.parameters = None - self.hide = False - Node.__setstate__(self, state) - - def __init__(self, loc, name, block, parameters, hide=False): - """ - Constructs a new Label node. - - @param name: The name of this label. - @param block: A (potentially empty) list of nodes making up the - block associated with this label. - """ - - super(Label, self).__init__(loc) - - self.name = name - self.block = block - self.parameters = parameters - self.hide = hide - - def diff_info(self): - return (Label, self.name) - - def get_children(self): - return self.block - - def chain(self, next): #@ReservedAssignment - - if self.block: - self.next = self.block[0] - chain_block(self.block, next) - else: - self.next = next - - def execute(self): - next_node(self.__next__) - - renpy.game.context().mark_seen() - - values = apply_arguments(self.parameters, renpy.store._args, renpy.store._kwargs) - - for k, v in values.items(): - renpy.exports.dynamic(k) - setattr(renpy.store, k, v) - - renpy.store._args = None - renpy.store._kwargs = None - - if renpy.config.label_callback: - renpy.config.label_callback(self.name, renpy.game.context().last_abnormal) - - def restructure(self, callback): - callback(self.block) - - -class Python(Node): - - __slots__ = [ - 'hide', - 'code', - 'store', - ] - - def __setstate__(self, state): - self.store = "store" - super(Python, self).__setstate__(state) - - def __init__(self, loc, python_code, hide=False, store="store"): - """ - @param code: A PyCode object. - - @param hide: If True, the code will be executed with its - own local dictionary. - """ - - super(Python, self).__init__(loc) - - self.hide = hide - self.code = PyCode(python_code, loc=loc, mode='exec') - self.store = store - - def diff_info(self): - return (Python, self.code.source) - - def early_execute(self): - renpy.python.create_store(self.store) - - def execute(self): - next_node(self.__next__) - - try: - renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store) - finally: - - if not renpy.game.context().init_phase: - for i in renpy.config.python_callbacks: - i() - - def scry(self): - rv = Node.scry(self) - rv.interacts = True - return rv - -class EarlyPython(Node): - - __slots__ = [ - 'hide', - 'code', - 'store', - ] - - def __setstate__(self, state): - self.store = "store" - super(EarlyPython, self).__setstate__(state) - - def __init__(self, loc, python_code, hide=False, store="store"): - """ - @param code: A PyCode object. - - @param hide: If True, the code will be executed with its - own local dictionary. - """ - - super(EarlyPython, self).__init__(loc) - - self.hide = hide - self.code = PyCode(python_code, loc=loc, mode='exec') - self.store = store - - def diff_info(self): - return (EarlyPython, self.code.source) - - def execute(self): - next_node(self.__next__) - - def early_execute(self): - renpy.python.create_store(self.store) - - if self.code.bytecode: - renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store) - -class Image(Node): - - __slots__ = [ - 'imgname', - 'code', - 'atl', - ] - - def __init__(self, loc, name, expr=None, atl=None): - """ - @param name: The name of the image being defined. - - @param expr: An expression yielding a Displayable that is - assigned to the image. - """ - - super(Image, self).__init__(loc) - - self.imgname = name - - if expr: - self.code = PyCode(expr, loc=loc, mode='eval') - self.atl = None - else: - self.code = None - self.atl = atl - - def diff_info(self): - return (Image, tuple(self.imgname)) - - def execute(self): - - # Note: We should always check that self.code is None before - # accessing self.atl, as self.atl may not always exist. - - next_node(self.__next__) - - if self.code is not None: - img = renpy.python.py_eval_bytecode(self.code.bytecode) - else: - img = renpy.display.motion.ATLTransform(self.atl) - - renpy.exports.image(self.imgname, img) - - - -class Transform(Node): - - __slots__ = [ - - # The name of the transform. - 'varname', - - # The block of ATL associated with the transform. - 'atl', - - # The parameters associated with the transform, if any. - 'parameters', - ] - - default_parameters = ParameterInfo([ ], [ ], None, None) - - def __init__(self, loc, name, atl=None, parameters=default_parameters): - - super(Transform, self).__init__(loc) - - self.varname = name - self.atl = atl - self.parameters = parameters - - def diff_info(self): - return (Transform, self.varname) - - def execute(self): - - next_node(self.__next__) - - parameters = getattr(self, "parameters", None) - - if parameters is None: - parameters = Transform.default_parameters - - trans = renpy.display.motion.ATLTransform(self.atl, parameters=parameters) - renpy.dump.transforms.append((self.varname, self.filename, self.linenumber)) - setattr(renpy.store, self.varname, trans) - - -def predict_imspec(imspec, scene=False, atl=None): - """ - Call this to use the given callback to predict the image named - in imspec. - """ - - if len(imspec) == 7: - name, expression, tag, _at_list, layer, _zorder, _behind = imspec - - elif len(imspec) == 6: - name, expression, tag, _at_list, layer, _zorder = imspec - - elif len(imspec) == 3: - name, _at_list, layer = imspec - - - if expression: - try: - img = renpy.python.py_eval(expression) - img = renpy.easy.displayable(img) - except: - return - - else: - img = renpy.display.image.images.get(name, None) - if img is None: - return - - full_name = name - if tag: - full_name = (tag,) + full_name[1:] - - if scene: - renpy.game.context().images.predict_scene(layer) - - renpy.game.context().images.predict_show(tag or name, layer) - - if atl is not None: - try: - img = renpy.display.motion.ATLTransform(atl, child=img) - except: - import traceback - traceback.print_exc() - - renpy.display.predict.displayable(img) - - - -def show_imspec(imspec, atl=None): - - if len(imspec) == 7: - name, expression, tag, at_list, layer, zorder, behind = imspec - - elif len(imspec) == 6: - name, expression, tag, at_list, layer, zorder = imspec - behind = [ ] - - elif len(imspec) == 3: - name, at_list, layer = imspec - expression = None - tag = None - zorder = None - behind = [ ] - - if zorder is not None: - zorder = renpy.python.py_eval(zorder) - else: - zorder = 0 - - if expression is not None: - expression = renpy.python.py_eval(expression) - expression = renpy.easy.displayable(expression) - - at_list = [ renpy.python.py_eval(i) for i in at_list ] - - renpy.config.show(name, - at_list=at_list, - layer=layer, - what=expression, - zorder=zorder, - tag=tag, - behind=behind, - atl=atl) - -class Show(Node): - - __slots__ = [ - 'imspec', - 'atl', - ] - - def __init__(self, loc, imspec, atl=None): - """ - @param imspec: A triple consisting of an image name (itself a - tuple of strings), a list of at expressions, and a layer. - """ - - super(Show, self).__init__(loc) - - self.imspec = imspec - self.atl = atl - - def diff_info(self): - return (Show, tuple(self.imspec[0])) - - def execute(self): - next_node(self.__next__) - - show_imspec(self.imspec, atl=getattr(self, "atl", None)) - - def predict(self): - predict_imspec(self.imspec, atl=getattr(self, "atl", None)) - return [ self.__next__ ] - - -class Scene(Node): - - __slots__ = [ - 'imspec', - 'layer', - 'atl', - ] - - def __init__(self, loc, imgspec, layer, atl=None): - """ - @param imspec: A triple consisting of an image name (itself a - tuple of strings), a list of at expressions, and a layer, or - None to not have this scene statement also display an image. - """ - - super(Scene, self).__init__(loc) - - self.imspec = imgspec - self.layer = layer - self.atl = atl - - def diff_info(self): - - if self.imspec: - data = tuple(self.imspec[0]) - else: - data = None - - return (Scene, data) - - def execute(self): - - next_node(self.__next__) - - renpy.config.scene(self.layer) - - if self.imspec: - show_imspec(self.imspec, atl=getattr(self, "atl", None)) - - def predict(self): - - if self.imspec: - predict_imspec(self.imspec, atl=getattr(self, "atl", None), scene=True) - - return [ self.__next__ ] - - -class Hide(Node): - - __slots__ = [ - 'imspec', - ] - - def __init__(self, loc, imgspec): - """ - @param imspec: A triple consisting of an image name (itself a - tuple of strings), a list of at expressions, and a list of - with expressions. - """ - - super(Hide, self).__init__(loc) - - self.imspec = imgspec - - def diff_info(self): - return (Hide, tuple(self.imspec[0])) - - def predict(self): - - if len(self.imspec) == 3: - name, _at_list, layer = self.imspec - tag = None - _expression = None - _zorder = None - _behind = None - elif len(self.imspec) == 6: - name, _expression, tag, _at_list, layer, _zorder = self.imspec - _behind = None - elif len(self.imspec) == 7: - name, _expression, tag, _at_list, layer, _zorder, _behind = self.imspec - - - if tag is None: - tag = name[0] - - renpy.game.context().images.predict_hide(tag, layer) - - return [ self.__next__ ] - - def execute(self): - - next_node(self.__next__) - - if len(self.imspec) == 3: - name, _at_list, layer = self.imspec - _expression = None - tag = None - _zorder = 0 - elif len(self.imspec) == 6: - name, _expression, tag, _at_list, layer, _zorder = self.imspec - elif len(self.imspec) == 7: - name, _expression, tag, _at_list, layer, _zorder, _behind = self.imspec - - renpy.config.hide(tag or name, layer) - - -class With(Node): - - __slots__ = [ - 'expr', - 'paired', - ] - - def __setstate__(self, state): - self.paired = None - Node.__setstate__(self, state) - - def __init__(self, loc, expr, paired=None): - """ - @param expr: An expression giving a transition or None. - """ - - super(With, self).__init__(loc) - self.expr = expr - self.paired = paired - - def diff_info(self): - return (With, self.expr) - - def execute(self): - - next_node(self.__next__) - - trans = renpy.python.py_eval(self.expr) - - if self.paired is not None: - paired = renpy.python.py_eval(self.paired) - else: - paired = None - - renpy.exports.with_statement(trans, paired) - - def predict(self): - - try: - trans = renpy.python.py_eval(self.expr) - - if trans: - renpy.display.predict.displayable(trans(old_widget=None, new_widget=None)) - - except: - pass - - - return [ self.__next__ ] - - -class Call(Node): - - __slots__ = [ - 'label', - 'arguments', - 'expression', - ] - - def __setstate__(self, state): - self.arguments = None - Node.__setstate__(self, state) - - def __init__(self, loc, label, expression, arguments): - - super(Call, self).__init__(loc) - self.label = label - self.expression = expression - self.arguments = arguments - - def diff_info(self): - return (Call, self.label, self.expression) - - def execute(self): - - label = self.label - if self.expression: - label = renpy.python.py_eval(label) - - rv = renpy.game.context().call(label, return_site=self.next.name) - next_node(rv) - renpy.game.context().abnormal = True - - if self.arguments: - - args = [ ] - kwargs = renpy.python.RevertableDict() - - for name, expr in self.arguments.arguments: - - value = renpy.python.py_eval(expr) - - if name is None: - args.append(value) - else: - if name in kwargs: - raise Exception("The argument named %s appears twice." % name) - - kwargs[name] = value - - if self.arguments.extrapos: - args.extend(renpy.python.py_eval(self.arguments.extrapos)) - - if self.arguments.extrakw: - for name, value in renpy.python.py_eval(self.arguments.extrakw).items(): - if name in kwargs: - raise Exception("The argument named %s appears twice." % name) - - kwargs[name] = value - - - renpy.store._args = tuple(args) - renpy.store._kwargs = kwargs - - def predict(self): - if self.expression: - return [ ] - else: - return [ renpy.game.script.lookup(self.label) ] - - def scry(self): - rv = Node.scry(self) - rv._next = None - return rv - - -class Return(Node): - - __slots__ = [ 'expression'] - - def __setstate__(self, state): - self.expression = None - Node.__setstate__(self, state) - - def __init__(self, loc, expression): - super(Return, self).__init__(loc) - self.expression = expression - - def diff_info(self): - return (Return, ) - - # We don't care what the next node is. - def chain(self, next): #@ReservedAssignment - self.next = None - return - - def execute(self): - - if self.expression: - renpy.store._return = renpy.python.py_eval(self.expression) - else: - renpy.store._return = None - - renpy.game.context().pop_dynamic() - - next_node(renpy.game.context().lookup_return(pop=True)) - - def predict(self): - site = renpy.game.context().lookup_return(pop=False) - if site: - return [ site ] - else: - return [ ] - - def scry(self): - rv = Node.scry(self) - rv._next = None - return rv - - -class Menu(Node): - - __slots__ = [ - 'items', - 'set', - 'with_', - ] - - def __init__(self, loc, items, set, with_): #@ReservedAssignment - super(Menu, self).__init__(loc) - - self.items = items - self.set = set - self.with_ = with_ - - def diff_info(self): - return (Menu,) - - def get_children(self): - rv = [ ] - - for _label, _condition, block in self.items: - if block: - rv.extend(block) - - return rv - - # Blocks of statements in a choice continue after the menu. - def chain(self, next): #@ReservedAssignment - - self.next = next - - for (_label, _condition, block) in self.items: - if block: - chain_block(block, next) - - def execute(self): - - next_node(self.__next__) - - choices = [ ] - narration = [ ] - - for i, (label, condition, block) in enumerate(self.items): - - if renpy.config.say_menu_text_filter: - label = renpy.config.say_menu_text_filter(label) - - if block is None: - if renpy.config.narrator_menu and label: - narration.append(label) - else: - choices.append((label, condition, None)) - else: - choices.append((label, condition, i)) - next_node(block[0]) - - if narration: - renpy.exports.say(None, "\n".join(narration), interact=False) - - say_menu_with(self.with_, renpy.game.interface.set_transition) - choice = renpy.exports.menu(choices, self.set) - - if choice is not None: - next_node(self.items[choice][2][0]) - else: - next_node(self.__next__) - - - def predict(self): - rv = [ ] - - def predict_with(trans): - renpy.display.predict.displayable(trans(old_widget=None, new_widget=None)) - - say_menu_with(self.with_, predict_with) - - renpy.store.predict_menu() - - for _label, _condition, block in self.items: - if block: - rv.append(block[0]) - - return rv - - def scry(self): - rv = Node.scry(self) - rv._next = None - rv.interacts = True - return rv - - def restructure(self, callback): - for _label, _condition, block in self.items: - if block is not None: - callback(block) - -setattr(Menu, "with", Menu.with_) # E1101 - - -# Goto is considered harmful. So we decided to name it "jump" -# instead. -class Jump(Node): - - __slots__ = [ - 'target', - 'expression', - ] - - def __init__(self, loc, target, expression): - super(Jump, self).__init__(loc) - - self.target = target - self.expression = expression - - def diff_info(self): - return (Jump, self.target, self.expression) - - # We don't care what our next node is. - def chain(self, next): #@ReservedAssignment - self.next = None - return - - def execute(self): - - target = self.target - if self.expression: - target = renpy.python.py_eval(target) - - rv = renpy.game.script.lookup(target) - renpy.game.context().abnormal = True - - next_node(rv) - - def predict(self): - - if self.expression: - return [ ] - else: - return [ renpy.game.script.lookup(self.target) ] - - def scry(self): - rv = Node.scry(self) - if self.expression: - rv._next = None - else: - rv._next = renpy.game.script.lookup(self.target) - - return rv - - -# GNDN -class Pass(Node): - - __slots__ = [ ] - - def diff_info(self): - return (Pass,) - - def execute(self): - next_node(self.__next__) - - -class While(Node): - - __slots__ = [ - 'condition', - 'block', - ] - - def __init__(self, loc, condition, block): - super(While, self).__init__(loc) - - self.condition = condition - self.block = block - - def diff_info(self): - return (While, self.condition) - - def get_children(self): - return self.block - - def chain(self, next): #@ReservedAssignment - self.next = next - chain_block(self.block, self) - - def execute(self): - - next_node(self.__next__) - - if renpy.python.py_eval(self.condition): - next_node(self.block[0]) - - def predict(self): - return [ self.block[0], self.__next__ ] - - def scry(self): - rv = Node.scry(self) - rv._next = None - return rv - - def restructure(self, callback): - callback(self.block) - -class If(Node): - - __slots__ = [ 'entries' ] - - def __init__(self, loc, entries): - """ - @param entries: A list of (condition, block) tuples. - """ - - super(If, self).__init__(loc) - - self.entries = entries - - def diff_info(self): - return (If,) - - def get_children(self): - rv = [ ] - - for _condition, block in self.entries: - rv.extend(block) - - return rv - - def chain(self, next): #@ReservedAssignment - self.next = next - - for _condition, block in self.entries: - chain_block(block, next) - - def execute(self): - - next_node(self.__next__) - - for condition, block in self.entries: - if renpy.python.py_eval(condition): - next_node(block[0]) - return - - def predict(self): - - return [ block[0] for _condition, block in self.entries ] + \ - [ self.__next__ ] - - def scry(self): - rv = Node.scry(self) - rv._next = None - return rv - - def restructure(self, callback): - for _condition, block in self.entries: - callback(block) - -class UserStatement(Node): - - __slots__ = [ - 'line', - 'parsed', - 'block', - 'translatable' ] - - def __setstate__(self, state): - self.block = [ ] - self.translatable = False - Node.__setstate__(self, state) - - def __init__(self, loc, line, block): - - super(UserStatement, self).__init__(loc) - self.line = line - self.block = block - self.parsed = None - - # Do not store the parse quite yet. - _parse_info = renpy.statements.parse(self, self.line, self.block) - - def diff_info(self): - return (UserStatement, self.line) - - def execute(self): - next_node(self.get_next()) - - self.call("execute") - - def predict(self): - self.call("predict") - return [ self.get_next() ] - - def call(self, method, *args, **kwargs): - - parsed = self.parsed - if parsed is None: - parsed = renpy.statements.parse(self, self.line, self.block) - self.parsed = parsed - - renpy.statements.call(method, parsed, *args, **kwargs) - - def get_next(self): - rv = self.call("next") - if rv is not None: - return renpy.game.script.lookup(rv) - else: - return self.__next__ - - def scry(self): - rv = Node.scry(self) - rv._next = self.get_next() - self.call("scry", rv) - return rv - - def get_code(self, dialogue_filter=None): - return self.line - - -class Define(Node): - - __slots__ = [ - 'varname', - 'code', - ] - - def __init__(self, loc, name, expr): - """ - @param name: The name of the image being defined. - - @param expr: An expression yielding a Displayable that is - assigned to the image. - """ - - super(Define, self).__init__(loc) - - self.varname = name - self.code = PyCode(expr, loc=loc, mode='eval') - - def diff_info(self): - return (Define, tuple(self.varname)) - - def execute(self): - - next_node(self.__next__) - - value = renpy.python.py_eval_bytecode(self.code.bytecode) - renpy.dump.definitions.append((self.varname, self.filename, self.linenumber)) - setattr(renpy.store, self.varname, value) - - -class Screen(Node): - - __slots__ = [ - 'screen', - ] - - def __init__(self, loc, screen): - """ - @param name: The name of the image being defined. - - @param expr: An expression yielding a Displayable that is - assigned to the image. - """ - - super(Screen, self).__init__(loc) - - self.screen = screen - - def diff_info(self): - return (Screen, self.screen.name) - - def execute(self): - next_node(self.__next__) - self.screen.define() - renpy.dump.screens.append((self.screen.name, self.filename, self.linenumber)) - - -################################################################################ -# Translations -################################################################################ - -class Translate(Node): - """ - A translation block, produced either by explicit translation statements - or implicit translation blocs. - - If language is None, when executed this transfers control to the translate - statement in the current language, if any, and otherwise runs the block. - If language is not None, causes an error to occur if control reaches this - statement. - - When control normally leaves a translate statement, in any language, it - goes to the end of the translate statement in the None language. - """ - - __slots__ = [ - "identifier", - "language", - "block", - ] - - def __init__(self, loc, identifier, language, block): - super(Translate, self).__init__(loc) - - self.identifier = identifier - self.language = language - self.block = block - - def diff_info(self): - return (Translate, self.identifier, self.language) - - def chain(self, next): #@ReservedAssignment - self.next = next - chain_block(self.block, next) - - def execute(self): - - if self.language is not None: - next_node(self.__next__) - raise Exception("Translation nodes cannot be run directly.") - - next_node(renpy.game.script.translator.lookup_translate(self.identifier)) - renpy.game.context().translate_identifier = self.identifier - - def predict(self): - node = renpy.game.script.translator.lookup_translate(self.identifier) - return [ node ] - - def scry(self): - rv = Scry() - rv._next = renpy.game.script.translator.lookup_translate(self.identifier) - return rv - - def get_children(self): - return self.block - - def restructure(self, callback): - return callback(self.block) - - -class EndTranslate(Node): - """ - A node added implicitly after each translate block. It's responsible for - resetting the translation identifier. - """ - - def __init__(self, loc): - super(EndTranslate, self).__init__(loc) - - def diff_info(self): - return (EndTranslate,) - - def execute(self): - next_node(self.__next__) - renpy.game.context().translate_identifier = None - - -class TranslateString(Node): - """ - A node used for translated strings. - """ - - __slots__ = [ - "language", - "old", - "new" - ] - - def __init__(self, loc, language, old, new): - super(TranslateString, self).__init__(loc) - self.language = language - self.old = old - self.new = new - - def diff_info(self): - return (TranslateString,) - - def execute(self): - next_node(self.__next__) - renpy.translation.add_string_translation(self.language, self.old, self.new) - -class TranslatePython(Node): - - __slots__ = [ - 'language', - 'code', - ] - - def __init__(self, loc, language, python_code): - """ - @param code: A PyCode object. - - @param hide: If True, the code will be executed with its - own local dictionary. - """ - - super(TranslatePython, self).__init__(loc) - - self.language = language - self.code = PyCode(python_code, loc=loc, mode='exec') - - def diff_info(self): - return (TranslatePython, self.code.source) - - def execute(self): - next_node(self.__next__) - - # def early_execute(self): - # renpy.python.create_store(self.store) - # renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store) - - |