@tornado.gen.coroutine
    def interpolate_text(self, text):
        """Evaluate a bunch of (already-looked-up) interpolation markup.
        """
        self.task.tick()
        
        nodls = twcommon.interp.parse(text)
        
        # While trawling through nodls, we may encounter $if/$end
        # nodes. This keeps track of them. Specifically: a 0 value
        # means "within a true conditional"; 1 means "within a
        # false conditional"; 2 means "in an else/elif after a true
        # conditional."
        suppstack = []
        # We suppress output if any value in suppstack is nonzero.
        # It's easiest to track sum(suppstack), so that's what this is.
        suppressed = 0
        
        for nod in nodls:
            if not (isinstance(nod, InterpNode)):
                # String.
                if nod and not suppressed:
                    self.accum_append(nod, raw=True)
                continue
            
            nodkey = nod.classname
            # This switch statement might be better off as a method
            # lookup table. But only if it gets long.

            if nodkey == 'If':
                if suppressed:
                    # Can't get any more suppressed.
                    suppstack.append(0)
                    continue
                try:
                    ifval = yield self.evalobj(nod.expr, evaltype=EVALTYPE_CODE)
                except LookupError: # includes SymbolError
                    ifval = None
                except __HOLE__:
                    ifval = None
                if ifval:
                    suppstack.append(0)
                else:
                    suppstack.append(1)
                    suppressed += 1
                continue
                    
            if nodkey == 'ElIf':
                if len(suppstack) == 0:
                    self.accum_append('[$elif without matching $if]')
                    continue
                if not suppressed:
                    # We follow a successful "if". Suppress now.
                    suppstack[-1] = 2
                    suppressed = sum(suppstack)
                    continue
                if suppstack[-1] == 2:
                    # We had a successful "if" earlier, so no change.
                    continue
                # We follow an unsuccessful "if". Maybe suppress.
                try:
                    ifval = yield self.evalobj(nod.expr, evaltype=EVALTYPE_CODE)
                except LookupError: # includes SymbolError
                    ifval = None
                except AttributeError:
                    ifval = None
                if ifval:
                    suppstack[-1] = 0
                else:
                    suppstack[-1] = 1
                suppressed = sum(suppstack)
                continue
                    
            if nodkey == 'End':
                if len(suppstack) == 0:
                    self.accum_append('[$end without matching $if]')
                    continue
                suppstack.pop()
                suppressed = sum(suppstack)
                continue

            if nodkey == 'Else':
                if len(suppstack) == 0:
                    self.accum_append('[$else without matching $if]')
                    continue
                val = suppstack[-1]
                if val == 1:
                    val = 0
                else:
                    val = 2
                suppstack[-1] = val
                suppressed = sum(suppstack)
                continue

            # The rest of these nodes cannot affect the suppression
            # state.
            if suppressed:
                continue
            
            if nodkey == 'Link':
                # Non-printing element, append directly
                if not nod.external:
                    ackey = EvalPropContext.build_action_key()
                    self.linktargets[ackey] = nod.target
                    self.accum.append( ['link', ackey] )
                else:
                    self.accum.append( ['exlink', nod.target] )
                continue
            
            if nodkey == 'Interpolate':
                try:
                    subres = yield self.evalobj(nod.expr, evaltype=EVALTYPE_CODE)
                except LookupError: # includes SymbolError:
                    continue
                except AttributeError:
                    continue
                # {text} objects have already added their contents to
                # the accum array.
                if not (subres is None or subres == ''):
                    # Anything not a {text} object gets interpolated as
                    # a string.
                    self.accum_append(str(subres), raw=True)
                continue
            
            if nodkey == 'PlayerRef':
                if nod.expr:
                    uid = yield self.evalobj(nod.expr, evaltype=EVALTYPE_CODE)
                    if isinstance(uid, two.execute.PlayerProxy):
                        uid = uid.uid
                    else:
                        uid = ObjectId(uid)
                else:
                    uid = self.uid
                    
                player = yield motor.Op(self.app.mongodb.players.find_one,
                                        {'_id':uid},
                                        {'name':1, 'pronoun':1})
                if not player:
                    self.accum.append('[No such player]')
                    continue
                if nod.key == 'name':
                    self.accum_append(player['name'], raw=True)
                else:
                    self.accum_append(two.grammar.resolve_pronoun(player, nod.key), raw=True)
                continue

            if nodkey == 'OpenBracket':
                self.accum_append('[', raw=True)
                continue

            if nodkey == 'CloseBracket':
                self.accum_append(']', raw=True)
                continue

            # Otherwise...
            # Non-printing element, append directly
            self.accum.append(nod.describe())

        # End of nodls interaction.
        if len(suppstack) > 0:
            self.accum.append('[$if without matching $end]')
            
        # We used raw mode, but if the ctx is in cooked mode, we'll fake
        # in WordNode state at the end.
        if self.cooked and self.textstate is twcommon.gentext.RunOnNode:
            self.textstate = twcommon.gentext.WordNode
dataset/ETHPy150Open erkyrath/tworld/lib/two/evalctx.py/EvalPropContext.interpolate_text